Scrolling a React Element into View
A use case
Occasionally we build pages where we want to alert the user to something, but it may be outside their view. An example is a long form with a vertical scrollbar, with a field error out of view after the form is submitted.
Try this example in CodeSandbox. Put “bad” in Field 1, scroll to the last field, and click Save. Field 1 contains an error, but you probably can’t see it until you scroll back up.
In this case, we want to automatically scroll the problem field into the users view to improve the user experience.
scrollIntoView
There is a method called scrollIntoView
that exists on HTML elements that we can use that is supported on all modern browsers. This method will scroll the element’s parent container so that it becomes visible to a user.
Nice!
Using scrollIntoView
in React
How do we use scrollIntoView
in React? We don’t usually call DOM element methods imperatively in the React world!
Well, we start by getting references to the elements we want to call scrollIntoView
on. These elements are the div
containers for each field in our example.
const Field = ({ ... }: FieldProps) => {
const fieldRef = React.useRef<HTMLInputElement>(null); return (
<div className="field" ref={fieldRef}> ...
</div>
);
};
We use the useRef
hook to put a reference to the div
in a variable called fieldRef
.
We can then use the useEffect
hook to invoke this method when the field has an error:
const Field = ({ ... }: FieldProps) => {
const fieldRef = React.useRef<HTMLInputElement>(null);
React.useEffect(() => { if (error && fieldRef.current) { fieldRef.current.scrollIntoView(); } }, [error]); return ...
};
We put the error
prop in the useEffect
dependency array so that the effect function is invoked every time the error changes. Inside the effect function, we access the field div
element using fieldRef.current
and call scrollIntoView
when there is an error, and we have reference to the div
.
That’s it! The problem field is automatically scrolled to when the Save button is clicked.
Smooth transition
There is a minor improvement we can make, to make the scrolling smoother. scrollIntoView
takes in a scrollIntoViewOptions
object parameter. Within that object there is a behavior
property that we can set to "smooth"
:
fieldRef.current.scrollIntoView({
behavior: "smooth",
});
Note that scrollIntoViewOptions
isn’t available on IE and Safari at the time of writing this post. So, we won’t see this minor improvement in those browsers.
That completes this example of scrolling a React element into view. The final example is in CodeSandbox at https://codesandbox.io/s/scrollntoview-fn0bb?file=/src/index.tsx
If you to learn more about using TypeScript with React, you may find my course useful: