How to build an accessible LargeTitleHeader in React
The component owns the scroll container, so the sticky bar and the scroll timeline cannot be broken by surrounding markup. The title is a real h1–h3 in normal flow, so heading order and document outline are unaffected; the copy mirrored into the sticky bar is aria-hidden so screen readers announce the title exactly once. The collapse is a CSS scroll-driven animation with no client JavaScript, so the header is complete in server-rendered HTML and nothing depends on hydration. Where animation-timeline is unsupported the mirror stays hidden and the header degrades to a sticky bar above a heading — no content is lost. Under prefers-reduced-motion the reveal snaps with steps(1, jump-end) instead of interpolating. The bar clears the coarse-pointer target floor and pads for the top safe-area inset.
When to use a LargeTitleHeader
- A scrolling screen that should keep its title reachable after the heading scrolls away
- Mobile and tablet layouts following the platform convention of a large title that collapses
- Any page where a persistent back control or actions must stay pinned while content scrolls
When not to use it
- A site-wide navigation bar with links and a brand — use Header
- An application chrome header spanning a sidebar layout — use ShellHeader
- A screen whose scroll container is owned by the app shell or router — this component owns its own
Accessibility
Role heading, verified at WCAG 2.2-AA.
Common mistakes
Avoid: Rendering it inside a parent with no resolved height
Prefer: Give the parent a height (a grid/flex track, a dvh value, or 100% of a sized ancestor)
The component is the scroll container at block-size 100%; with an auto-height parent it never scrolls, so the title never collapses
Avoid: Passing the page heading again as the first child of the content below
Prefer: Let the component own the heading
The component already renders a real h1–h3; repeating it duplicates the heading in the accessibility tree
Example
<LargeTitleHeader title="Library">
<List>
<ListItem>Recently Added</ListItem>
<ListItem>Artists</ListItem>
<ListItem>Albums</ListItem>
</List>
</LargeTitleHeader>