Skip to content

Instantly share code, notes, and snippets.

@cferdinandi
Created May 7, 2025 03:16
Show Gist options
  • Save cferdinandi/41af2c9391809df6d0ebed34ae55694c to your computer and use it in GitHub Desktop.
Save cferdinandi/41af2c9391809df6d0ebed34ae55694c to your computer and use it in GitHub Desktop.
Watch the tutorial: https://youtu.be/Kws6l0Rp1Yg
<!DOCTYPE html>
<html>
<head>
<title>Smooth Scroll</title>
<style type="text/css">
body {
margin: 1em auto;
max-width: 30em;
width: 88%;
}
html {
scroll-behavior: smooth;
}
@media screen and (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
}
</style>
</head>
<body>
<h1>Smooth Scroll</h1>
<p id="top">
<a href="#bazinga">Go to the middle</a><br>
<a href="#1@#%^-bottom">Go to the bottom</a>
</p>
<p>
.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>
.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>
.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.
</p>
<p id="bazinga"><a href="#1@#%^-bottom">Go to the bottom</a></p>
<p>
.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>
.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>
.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.
.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>
.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>
.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.
</p>
<p id="1@#%^-bottom"><a href="#">Go back to the top</a></p>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>Marquee</title>
<style type="text/css">
body {
margin: 1em auto;
max-width: 30em;
width: 88%;
}
#marquee > div {
font-size: 3em;
}
</style>
</head>
<body>
<h1>Marquee</h1>
<div id="marquee">
<div hidden>πŸ‘‹</div>
<div hidden>πŸŽ‰</div>
<div hidden>🧠</div>
<div>πŸ™ˆ</div>
</div>
<script>
let marquee = document.querySelector('#marquee');
let speed = 3000;
setInterval(function () {
// Get the current and next elements
let current = marquee.querySelector('& > *:not([hidden])');
let next = current.nextElementSibling ?? marquee.children[0];
// Swap visibility
current.setAttribute('hidden', '');
next.removeAttribute('hidden');
}, speed);
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>Prefers Reduced Motion with JS</title>
<style type="text/css">
body {
margin: 1em auto;
max-width: 30em;
width: 88%;
}
html {
scroll-behavior: smooth;
}
@media screen and (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
}
</style>
</head>
<body>
<h1>Prefers Reduced Motion with JS</h1>
<script>
let prefersReducedMotion = window.matchMedia('(prefers-reduced-motion)');
console.log('prefers less motion', prefersReducedMotion.matches);
prefersReducedMotion.addEventListener('change', function (event) {
// The new value of the matched media
console.log('what about now?', event.matches);
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>Marquee - Prefers Reduced Motion</title>
<style type="text/css">
body {
margin: 1em auto;
max-width: 30em;
width: 88%;
}
#marquee > div {
font-size: 3em;
}
</style>
</head>
<body>
<h1>Marquee - Prefers Reduced Motion</h1>
<div id="marquee">
<div hidden="">πŸ‘‹</div>
<div hidden="">πŸŽ‰</div>
<div hidden="">🧠</div>
<div>πŸ™ˆ</div>
</div>
<script>
let marquee = document.querySelector('#marquee');
let prefersReducedMotion = window.matchMedia('(prefers-reduced-motion)');
let speed = prefersReducedMotion.matches ? 10_000 : 3000;
let timer;
function start () {
timer = setInterval(function () {
// Get the current and next elements
let current = marquee.querySelector('& > *:not([hidden])');
let next = current.nextElementSibling ?? marquee.children[0];
// Swap visibility
current.setAttribute('hidden', '');
next.removeAttribute('hidden');
}, speed);
}
prefersReducedMotion.addEventListener('change', function (event) {
clearInterval(timer);
speed = event.matches ? 10_000 : 3000;
start();
});
start();
</script>
</body>
</html>
import { useEffect, useState } from 'react';
/**
* A hook to check if user has prefers-reduce-motion enabled
* Automatically updates when the user updates their preferences
*/
export function usePrefersReducedMotion () {
// If true, user prefers reduced motion
const [matches, setMatches] = useState(false);
// On render, sets user preference and listens for changes
useEffect(() => {
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion)');
setMatches(prefersReducedMotion.matches);
// Callback function for updating user preference
function updateMatches (event) {
setMatches(event.matches);
}
prefersReducedMotion.addEventListener('change', updateMatches);
return () => {
prefersReducedMotion.removeEventListener('change', updateMatches);
};
}, []);
return { @ };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment