React implementation of the Intersection Observer API to tell you when an element enters or leaves the viewport.
Contains both a Hooks, render props and plain children implementation.
This Storybook is a collection of examples. The examples are used during development as a way to validate that all features are working as intended.
React Hooks make it easy to monitor the inView
state of your components. Call
the useInView
hook with the (optional) options you need. It will
return an array containing a ref
, the inView
status and the current
entry
.
Assign the ref
to the DOM element you want to monitor, and the hook will
report the status.
import React from 'react';
import { useInView } from 'react-intersection-observer';
const Component = () => {
const { ref, inView, entry } = useInView({
/* Optional options */
threshold: 0,
});
return (
<div ref={ref}>
<h2>{`Header inside viewport ${inView}.`}</h2>
</div>
);
};
To use the <InView>
component, you pass it a function. It will be called
whenever the state changes, with the new value of inView
. In addition to the
inView
prop, children also receive a ref
that should be set on the
containing DOM element. This is the element that the IntersectionObserver will
monitor.
If you need it, you can also access the
IntersectionObserverEntry
on entry
, giving you access to all the details about the current intersection
state.
import { InView } from 'react-intersection-observer';
const Component = () => (
<InView>
{({ inView, ref, entry }) => (
<div ref={ref}>
<h2>{`Header inside viewport ${inView}.`}</h2>
</div>
)}
</InView>
);
export default Component;
You can pass any element to the <InView />
, and it will handle creating the
wrapping DOM element. Add a handler to the onChange
method, and control the
state in your own component. Any extra props you add to <InView>
will be
passed to the HTML element, allowing you set the className
, style
, etc.
import { InView } from 'react-intersection-observer';
const Component = () => (
<InView as="div" onChange={(inView, entry) => console.log('Inview:', inView)}>
<h2>Plain children are always rendered. Use onChange to monitor state.</h2>
</InView>
);
export default Component;
⚠️ When rendering a plain child, make sure you keep your HTML output semantic. Change theas
to match the context, and add aclassName
to style the<InView />
. The component does not support Ref Forwarding, so if you need aref
to the HTML element, use the Render Props version instead.
Provide these as props on the <InView />
component or as the options
argument for the hooks.
Name | Type | Default | Required | Description |
---|---|---|---|---|
root | Element | document | false | The IntersectionObserver interface's read-only root property identifies the Element or Document whose bounds are treated as the bounding box of the viewport for the element which is the observer's target. If the root is null, then the bounds of the actual document viewport are used. |
rootMargin | string | '0px' | false | Margin around the root. Can have values similar to the CSS margin property, e.g. "10px 20px 30px 40px" (top, right, bottom, left). |
threshold | number | number[] | 0 | false | Number between 0 and 1 indicating the percentage that should be visible before triggering. Can also be an array of numbers, to create multiple trigger points. |
trackVisibility 🧪 | boolean | false | false | A boolean indicating whether this IntersectionObserver will track changes in a target’s visibility. |
delay 🧪 | number | undefined | false | A number indicating the minimum delay in milliseconds between notifications from this observer for a given target. This must be set to at least 100 if trackVisibility is true . |
skip | boolean | false | false | Skip creating the IntersectionObserver. You can use this to enable and disable the observer as needed. If skip is set while inView , the current state will still be kept. |
triggerOnce | boolean | false | false | Only trigger the observer once. |
initialInView | boolean | false | false | Set the initial value of the inView boolean. This can be used if you expect the element to be in the viewport to start with, and you want to trigger something when it leaves. |
fallbackInView | boolean |
undefined | false | If the IntersectionObserver API isn't available in the client, the default behavior is to throw an Error. You can set a specific fallback behavior, and the inView value will be set to this instead of failing. To set a global default, you can set it with the defaultFallbackInView() |
The <InView />
component also accepts the following props:
Name | Type | Default | Required | Description |
---|---|---|---|---|
as | string |
'div' | false | Render the wrapping element as this element. Defaults to div . |
children | ({ref, inView, entry}) => React.ReactNode , ReactNode |
true | Children expects a function that receives an object containing the inView boolean and a ref that should be assigned to the element root. Alternatively pass a plain child, to have the <InView /> deal with the wrapping element. You will also get the IntersectionObserverEntry as `entry, giving you more details. |
|
onChange | (inView, entry) => void |
false | Call this function whenever the in view state changes. It will receive the inView boolean, alongside the current IntersectionObserverEntry . |