All hooks / Viewport and media

useWindowScroll

169 B minified and brotliedSourceMarkdown✓ Works in all modern browsers

The window's scroll position in CSS pixels, updated on scroll.

Renders serverValue on the server and during hydration, then switches to the real position with no hydration mismatch. Re-renders on every scroll event that moves the page (not throttled).

Import

import { useWindowScroll } from '@vincent.ri/react-tils'
// or only this hook
import { useWindowScroll } from '@vincent.ri/react-tils/useWindowScroll'

Usage

const { y } = useWindowScroll()
return y > 400 ? <button onClick={() => window.scrollTo({ top: 0 })}>Top</button> : null

Live demo

Scroll the page.

y = 0

When to use it

JS needs the scroll position, e.g. a "back to top" button after scrolling down, or parallax that depends on the exact offset.

When not to

You only need to know if an element is visible; use useInView, which does not re-render on every scroll. For a header that hides on scroll down, use useScrollDirection; for a reading progress bar, useScrollProgress; both re-render far less. For sticky elements, use CSS position: sticky. For scroll-linked animation, use CSS scroll-driven animations.

API

function useWindowScroll(serverValue?: WindowScroll): WindowScroll
ParameterDescription
serverValuePosition on the server and during hydration. Default { x: 0, y: 0 }. Pass a constant, not an inline object.

Types

export type WindowScroll = {
  x: number;
  y: number;
};

Browser support

Uses only long-established browser features, so it works wherever React does.

First version with support, from MDN's compatibility data (web-features 3.42.0, @mdn/browser-compat-data 8.1.5).