Skip to content
Esc
navigateopen⌘Jpreview
On this page

Overview

A React implementation of the Intersection Observer API that tells you when an element enters or leaves the viewport. Use hooks for React state or effects, or <InView> for render props and plain children.

Use it to lazy-load content, trigger scroll-based animations, track impressions, prefetch data, highlight visible sections, and load more results.

Install

npm install react-intersection-observer
pnpm add react-intersection-observer
yarn add react-intersection-observer
bun add react-intersection-observer
import { useInView } from "react-intersection-observer";

export function Section() {
  const { ref, inView } = useInView();

  return <section ref={ref}>{inView ? "In view" : "Waiting"}</section>;
}

Attach ref to an element and use inView in the render. The browser viewport is the root by default, and any intersection flips the state. Set a threshold, margin, or custom root when that default is not enough.

entry is the latest observer result, so read geometry from it. It stays undefined until the browser delivers the first accepted notification.

Choose an API

When you need to Use Why
Change what a component renders useInView Returns a ref, inView, and the latest entry.
Run an impression, prefetch, or analytics callback useOnInView Calls your callback without a hook-owned state update.
Keep observation close to render props or a wrapper <InView> Provides render props and supports plain children.

Try it

The hook above uses the browser viewport. This demo adds a custom scroll root and a threshold, so you can see how options change the same inView state.

See when an element becomes visible
Step 2 · Scroll this panel to reveal the observed card ↓
Design systems that travelA small feed item
A quiet note on shippingA small feed item
Small details, deliberately timedA small feed item
A scroll worth observingA small feed item
A detail worth loadingA small feed item
One more thing to noticeA small feed item
QueuedWatching
Feature card is waiting

Scroll until enough of this card is visible.

Waiting for visibility
Where interaction beginsA small feed item
A follow-up for the readerA small feed item
The next item is already waitingA small feed item

What you get

  • Shared observer instances. Targets that use the same options share one IntersectionObserver, so observing hundreds of elements is cheap.
  • Types in the package. Hooks, components, options, and entries are typed. There is no @types package to install.
  • Two test layers. react-intersection-observer/test-utils drives deterministic transitions, and Browser Mode runs the browser’s own observer.
  • Separate entry points. Import only useInView and the rest is tree shaken away, around 1.15kB gzipped.

Where to go next

Was this page helpful?