React Headroom — Build an Auto-Hiding, Sticky Navigation That Just Works
Short summary: react-headroom is a focused React component that detects scroll direction and pins/unpins a header. This article walks through installation, setup, customization, performance and accessibility, with examples and concise code you can paste into your project.
Why use react-headroom for your React navigation?
Auto-hiding headers improve perceived screen real estate and concentrate attention on content while keeping navigation accessible. react-headroom encapsulates the common pattern — detect scroll up/down, then pin or unpin the header — into a tiny, well-tested component so you don't reimplement this logic across apps.
Compared to building a header from scratch, react-headroom offers built-in conventions (class names for states, configurable sensitivity) that let you control behavior with a combination of props and CSS. That reduces bugs, keeps your code readable, and speeds up iteration.
It’s intentionally small and unobtrusive: you can opt out of inline styles, provide your own animations, and use callbacks to tie header visibility to analytics or other UI state. In short: plug-and-style, not lock-in.
Installation & quick setup
Install the package with your preferred package manager. For npm: npm install react-headroom. For yarn: yarn add react-headroom. This installs the core component without opinionated styling so you can integrate it into any design system.
Then import and wrap your header. The simplest usage puts your header inside the <Headroom> component. That’s enough for default hide-on-scroll behavior:
// Simple example
import React from 'react';
import Headroom from 'react-headroom';
export default function AppHeader(){
return (
<Headroom>
<header className="site-header">…</header>
</Headroom>
);
}
Configuration options include props like disableInlineStyles, upTolerance, downTolerance, and callbacks onPin/onUnpin. Use an upTolerance of 5–10 pixels to avoid jitter from micro-scrolls.
- npm/yarn install and import Headroom.
- Wrap your header, disable inline styles if you want full CSS control.
- Adjust tolerances and provide onPin/onUnpin handlers if you need to trigger side effects.
Further reading & downloads: react-headroom installation (npm) • react-headroom GitHub • react-headroom tutorial.
Core concepts: pinning, unpinning, tolerances, and states
react-headroom translates scroll motion into three high-level states: pinned (visible), unpinned (hidden), and unfixed (initial). It emits CSS class names for each state — typically headroom--pinned, headroom--unpinned — which you target in CSS for transitions and transforms.
Tolerances are thresholds that prevent rapid flicker on small scrolls. A downTolerance greater than zero delays hiding until the user scrolls downward more than that many pixels; upTolerance smooths showing the header when the user scrolls up a small distance. Tuning these avoids false positives on touch devices.
Callbacks (onPin, onUnpin, onTop, onNotTop) let you couple header visibility to other UI concerns: toggling a compact logo, pausing animations, or sending analytics. They are useful for controlled header behavior beyond plain CSS.
Custom animations and styling
Prefer CSS-driven animations for smoothness. Target the state classes and transform the header vertically. Example: translateY(-100%) on unpinned, translateY(0) on pinned. Use will-change: transform and GPU-accelerated transforms for better performance.
Example CSS patterns:
/* minimal CSS */
.site-header{position:fixed;top:0;left:0;right:0;transition:transform 220ms ease}
.headroom--unpinned .site-header{transform:translateY(-100%)}
.headroom--pinned .site-header{transform:translateY(0)}
If you want more elaborate transitions (fade + slide), combine opacity with translateZ(0). When you need JS-driven animation, call your animation library (GSAP, Framer Motion) inside the onPin/onUnpin callbacks to coordinate entrance/exit timing.
Examples: basic, sticky, and controlled header
Basic example covers the typical site header that disappears on scroll down and reappears on scroll up. The prior code snippet demonstrates this exact behavior with minimal CSS. It works well for desktop and mobile if you set sensible tolerances.
For a sticky navigation that remains visible at the top but reduces in height (compact header), use the onPin/onUnpin callbacks to toggle a compact class on the header. That class then adjusts padding, font-size, or logo size with a transition.
Controlled header: if you want to programmatically show the header (for example, when a modal opens) create a wrapper component that manages a disabled flag or toggles an override class. You can also combine react-headroom with state derived from route changes so the header is always shown on certain pages.
Integration with React Router, hooks, and server-side rendering
react-headroom is client-side; when using server-side rendering (SSR), render a static header for the initial paint and hydrate client-side. Because react-headroom depends on scroll events, ensure scripts run only on the client by placing Headroom use in components that mount in useEffect or guarded by typeof window !== 'undefined' checks.
With React Router, place Headroom at a level where you want the behavior to persist across routes (e.g., inside App layout). If you need per-route header variants, wrap each route’s header in its own Headroom instance or add route-aware logic in callbacks.
Hooks: while react-headroom is a component, you can control behavior with hooks by wrapping it. For example, use a custom hook that exposes a ref and visibility state. Provide that state to Headroom callbacks to synchronize other UI elements.
Performance, mobile quirks, and accessibility
Performance tips: avoid heavy work inside scroll handlers. react-headroom debounces internally via tolerances; prefer CSS transitions and transforms (GPU-accelerated) rather than changing layout-affecting properties like height. Keep your header DOM shallow and avoid expensive React renders triggered by scroll.
Mobile devices have touch momentum and elastic scroll. Tune downTolerance (10–20px) and test on physical devices. On iOS Safari, position:fixed can be quirky; prefer transform-based hide/show to reduce layout churn and ensure consistent behavior.
Accessibility: maintain focus order and visibility. When the header hides, don't remove it from the accessibility tree — simply visually hide it with transforms so keyboard users and screen readers can still reach navigation if needed. Ensure contrast and hit targets meet a11y guidelines.
Troubleshooting & advanced tips
If the header flickers, increase tolerances. If it fails to hide, ensure no parent element is capturing scroll events (overflow on body vs inner container). For single-page apps where you programmatically change scroll, call Headroom callbacks or update state so header responds to non-user scrolls.
To animate other components when header visibility changes, use the onPin/onUnpin callbacks to toggle classes or trigger an animation library. This keeps the header component simple and delegates visual polish to CSS or animation tools.
If you need a bit more control, write a tiny wrapper that forwards props to Headroom and exposes a ref with a forcePin/forceUnpin API by manipulating a class. That pattern is helpful for onboarding flows or when modals need the header always visible.
Top user questions (PAA-inspired)
These are commonly asked queries you’ll encounter when implementing react-headroom:
- How do I install react-headroom?
- How to hide header on scroll in React?
- How to customize react-headroom animations?
- Does react-headroom support hooks and SSR?
- How can I combine react-headroom with React Router?
- What tolerances should I use for mobile?
- How to stop header flicker when using transforms?
Below are the three most relevant questions answered succinctly for quick reference.
FAQ
How do I install and set up react-headroom?
Install with npm or yarn: npm i react-headroom or yarn add react-headroom. Import Headroom from 'react-headroom' and wrap your header element. Optionally set disableInlineStyles to true and style your header via CSS using the provided state class names.
Use sensible tolerances to avoid flicker: try downTolerance={10} and upTolerance={5}, then tweak on devices you support. Example starter code appears above for a minimal implementation.
Reference links: npm package page (react-headroom installation), GitHub repo (react-headroom GitHub), and a practical tutorial (react-headroom tutorial).
How can I customize animations and behavior for the auto-hiding header?
Prefer CSS transitions on transform for best performance. Target the class names that react-headroom applies (headroom--pinned, headroom--unpinned) and animate transform/opacity. Use will-change: transform to hint the browser.
For JS-driven or coordinated animations, use the onPin and onUnpin callbacks to trigger animation libraries (GSAP, Framer Motion). Keep scroll handling minimal; let CSS do the heavy lifting for smoothness.
If you want to disable inline styles from the component, pass disableInlineStyles and provide your own CSS entirely. This gives full control over transition timings, easing, and responsive behavior.
Will react-headroom work with React Router and hooks?
Yes. Place Headroom at the level where you want persistent or per-route behavior. If you need the header to respond to route changes (always visible on some routes), toggle classes or state inside route-level components and use Headroom callbacks when necessary.
For hook-friendly control, wrap Headroom with a small component that exposes a ref or state, then use your hooks to update that wrapper. Because react-headroom attaches to the window scroll, ensure any SSR rendering guards are in place so you only run client-side scroll logic.
Test on real devices to verify touch momentum and bounce behavior, and tune tolerances accordingly.
Expanded Semantic Core (keyword clusters)
Primary cluster (high-intent):
- react-headroom
- React auto-hiding header
- React hide on scroll
- react-headroom installation
- react-headroom tutorial
Secondary cluster (feature & usage):
- react-headroom setup
- React sticky navigation
- react-headroom example
- React scroll header
- react-headroom customization
Clarifying / long-tail & LSI phrases:
- React header library
- React scroll detection
- react-headroom animations
- React hide header on scroll tutorial
- how to use react-headroom with hooks
- react-headroom GitHub
- react-headroom npm
Use these groups to vary anchor text and H2/H3 targets; incorporate natural language questions for voice search like: "How do I make my header hide on scroll in React?" or "React Headroom tutorial install and customize".