webdevpuneet.com

Sticky Header — Free HTML CSS JS Snippet

Sticky Header · Navigation · Plain HTML, CSS & JS · Live preview

CategoryNavigation

Copy & paste

Source Code

<div class="page">
  <header class="header" id="header">
    <div class="header-inner">
      <a href="#" class="logo">
        <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 2 7 12 22 22 7 12 2"/></svg>
        <span>Acme</span>
      </a>

      <nav class="nav" id="nav">
        <a href="#" class="nav-link">Product</a>
        <a href="#" class="nav-link">Pricing</a>
        <a href="#" class="nav-link">Docs</a>
        <a href="#" class="nav-link">Blog</a>
      </nav>

      <div class="header-cta">
        <a href="#" class="btn-ghost">Sign in</a>
        <a href="#" class="btn-solid">Get started</a>
      </div>

      <button class="burger" id="burger" onclick="toggleMobileNav()" aria-label="Menu" aria-expanded="false">
        <span></span><span></span><span></span>
      </button>
    </div>

    <div class="scroll-bar" id="scroll-bar"></div>
  </header>

  <div class="hero-section">
    <h1>Scroll down to see<br>the sticky header effect</h1>
    <p>The header shrinks, gains a background blur, and a scroll progress bar appears when you scroll past the top.</p>
  </div>

  <div class="content-blocks">
    <div class="block">Section One — keep scrolling…</div>
    <div class="block">Section Two</div>
    <div class="block">Section Three</div>
    <div class="block">Section Four</div>
  </div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

position: fixed with .scrolled class toggled at scrollY > 20
CSS transitions handle all style changes — one class toggle triggers all
backdrop-filter: blur(12px) + rgba(0,0,0,0.9) frosted glass effect
-webkit-backdrop-filter: Safari prefix for cross-browser blur support
Scroll progress bar: scrollY/(scrollHeight-innerHeight) × 100% width
passive: true scroll listener — non-blocking, runs on compositor thread
padding: 16px → 10px transition on scroll for shrink effect
Responsive: nav hides on mobile, hamburger shows, mobile dropdown on toggle

About this UI Snippet

Sticky Header — Scroll-Triggered Blur, Shrink Animation, Progress Bar & Responsive Mobile Nav

Screenshot of the Sticky Header snippet rendered live

A sticky header that changes its appearance on scroll is one of the most universally used navigation patterns on the web. The header starts transparent and full-height at the top of the page, then transitions to a frosted glass appearance with reduced padding as the user scrolls. This snippet implements the complete sticky header pattern: position: fixed, scroll-triggered .scrolled class toggling, backdrop-filter blur, box-shadow transition, padding reduction, a scroll progress bar, and a mobile hamburger navigation.

The scroll event handler

A passive scroll event listener fires on every scroll event. It reads window.scrollY and toggles the .scrolled class on the header when scrollY > 20 (past the initial hero area). The passive: true option tells the browser this listener never calls preventDefault(), allowing it to run on a separate thread without blocking smooth scrolling.

The CSS transition approach

All header style changes are handled by CSS transitions on the .scrolled class — no JavaScript style manipulation. transition: background 0.25s, box-shadow 0.25s, padding 0.25s, backdrop-filter 0.25s on .header animates every property simultaneously when .scrolled is added or removed. The JavaScript only adds or removes one class.

The frosted glass blur

backdrop-filter: blur(12px) creates the frosted glass effect. background: rgba(255,255,255,0.9) provides the semi-transparent tint. -webkit-backdrop-filter is the Safari prefix. The header must NOT be fully opaque — the blurred content behind must show through for the effect to work.

The scroll progress bar

The built-in scroll progress bar uses scrollY / (scrollHeight - innerHeight) × 100 for the scroll percentage. The progress bar uses this percentage as its width. opacity transitions from 0 to 1 when .scrolled is applied, keeping the bar hidden at the top of the page.

Mobile hamburger navigation

On screens under 640px, the nav and CTA buttons hide and the hamburger button appears. Clicking it toggles .mobile-open on the nav (which switches it to an absolute dropdown panel) and .open on the burger (which animates the three spans into an ×). The mobile nav slides in from below the header.

Preventing layout shift

When the header transitions from absolute to fixed (or from tall to short), content can jump because the document flow changes. Prevent this by wrapping the page content in a container with padding-top equal to the header's maximum height. This reserves space for the header at all scroll positions without layout recalculation.

Step by step

How to Use

  1. 1
    Scroll down to see the header transformPast 20px of scroll the header gains a frosted glass background, box-shadow, and reduced padding. The scroll progress bar appears and grows as you scroll further down the page.
  2. 2
    Resize to mobile to test the hamburger navAt under 640px wide, the nav links and CTA buttons hide and a hamburger button appears. Click it to toggle the mobile dropdown nav. The three lines animate to an × when open.
  3. 3
    Update the logo and nav linksReplace the SVG icon and "Acme" text in .logo. Edit the four .nav-link anchor elements with your page sections and routes. Update .btn-solid and .btn-ghost href values.
  4. 4
    Change the scroll trigger thresholdUpdate scrollY > 20 in the JavaScript to any pixel value. Use > 0 to trigger immediately on any scroll, or > 100 to wait until the user has scrolled past the full hero area.
  5. 5
    Change the frosted glass colourUpdate rgba(255,255,255,0.9) on .header.scrolled for a coloured tint — e.g. rgba(15,23,42,0.8) for a dark header. Also update nav-link, logo, and button colours to maintain contrast on the new background.
  6. 6
    Export in your formatClick "HTML" for a standalone file, "JSX" for a React component using useEffect for the scroll listener, or "Tailwind" for a React + Tailwind CSS version.

Real-world uses

Common Use Cases

SaaS and product landing page navigation
The frosted glass sticky header is the standard navigation pattern for modern SaaS landing pages. It keeps the nav accessible throughout a long scroll while the blurred glass gives it a premium look without obscuring page content.
Blog and content site reading progress indicator
The scroll progress bar is particularly valuable on long-form content pages — articles, documentation, tutorials. It communicates reading progress at a glance without requiring the user to estimate their position in the document.
Marketing and campaign landing pages
Marketing pages need headers that transition from hero overlay to sticky nav as users read down. The transparent-to-frosted-glass transition avoids covering hero imagery while providing a readable nav during scroll.
Responsive navigation with mobile hamburger menu
The snippet includes a complete mobile nav: hamburger button that animates to ×, dropdown panel, and proper aria-expanded attributes. Test the full mobile experience by resizing the preview to under 640px.
Study the CSS class-toggle approach to scroll animations
This snippet demonstrates the cleanest approach to scroll-triggered animations: JavaScript adds/removes one class, CSS transitions handle everything else. No inline style changes, no JavaScript animation — all visual logic lives in CSS.
E-commerce and documentation site persistent nav
Documentation sites and e-commerce sites need headers visible at every scroll position. The sticky header with shrink effect is space-efficient — it takes less vertical space after scroll, giving more room to the content below.

Got questions?

Frequently Asked Questions

The passive: true option tells the browser that this scroll listener will never call e.preventDefault(). This allows the browser to continue smooth scrolling on a separate thread (the compositor) without waiting for the JavaScript to finish. Without passive: true, the browser must wait for the scroll handler to complete before advancing the scroll position, which can cause jank on slow devices. Always add passive: true to scroll, touchstart, and touchmove listeners that do not prevent default.

For a dark hero, start the header with no background (remove the default white background). Set nav-link, logo, and button text colours to white or light grey. When .scrolled applies, the dark rgba background and light text remain. Add a CSS transition for color on .nav-link and .logo so the text colour also transitions smoothly when the header changes state: .header.scrolled .nav-link { color: #64748b; }.

For a multi-page site, add .active to the link matching the current URL: const current = window.location.pathname; document.querySelectorAll(".nav-link").forEach(link => { link.classList.toggle("active", link.getAttribute("href") === current); }). For smooth scroll single-page navigation, use IntersectionObserver to add .active to the link corresponding to the currently visible section. Style .active: color: #6366f1; font-weight: 600.

Click "JSX" to download. The header component needs "use client" since it uses a scroll event listener. In a useEffect: window.addEventListener("scroll", handler, { passive: true }); return () => window.removeEventListener("scroll", handler). Manage scrolled state with useState(false). In Next.js, use this as a client component inside your app/layout.tsx server component: import Header from "@/components/Header"; export default function Layout({ children }) { return <><Header />{children}</>; }.

Yes. While the Sticky Header snippet gives you one pattern to copy, the free Responsive Navbar Builder at webdevpuneet.com/navbar-builder/ designs a whole navigation bar: logo, links and dropdown menus, a mobile hamburger menu (dropdown panel, slide-in drawer or full screen) and a scroll effect (sticky, shrink, hide on scroll or transparent). It has six presets, a live preview that runs the real code, and exports HTML + CSS + vanilla JS, React, Tailwind, Vue 3 or Angular — or you can click Fork & Edit to keep editing it in My Code.