The strip above everything is the most contested real estate on a page. It carries the header, and above the header it carries whatever the business decided this week: an announcement, a sale, a cookie notice, an upgrade prompt. Each one pushes the actual content further down, and each one is added by someone who is not counting.
Here are the components, and then the rules that stop the top of the page becoming a stack.
The header
Header 3, Header 2 and Header 1 by Efferd are the three shapes most sites need, and Header by tommyjepsen is the plain one. The navbar guide covers navigation itself in depth; this is about the strip's behaviour rather than its links.
Three decisions carry it. Sticky or not: sticky costs vertical space on every screen and earns it only when navigation is used mid-page. What happens on scroll: a header that shrinks or gains a border on scroll needs a one-pixel sentinel and an IntersectionObserver, not a scroll handler running every frame. And whether it hides on scroll down, which saves space and is disorienting if the threshold is too small.
The announcement bar
Banner by Efferd, banner by mdafsarx and Animated Banner by dqnamo are the shapes. Upgrade Banner by victorwelander is the in-product prompt version.
Four rules, and the first one is the one nobody applies.
One at a time. Cookie notice, announcement, upgrade prompt and beta banner all stacked is four strips before the page starts. Pick a slot and let one occupant win it.
Dismissible, and it stays dismissed. A banner that returns on the next page load is worse than no banner, because the reader learns that dismissing does nothing. Persist it, and key the storage to the message so a new announcement can appear again.
It moves the page, so reserve the space. A banner injected after hydration pushes everything down and is a layout shift straight into the Core Web Vitals metric. Render it server-side or reserve its height.
The close button is a real button with a name. "Dismiss announcement", not a bare glyph, and it needs a focus style.
What belongs up there at all
A short test that resolves most arguments: does this need to be seen on every page, and would the reader be worse off if it were not?
An outage notice passes. A shipping cut-off passes. A permanent "new feature" banner does not, because after two days it is furniture nobody reads and it costs vertical space on every screen forever. Give announcements an expiry date at the moment they are written.
The upgrade prompt is the awkward one. It is not an announcement, it is an ad in your own product, and the top strip is the most expensive place to put one. In-context prompts, at the moment a limit is reached, do the same job without taxing every page.
The sticky stack problem
Once a header is sticky and a banner sits above it, mobile has a real problem: two strips can eat a third of a small viewport before any content shows.
The workable arrangement is one sticky element and one scroll-away element. The banner scrolls away and does not come back; the header sticks. And if the page also has a sticky filter bar or a bottom action bar, that is three strips competing, which is the point at which the layout needs a decision rather than another position: sticky.
Worth remembering: 100vh does not account for mobile browser chrome. Use 100dvh for anything measuring the visible viewport around these strips.
Where else to look
The honest list, because the answer is not always us:
| Source | Best for | Trade-off |
|---|---|---|
| shadcn/ui | Alert, Button and NavigationMenu as the parts | No banner, no assembled header |
CSS position: sticky | The behaviour itself, with no JavaScript | The scroll-state flag still needs an observer |
| 21st | Assembled headers, announcement bars and upgrade prompts | Quality varies by author, so preview before you take it |
Taking one
Every component page has a live preview and the code. Installing goes through the shadcn CLI against our registry:
That key comes from your 21st account, and installs require a membership. Set API_KEY_21ST once in your shell and the command works for anything in the catalogue. The 21st MCP covers the same ground without leaving the editor: ask Claude, Cursor or Codex for a header, get the previews inline, and let the agent write the file.
Frequently asked
- How many banners can a page have above the header?
- One. Cookie notice, announcement, upgrade prompt and beta banner stacked is four strips before the content starts, and on a phone that can be a third of the viewport. Pick a slot and let one occupant win it, with an expiry date decided when the message is written.
- Why does a banner cause layout shift?
- Because it is usually injected after hydration, which pushes everything below it down. That lands directly in the Cumulative Layout Shift metric. Render it server-side, or reserve its height so the space exists before the content arrives.
- Should a dismissed banner stay dismissed?
- Yes, and this is the rule most often broken. A banner that returns on the next page load teaches the reader that dismissing does nothing. Persist the dismissal, keyed to the message itself so a genuinely new announcement can appear again.
- How do you make a header react to scroll efficiently?
- Watch a one-pixel sentinel element at the top of the page with an IntersectionObserver, which fires once per crossing. A scroll handler runs on every frame during the most performance-sensitive moment there is, and it is the usual reason a sticky header feels heavy on a phone.







