use-intersection

Detects if given element is visible in the viewport or other element with IntersectionObserver

Import

Usage

use-intersection returns information about the intersection of a given element with its scroll container or body element with Intersection Observer API:

Obscured

import { useRef } from 'react';
import { useIntersection } from '@mantine/hooks';
import { Text, Paper, Box } from '@mantine/core';

function Demo() {
  const containerRef = useRef<HTMLDivElement>(null);
  const { ref, entry } = useIntersection({
    root: containerRef.current,
    threshold: 1,
  });

  return (
    <Paper ref={containerRef} h={300} style={{ overflowY: 'scroll' }}>
      <Box pt={260} pb={280}>
        <Paper
          ref={ref}
          p="xl"
          style={{
            backgroundColor: entry?.isIntersecting
              ? 'var(--mantine-color-teal-7)'
              : 'var(--mantine-color-red-7)',
            minWidth: '50%',
          }}
        >
          <Text c="#fff" fw={700}>
            {entry?.isIntersecting ? 'Fully visible' : 'Obscured'}
          </Text>
        </Paper>
      </Box>
    </Paper>
  );
}

API

The hook accepts IntersectionObserver's options as its only optional argument:

useIntersection({
  root: someDomElement,
  rootMargin: '0rem',
  threshold: 1.0,
});

The hook returns a ref function that should be passed to the observed element, and the latest entry, as returned by IntersectionObserver's callback. See Intersection Observer API documentation to learn everything about options.

On the first render (as well as during SSR), or when no element is being observed, the entry is null.

const { ref, entry } = useIntersection();

// With regular element:
<div ref={ref}>Observed</div>

// With Mantine component:
<Paper ref={ref}>Observed</Paper>

Definition

function useIntersection<T extends HTMLElement = any>(
  options?: ConstructorParameters<typeof IntersectionObserver>[1]
): {
  ref: (element: T | null) => void;
  entry: IntersectionObserverEntry;
};