Creating a Smart Header Visibility Toggle with Svelte
How a website's header behaves during scrolling can significantly affect user experience. Here's a simple yet effective way to hide the header when scrolling down and reveal it when scrolling up, implemented in Svelte.
Johan
2024 | 12 | 23
Creating a seamless and responsive web experience often comes down to the finer details. One subtle yet effective touch is dynamically hiding and showing the header based on user scroll behavior. This blog post explores how you can achieve this smart functionality using Svelte.
The idea
The goal is to dynamically hide the header when the user scrolls down and reveal it when scrolling up. This makes the interface less intrusive while still keeping the header easily accessible.
The code
Here’s the complete Svelte component that handles the header visibility toggle:
<script>
let scrollArray = [];
let style = 'transform: translateY(0);';
let ticking = false;
let debounce = false;
let debounceTimer;
let scrollTimer;
const handleScroll = (scrollOffset) => {
clearTimeout(scrollTimer);
scrollTimer = setTimeout(() => (scrollArray = []), 1000);
scrollArray.push(scrollOffset);
console.log(scrollArray);
if (scrollArray.length === 5) {
const stopValue = scrollArray[scrollArray.length - 1];
const startValue = scrollArray[0];
if (Math.abs(stopValue - startValue) > 100) {
style =
stopValue > startValue ? 'transform: translateY(-100%);' : 'transform: translateY(0);';
}
scrollArray = [];
}
};
const hideOrShowHeader = (event) => {
const scrollOffset = event.target.defaultView.pageYOffset;
if (scrollOffset < 200) {
style = 'transform: translateY(0);';
scrollArray = [];
ticking = false;
return;
}
if (debounce) return;
debounce = true;
if (!ticking) {
requestAnimationFrame(() => {
handleScroll(scrollOffset);
ticking = false;
});
ticking = true;
}
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
debounce = false;
}, 200);
};
</script>
<svelte:window on:scroll={(event) => hideOrShowHeader(event)} />
Benefits of this approach
Efficient Handling with Debouncing and Throttling:
The
debounce
mechanism ensures that rapid scrolling doesn't overwhelm the logic.requestAnimationFrame
is used to batch DOM updates efficiently.
Adaptive Behavior:
The
scrollArray
collects scroll positions over time, allowing the header's visibility to adapt based on the user's scrolling behavior. For example, it checks if the scroll offset changes significantly over five recorded events.
Reset Logic:
A
scrollTimer
clears thescrollArray
after 1 second of inactivity, ensuring no stale data affects future decisions.
Minimal CSS Changes:
By toggling only the
transform
property, we avoid expensive layout recalculations, making the animation smooth.
How It Works
The
on:scroll
event on the<svelte:window>
component captures the scroll offset.The
handleScroll
function calculates whether the user is scrolling up or down.The header’s position is updated dynamically with inline styles.
With this setup, you’ll have a responsive and intuitive header experience that enhances your website's usability. Let me know how you’d use or improve this solution!