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
debouncemechanism ensures that rapid scrolling doesn't overwhelm the logic.requestAnimationFrameis used to batch DOM updates efficiently.
Adaptive Behavior:
The
scrollArraycollects 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
scrollTimerclears thescrollArrayafter 1 second of inactivity, ensuring no stale data affects future decisions.
Minimal CSS Changes:
By toggling only the
transformproperty, we avoid expensive layout recalculations, making the animation smooth.
How It Works
The
on:scrollevent on the<svelte:window>component captures the scroll offset.The
handleScrollfunction 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!