use-scroll-into-view

Scroll given node into view
Import

Usage

use-scroll-into-view handles scroll behavior for any scrollable element. Basic usage works the same way as element.scrollIntoView(). Hook adjusts scrolling animation with respect to the reduced-motion user preference.

Hello there
import { useScrollIntoView } from '@mantine/hooks';
import { Button, Text } from '@mantine/core';
function Demo() {
const { scrollIntoView, targetRef } = useScrollIntoView<HTMLDivElement>({ offset: 60 });
return (
<>
<Button onClick={() => scrollIntoView({ alignment: 'center' })}>Scroll to target</Button>
<div style={{ height: '50vh' }} />
<Text ref={targetRef}>Hello there</Text>
</>
);
}

API

Hook is configured with settings object:

  • onScrollFinish – function that will be called after scroll animation
  • easing – custom math easing function
  • duration - duration of scroll animation in milliseconds
  • axis - axis of scroll
  • cancelable - indicator if animation may be interrupted by user scrolling
  • offset - additional distance between nearest edge and element
  • isList - indicator that prevents content jumping in scrolling lists with multiple targets eg. Select, Carousel

Hook returns an object with:

  • scrollIntoView – function that starts scroll animation
  • cancel – function that stops scroll animation
  • targetRef - ref of target HTML node
  • scrollableRef - ref of scrollable parent HTML element, if not used document element will be used

Returned scrollIntoView function accepts single optional argument alignment - optional target element alignment relatively to parent based on current axis.

scrollIntoView({ alignment: 'center' });

Easing

Hook accept custom easing math function to control the flow of animation. It takes t argument which is a number between 0 and 1.

Default easing is easeInOutQuad - more info here. You can find other popular examples on easings.net

useScrollIntoView({
target: someDomElement,
easing: (t) => (t < 0.5 ? 16 * Math.pow(t, 5) : 1 - Math.pow(-2 * x + 2, 5) / 2), // easeInOutQuint
});

Examples

Parent node

Scroll me into view
import { useScrollIntoView } from '@mantine/hooks';
import { Button, Paper } from '@mantine/core';
function Demo() {
const { scrollIntoView, targetRef, scrollableRef } = useScrollIntoView();
return (
<>
<Paper ref={scrollableRef} style={{ overflowY: 'scroll', height: 300, flex: 1 }}>
<Paper ref={targetRef}>Scroll me into view</Paper>
</Paper>
<Button onClick={() => scrollIntoView()}>Scroll to target</Button>
</>
);
}

Scroll X axis

Scroll me into view
import { useScrollIntoView } from '@mantine/hooks';
import { Button, Paper } from '@mantine/core';
function Demo() {
const { scrollIntoView, targetRef, scrollableRef } = useScrollIntoView({
axis: 'x',
});
return (
<>
<Paper ref={scrollableRef} style={{ overflowX: 'scroll', height: 150, width: 300 }}>
<Paper ref={targetRef}>Scroll me into view</Paper>
</Paper>
<Button onClick={() => scrollIntoView()}>Scroll to target</Button>
</>
);
}

Definition

function useScrollIntoView<
Target extends HTMLElement,
Parent extends HTMLElement | null = null
>({
onScrollFinish?: () => void;
duration?: number;
axis?: 'x' | 'y';
easing?: (t: number) => number;
offset?: number;
cancelable?: boolean;
isList?: boolean;
}): {
targetRef: MutableRefObject<Target>;
scrollableRef: MutableRefObject<Parent>;
scrollIntoView: ({
alignment?: 'start' | 'end' | 'center';
}) => void;
cancel: () => void;
};