Smart Scroll-Aware Header Navigation Library – Peek.js

Category: Javascript , Menu & Navigation | February 18, 2026
Authoradesignl
Last UpdateFebruary 18, 2026
LicenseMIT
Views0 views
Smart Scroll-Aware Header Navigation Library – Peek.js

Peek is a tiny, dependency-free JavaScript library that hides your fixed header navwhen a user scrolls down and reveals it when they scroll back up.

It reads scroll intent rather than raw scroll position, so the header only transitions after the user has moved a meaningful number of pixels in a given direction.

The result is a cleaner browsing experience on content-heavy pages. The header gets out of the way on the way down, and comes back the moment the user signals they want to navigate.

Features:

  • Scroll intent detection: A configurable tolerance threshold filters out micro-movements and accidental jitter before any state change fires.
  • requestAnimationFrame scheduling: All DOM updates run inside rAF calls.
  • Passive scroll listeners: The scroll event is attached with { passive: true }. This unlocks browser-level scroll optimizations and avoids blocking the main thread.
  • CSS class-based API: Peek applies and removes classes on your header element. Your CSS owns the animation logic entirely.
  • Configurable offset and tolerance: You control exactly when and how sensitively the header responds to scroll changes.

See It In Action:

Use Cases:

  • Long-form content sites: On articles or documentation pages, the fixed header can cover a significant portion of the viewport. Peek hides it as soon as the user starts reading, then brings it back the moment they scroll up to navigate.
  • Mobile-first interfaces: Screen real estate is at a premium on mobile. Peek’s mobile-only initialization pattern lets you apply the behavior exclusively on small viewports and tear it down on larger ones.
  • E-commerce product pages: Product detail pages often have tall layouts. Hiding the header on scroll down keeps the product imagery and copy in full view, and the cart/nav reappear as soon as the user scrolls up.

How To Use It:

1. Download peek.js and include it before your closing </body> tag:

<link rel="stylesheet" href="src/peek.css" />
<script src="src/peek.js"></script>

2. Add the ‘main-header’ class to your header navigation.

<header class="main-header">
  Your Header Nav Here
</header>

3. Initialize peek.js with default opitons.

const peek = Peek('.main-header');

4. Config the behavitor of peek.js with the following confiugration options.

  • offset (Number): The scroll distance in pixels from the top of the page before Peek begins evaluating pin/unpin behavior. The header stays pinned for any scroll position at or below this value. Default: 100.
  • tolerance (Number): The minimum number of pixels the user must scroll in a single direction before Peek changes the pin state. This filters out accidental micro-scrolls and touch jitter. Default: 5.
  • classes.pinned (String): The class applied to the header element when it should be visible (i.e., when the user scrolls up or is at the top of the page). Default: 'main-header--pinned'.
  • classes.unpinned (String): The class applied to the header element when it should be hidden (i.e., when the user scrolls down past the offset). Default: 'main-header--unpinned'.
  • classes.top (String): The class applied when scrollY is at or below the offset value. Use this to style the header differently when sitting above the page content — for example, a transparent background over a hero image. Default: 'main-header--top'.
  • classes.notTop (String): The class applied when scrollY exceeds the offset value. Use this to add a background color or drop shadow once the user has scrolled into the page body. Default: 'main-header--not-top'.
const peek = Peek('.main-header',{
  offset: 100,
  tolerance: 5,
  classes: {
    pinned: 'main-header--pinned',
    unpinned: 'main-header--unpinned',
    top: 'main-header--top',
    notTop: 'main-header--not-top',
  },
});

5. Removes the scroll event listener and strips all Peek-managed classes from the header element. Call this when you need to cleanly tear down the behavior. For example, before a framework route change or on resize when swapping between mobile and desktop modes.

peek.destroy();

6. Here is an example on how to create a smart, mobile-only header nav.

let peek;
function initPeekOnMobile() {
  if (window.innerWidth < 768 && !peek) {
    // Viewport is mobile-sized and Peek is not yet running — initialize it
    peek = Peek('.main-header');
  } else if (window.innerWidth >= 768 && peek) {
    // Viewport has grown to desktop size — tear down to keep header always visible
    peek.destroy();
    peek = null;
  }
}
initPeekOnMobile();
// Re-evaluate on every resize (consider debouncing for production)
window.addEventListener('resize', initPeekOnMobile);

Alternatives:

FAQs:

Q: The header flickers between pinned and unpinned when I scroll slowly. How do I fix it?
A: Increase the tolerance value. Start at 10 and tune from there.

Q: Can I use Peek with a CSS framework like Tailwind or Bootstrap?
A: Yes. Peek applies classes to your element. It has no opinion on what those classes do or where they come from.

Q: The header stays hidden after a programmatic scroll (e.g., scrollTo). Is this a known issue?
A: Programmatic scrolls fire the native scroll event, so Peek should respond normally. The most common cause of this symptom is a scrollDelta of 0 on the first frame after the scroll completes, which does not meet the tolerance threshold and leaves the state unchanged. Calling peek.destroy() and re-initializing after the programmatic scroll is a reliable workaround.

Q: Is Peek suitable for headers inside a scrolling container rather than the main window?
A: In its current form, no. Peek listens exclusively to the window scroll event. If your scrollable area is a div with overflow: auto, you would need to modify the source to attach the listener to that element and read its scrollTop property in place of window.pageYOffset.

You Might Be Interested In:


Leave a Reply