All hooks / Elements
useIsStuck
Whether a position: sticky element is currently stuck to the top of the viewport. Returns a callback ref for the sticky element.
Reads the element's own CSS top and watches it with an IntersectionObserver, so it costs nothing while scrolling and needs no extra markup. false on the server and until the element is measured.
Import
import { useIsStuck } from '@vincent.ri/react-tils'
// or only this hook
import { useIsStuck } from '@vincent.ri/react-tils/useIsStuck'Usage
const [ref, stuck] = useIsStuck<HTMLElement>()
return (
<header ref={ref} style={{ position: 'sticky', top: 0 }} className={stuck ? 'shadow' : ''}>
…
</header>
)Live demo
The status bar at the top gets a shadow once it sticks.
When to use it
Adding a shadow or border to a sticky header only once it sticks, or shrinking a sticky toolbar.
When not to
The sticky element sticks inside a scroll container rather than the page; this watches the viewport. If you only need the element to stick, CSS position: sticky alone is enough.
API
function useIsStuck<T extends Element = HTMLElement>(): [(element: T | null) => void, boolean]Returns [ref, stuck]. Pass ref to the sticky element.
Browser support
| Uses | Chrome | Edge | Firefox | Safari | Chrome Android | Safari iOS |
|---|---|---|---|---|---|---|
| IntersectionObserverWidely available | 51+ | 15+ | 55+ | 12.1+ | 51+ | 12.2+ |
First version with support, from MDN's compatibility data (web-features 3.42.0, @mdn/browser-compat-data 8.1.5).
Coming from another library?
Other libraries call this useSticky, useStickyFixed.