React Intersection provides a simple component-based interface to the Intersection Observer API.
It provides two core components: IntersectionElement
and IntersectionRoot
.
-
IntersectionElement
adds its direct DOM child as an observer of the nearest parentIntersectionRoot
, or the browser viewport if none found. -
IntersectionRoot
optionally creates a newIntersectionObserver
with either the browser viewport or its direct DOM child as the observedroot
.
React Intersection is:
- Tiny: Less than 1kb.
-
Unopinionated: Provides the full
IntersectionObserverEntry
object to eachonChange
handler. A great low-level starting point for more specific functionality. -
Component-based: No need to provide selectors or
Node
s to setIntersectionObserver.root
.
Contents
Install
npm install react-intersection --save
Usage
By default, wrapping a component with IntersectionElement
will subscribe its first child DOM element to a default viewport IntersectionObserver
, with threshold
set to [0, 1]
.
This means onChange
will fire when the element is first fully and partially off/on screen.
import { IntersectionElement } from 'react-intersection';
class Item extends React.Component {
state = {
isIntersecting: false
};
setVisibility = ({ isIntersecting }) => this.setState({ isIntersecting });
render() {
return (
<IntersectionElement onChange={this.setVisibility}>
<li />
</IntersectionElement>
);
}
}
root
Define a new We can use a parent element as the IntersectionObserver.root
instead of the viewport:
import { IntersectionRoot } from 'react-intersection';
const ScrollableList = () => (
<IntersectionRoot>
<ul>
{renderItems()}
</ul>
</IntersectionRoot>
);
In the above example, ul
will be the root
of the new IntersectionObserver
that any children IntersectionElement
s will subscribe to.
Define a new browser viewport root
To create a new browser viewport root with non-default settings, we can pass a viewport
prop to IntersectionRoot
:
const IntersectViewportWithMargins = ({ children }) => (
<IntersectionRoot viewport margin="20px 20px 20px 20px">
{children}
</IntersectionRoot>
);
API
IntersectionElement
Observe when an element intersects with its closest IntersectionRoot
Props
onChange: (e: IntersectionObserverEntry) => any
Fires after every breached threshold
on the IntersectionRoot
(or browser viewport if none set).
Is provided an IntersectionObserverEntry object.
once?: boolean = false
Stops firing events after the first true
intersection.
IntersectionRoot
Define a new IntersectionObserver.
If no root
property is defined, it only accepts a single child.
Props
viewport?: boolean = false
If true
, sets the browser viewport as the IntersectionObserver.root
property. If false
, uses the first DOM child.
margin?: string = '0px 0px 0px 0px'
A space-delimited list of margins that effectively change the observed bounding box.
Follows the CSS pattern of top/right/bottom/left where '10px 20px 30px 40px'
would give a right margin of 20px
.
If IntersectionRoot
is not a viewport observer, these values can be defined as percentages.
threshold?: number[] = [0, 1]
An array of values between 0
and 1
that dictates at which ratios the IntersectionObserver should fire callbacks. Thresholds are fully explained in the MDN Intersection Observer API article.
Browser support
React Intersection is dependent on the IntersectionObserver
API and WeakMap
: