How to Scroll to an Element on Click in React

To scroll to an element on click in React:

  1. Set a ref on the target element.
  2. Set a click listener on the element meant to cause the scroll on click.
  3. In the click event listener, call the scrollIntoView() method on the ref object.
App.jsx
import { useRef } from 'react'; export default function App() { const ref = useRef(null); const handleClick = () => { ref.current?.scrollIntoView({ behavior: 'smooth' }); }; return ( <div> <button onClick={handleClick}>Scroll to element</button> <div style={{ height: '150rem' }} /> <div ref={ref} style={{ backgroundColor: 'lightblue' }}> Coding Beauty </div> <div style={{ height: '150rem' }} /> </div> ); }
Scrolling to an element on click in React

Scrolling to an element on click improves user experience by allowing for quick navigation, especially for long lists or pages with multiple sections. It can also add a touch of interactivity to navigation through smooth-scrolling animations.

We create a ref object with the useRef hook and assign it to the ref prop of the target div element. Doing this sets the current property of the ref object to the DOM object that represents the element.

useRef returns a mutable object that maintains its value when a component updates. Also, modifying the value of this object’s current property doesn’t cause a re-render. This is unlike the setState update function return from the useState hook.

We use the onClick on the button to a click listener to it. So, this listener will be called when the user clicks the button.

App.jsx
const handleClick = () => { ref.current?.scrollIntoView({ behavior: 'smooth' }); };

In the handleClick listener, we call the scrollIntoView() method on the ref of the target div element to scroll down to it and display it to the user.

We set the behaviour option to smooth to make the element scroll into view in an animated way, instead of jumping straight to the element in the next frame – auto. auto is the default.

Scroll to dynamic element on click in React

We can do something similar to scroll to a dynamically created element in React:

App.jsx
import { useRef, useState } from 'react'; const allFruits = [ 'Apples', 'Bananas', 'Oranges', 'Grapes', 'Strawberries', 'Blueberries', 'Pineapples', 'Mangoes', 'Kiwis', 'Watermelons', ]; export default function App() { const ref = useRef(null); const [fruits, setFruits] = useState([...allFruits.slice(0, 3)]); const addFruit = () => { setFruits((prevFruits) => [...prevFruits, allFruits[prevFruits.length]]); }; const scrollToLastFruit = () => { const lastChildElement = ref.current?.lastElementChild; lastChildElement?.scrollIntoView({ behavior: 'smooth' }); }; return ( <div> <div style={{ position: 'fixed', backgroundColor: 'white', bottom: 0, marginBottom: 10, }} > <button onClick={addFruit}>Add fruit</button> <button onClick={scrollToLastFruit} style={{ marginLeft: '8px' }}> Scroll to last </button> </div> <div style={{ height: '5rem' }} /> <div ref={ref}> {fruits.map((fruit) => ( <h2 key={fruit}>{fruit}</h2> ))} </div> <div style={{ height: '150rem' }} /> </div> ); }
Scrolling to a dynamic element on click in React.

Here we have a list of fruits displayed. The Add fruit button dynamically adds an item to the fruit list on click. Then the Scroll to last button scrolls to this item on click, as it’s the last in the list.

Like before, we use the onClick prop to set a click event listener on the button.

This time we set the ref on the list instead of the items since the items are created dynamically, and the last item will not be constant. Doing this sets the current property of the ref object to the DOM object that represents the list element.

In this listener, we use the lastElementChild property of the list element to get its last item element. Then we call scrollIntoView() on this last item to scroll down to it.

JavaScript
const scrollToLastFruit = () => { const lastChildElement = ref.current?.lastElementChild; lastChildElement?.scrollIntoView({ behavior: 'smooth' }); };

Create and scroll to dynamic element on click

We can also combine the element creation and scroll as a single action caused by a button click.

To do this, we’ll add a useEffect hook to call scrollToLastFruit() whenever the fruits state array changes.

App.jsx
const addFruit = () => { setFruits((prevFruits) => [...prevFruits, allFruits[prevFruits.length]]); }; const scrollToLastFruit = () => { const lastChildElement = ref.current?.lastElementChild; lastChildElement?.scrollIntoView({ behavior: 'smooth' }); }; // 👇 Call `scrollToLastFruit()` when `fruits` changes. useEffect(() => { scrollToLastFruit(); }, [fruits]);
Creating and scrolling to a dynamic element on click in React.

Here’s the full code for reference:

App.jsx
import { useEffect, useRef, useState } from 'react'; const allFruits = [ 'Apples', 'Bananas', 'Oranges', 'Grapes', 'Strawberries', 'Blueberries', 'Pineapples', 'Mangoes', 'Kiwis', 'Watermelons', ]; export default function App() { const ref = useRef(null); const [fruits, setFruits] = useState([...allFruits.slice(0, 3)]); const addFruit = () => { setFruits((prevFruits) => [...prevFruits, allFruits[prevFruits.length]]); }; const scrollToLastFruit = () => { const lastChildElement = ref.current?.lastElementChild; lastChildElement?.scrollIntoView({ behavior: 'smooth' }); }; useEffect(() => { scrollToLastFruit(); }, [fruits]); return ( <div> <div style={{ position: 'fixed', backgroundColor: 'white', bottom: 0, marginBottom: 10, }} > <button onClick={addFruit}>Add fruit and scroll</button> </div> <div style={{ height: '5rem' }} /> <div ref={ref}> {fruits.map((fruit) => ( <h2 key={fruit}>{fruit}</h2> ))} </div> <div style={{ height: '150rem' }} /> </div> ); }

Key takeaways

  • To scroll to an element on click in React, set a ref on the target element, set a click listener on the element meant to cause the scroll, and in the click event listener, call the scrollIntoView() method on the ref object.
  • To scroll to a dynamically created element in React, set the ref on the list container and call scrollIntoView() on the target item element.
  • We can combine element creation and scrolling as a single action by using the useEffect hook to call scrollToLastFruit() whenever the state array changes.


Every Crazy Thing JavaScript Does

A captivating guide to the subtle caveats and lesser-known parts of JavaScript.

Every Crazy Thing JavaScript Does

Sign up and receive a free copy immediately.

Leave a Comment

Your email address will not be published. Required fields are marked *