Sticky Header React component
A site header that stays out of the way: it slides up while you scroll down and comes back the moment you scroll up, turns compact and frosted after the first few pixels, shows reading progress along its edge, and folds its links into a menu on narrow screens.
About the Sticky Header component
Sticky Header is a site header that stays at the top of the page. At the top it is transparent and roomy, and once you scroll it turns compact and solid with a blurred background. In hide mode it slides away while you scroll down and comes back as soon as you scroll up; in shrink mode it always stays. A thin reading-progress bar can run along its bottom edge.
brand sets the logo, links the navigation links and cta the button on the right. Hovering a link slides a pill behind it. threshold sets how far to scroll before it turns compact (24px by default), showProgress shows the progress bar, and contained makes it follow the nearest scrolling parent instead of the window. When the header is narrower than 640px, the links and the button fold into a menu that opens under the bar.
When to use it
Use Sticky Header for marketing sites, docs and blogs where navigation should always be one scroll-up away but shouldn't cover content while people read.
Use behavior="shrink" for apps and dashboards where the header holds controls people need at all times.
Installation
Add the Sticky Header component to your project with the shadcn CLI. It lands in components/sticky-header.tsx as plain React + Tailwind CSS source you own and can edit.
npx shadcn@latest add @reactframe/sticky-headerOr copy the source by hand and install its dependencies:
npm install motion clsx tailwind-mergeProps
<StickyHeader /> accepts 9 props, all optional.
| Prop | Type | Default |
|---|---|---|
| brand | React.ReactNode | ( <span className="flex items-center gap-2 text-[15px] font-semibold tracking-[-0.01em]">… |
| links | { label: string; href: string }[] | DEFAULT_LINKS |
| cta | { label: string; href: string } | { label: "Get started", href: "#start" } |
| behavior hide: slides away while scrolling down, back on scrolling up. shrink: always visible, gets compact. | "hide" | "shrink" | "hide" |
| threshold Scroll distance (px) after which the header turns compact and solid. | number | 24 |
| showProgress A thin reading-progress bar along the bottom edge. | boolean | true |
| contained Follow the nearest scrollable ancestor instead of the window (e.g. inside a preview box). | boolean | false |
| theme | "dark" | "light" | "dark" |
| className | string | — |
- brandReact.ReactNodeDefault: ( <span className="flex items-center gap-2 text-[15px] font-semibold tracking-[-0.01em]">…
- links{ label: string; href: string }[]Default: DEFAULT_LINKS
- cta{ label: string; href: string }Default: { label: "Get started", href: "#start" }
- behavior
hide: slides away while scrolling down, back on scrolling up. shrink: always visible, gets compact.
"hide" | "shrink"Default: "hide" - threshold
Scroll distance (px) after which the header turns compact and solid.
numberDefault: 24 - showProgress
A thin reading-progress bar along the bottom edge.
booleanDefault: true - contained
Follow the nearest scrollable ancestor instead of the window (e.g. inside a preview box).
booleanDefault: false - theme"dark" | "light"Default: "dark"
- classNamestring
npm dependencies
Installed for you by the shadcn CLI.
Sticky Header FAQ
- When does it hide?
- With behavior="hide" it slides away once you scroll down past the first 120px, and comes back as soon as you scroll up even a little. It never hides while the mobile menu is open.
- Does it work inside a scrolling panel?
- Yes. Set contained and it listens to the nearest scrollable ancestor instead of the window, which is how the preview works.
- What happens on phones?
- When the header itself is narrower than 640px, the links and button fold into a menu that opens below the bar.
- Where does the logo link go?
- To #top, the top of the page. Give an element near the top id="top", or change the href in the component to "/" if the logo should go to your home page.