<div class="inner">
<h2>Scroll me</h2>
<p>
Code based on CSS-tricks article "<a href="https://css-tricks.com/styling-based-on-scroll-position/">Styling Based on Scroll Position</a>".
</p>
<p>
Using css var to dynamically change css values. In this case the hue inside hsl() is changed.
</p>
<p>
Other fun properties to use this on are opacity and transforms. For example used as an alternative method for parallax.
</p>
</div>
:root {
--scrollpos: 0;
}
body {
min-height: 600vh;
background-color: hsl(calc(var(--scrollpos) * 3.6), 100%, 50%);
}
.inner {
position: fixed;
}
View Compiled
// The debounce function receives our function as a parameter
const debounce = (fn) => {
// This holds the requestAnimationFrame reference, so we can cancel it if we wish
let frame;
// The debounce function returns a new function that can receive a variable number of arguments
return (...params) => {
// If the frame variable has been defined, clear it now, and queue for next frame
if (frame) {
cancelAnimationFrame(frame);
}
// Queue our function call for the next frame
frame = requestAnimationFrame(() => {
// Call our function and pass any params we received
fn(...params);
});
}
};
// Reads out the scroll position and stores it in the data attribute
// so we can use it in our stylesheets
const storeScroll = () => {
let perc = window.scrollY / (document.body.clientHeight - window.innerHeight) * 100;
document.documentElement.setAttribute('style', `--scrollpos: ${perc}`);
}
// Listen for new scroll events, here we debounce our `storeScroll` function
document.addEventListener('scroll', debounce(storeScroll), { passive: true });
// Update scroll position for first time
storeScroll();
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.