Scrolling up · bottom of page in view: no

All hooks / Elements

useIsStuck

268 B minified and brotliedSourceMarkdown✓ Works in all modern browsers

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.

status bar stuck: no

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

UsesChromeEdgeFirefoxSafariChrome AndroidSafari iOS
IntersectionObserverWidely available51+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.