Sticky headers are everywhere. Open any modern web app — Stripe, Notion, GitHub — and the nav bar sticks to the top while you scroll. Feels smooth. Looks professional. On desktop with 1440px of vertical space, it's a win. On mobile, it's a quiet catastrophe.
You just nuked 60px (or 48px, or however tall your nav is) of precious viewport height on a 375px screen. That's 16% of your screen already gone before the user reads a single word of content. You're killing the signal-to-noise ratio you desperately need on mobile.
Here's the hard truth: sticky headers make sense for short pages (your users scroll 2–3 times and jump back to nav). They backfire on long pages where users spend 90% of their time reading and scrolling. Most apps can't decide which is which, so they sticky everything and hope.
The fix isn't "remove sticky headers." It's hide-on-scroll-down, show-on-scroll-up. Users scroll down to read; you hide the nav and give them 60px of content real estate. They scroll up or pause; you show it again. Airbnb, LinkedIn, and most mobile-first platforms do this well. It's a 2-minute JavaScript pattern that converts a UX liability into a feature.
let lastScrollY = 0;
const nav = document.querySelector('header');
window.addEventListener('scroll', () => {
const currentScrollY = window.scrollY;
if (currentScrollY > lastScrollY) {
// scrolling down
nav.classList.add('hidden');
} else {
// scrolling up
nav.classList.remove('hidden');
}
lastScrollY = currentScrollY;
});
Add a smooth CSS transition (transition: transform 0.3s ease) and it feels intentional, not janky.
But here's the catch: sticky headers solve a real problem on long pages — you need to get back to navigation fast. If users have to scroll 500px back to the top to find a link, they rage-quit. Hide-on-scroll is the answer, but you need to pair it with the scroll-margin-top fix so anchor links don't get hidden *behind* the bar when they land.
html {
scroll-behavior: smooth;
scroll-margin-top: 60px; /* match your nav height */
}
header {
transition: transform 0.3s ease;
}
header.hidden {
transform: translateY(-100%);
}
When a user clicks "#pricing" and the page jumps there, the browser respects scroll-margin-top and leaves 60px of breathing room so the heading isn't tucked behind your nav. Without it, the content slides under the header and looks like a bug.
The verdict: sticky headers are fine on desktop. On mobile, hide-on-scroll is the pattern that wins. It gives users the illusion of more screen real estate (they get it back when they stop scrolling), keeps the UX feeling responsive, and doesn't break anchor navigation. Test it on your 3G connection and a 5-inch screen — you'll feel the difference.