Scroll to top on page transition in React js

Last updated : Jul 30, 2023 12:00 AM

Scrolling to the page-top is achievable in two ways.

  1. Using the browser's window.scrollTo()
  2. Using React's useRef

Let's look at both methods on how to implement scroll to top.

Scroll to top using window.scrollTo()

The scrollTo() function belongs to the window object. The scrollTo() function allows us to scroll to specified coordinates of the browser window. Therefore, we can use window.scrollTo(0, 0) to scroll to top of the page.

We can use the window.scrollTo(0,0) in the useEffect hook to trigger scroll to the top in every page navigation. You need to place the below code on every page where you want to scroll to the top. Note the empty argument array [], which means the useEffect is executed in every page re-render. You may need to remove that depending on the requirement.

useEffect(() => {
  window.scrollTo(0,0)
},[])

The example code shows links to other pages at the bottom of the page. Without window.scrollTo(0,0), you will notice that each link lands you at the bottom of the navigated page.

import { useEffect } from "react"
import { Link } from "react-router-dom"
const Post = () => {
  useEffect(() => {
    window.scrollTo(0,0)
  },[])
    return(       
    <>
    <div>
      <h1>Page Title</h1>
      <p>Some long page content</p>
    </div>
    <div>
      <span><Link to="/post1">Another Post</Link></span>
      <span><Link to="/post2">Another Long Post</Link></span>
    </div>
    </>
    )
 }
export default Post

Using hooks to scroll to the top of the page

Placing the scroll code inside the useEffect hook on every page may not be the cleanest way to achieve the scroll-to-top functionality. We can use React hooks to conceal most of the boilerplate code.

Scroll to the top React hook

import { useEffect } from "react"
export const useScrollTo = (x: number, y: number) => {
    useEffect(() => {
        window.scrollTo(x,y)
    })
}

The usage is simple as placing useScrollTo(0,0) on the page where you want to scroll to the top.

import { useScrollTo } from "./components/useScrollTo";
import { Link } from "react-router-dom"
const Post = () => {
  useScrollTo(0,0)
    return(       
    <>
    <div>
      <h1>Page Title</h1>
      <p>Some long page content</p>
    </div>
    <div>
      <span><Link to="/post1">Another Post</Link></span>
      <span><Link to="/post2">Another Long Post</Link></span>
    </div>
    </>
    )
 }
 export default Post

Scroll to top using useRef

Scrolling to the top using useRef requires a ref element located at the top of the page. Below is a code example.

is the page top anchor that we scroll to.

import { useEffect, useRef } from "react"
import { Link } from "react-router-dom";
const Home = () =>{
  const refToTop = useRef<HTMLInputElement>(null);
  useEffect(() => {
    refToTop.current && refToTop.current.scrollIntoView();
  })
  return(
    <div ref={refToTop}>
    <div>
      <h1>Page Title</h1>
      <p>Some long page content</p>
    </div>
    <div>
      <span><Link to="/post1">Another Post</Link></span>
      <span><Link to="/post2">Another Long Post</Link></span>
    </div>
    </div>
  )
}
export default Home;

Like window.scrollTo(), we can delegate the code to a react hook.

Scroll to the top React hook for useRef

import { useEffect, useRef } from "react"
export const useRefScrollTo = () => {
    const scrollToTop = useRef<HTMLInputElement>(null);
    useEffect(() => {
        scrollToTop.current && scrollToTop.current.scrollIntoView();
    })
    return scrollToTop
}

That simplifies our component to a certain stage.

import { Link } from "react-router-dom";
import { useRefScrollTo } from "./useRefScrollTo";
const Home = () =>{
  const refToTop = useRefScrollTo()
  return(
    <div ref={refToTop}>
     <div>
      <h1>Page Title</h1>
      <p>Some long page content</p>
    </div>
    <div>
      <span><Link to="/post1">Another Post</Link></span>
      <span><Link to="/post2">Another Long Post</Link></span>
    </div>
    </div>
  )
}
export default Home

Using animations with scroll to top

We can further animate the scroll effects with useRef's scrollIntoView function.

import { useEffect, useRef } from "react"
export const useRefScrollTo = (scrollProps: ScrollIntoViewOptions) => {
    const scrollToTop = useRef<HTMLInputElement>(null);
    useEffect(() => {
        scrollToTop.current && scrollToTop.current.scrollIntoView({...scrollProps});
    })
    return scrollToTop
}

With that, we can use ScrollIntoViewOptions properties to animate the scroll function.

import { Link } from "react-router-dom";
import { useRefScrollTo } from "./useRefScrollTo";
const Home = () =>{
  const refToTop = useRefScrollTo({behavior: 'smooth', block: 'start', inline: 'nearest'})
  return(
    <div ref={refToTop}>
     <div>
      <h1>Page Title</h1>
      <p>Some long page content</p>
    </div>
    <div>
      <span><Link to="/post1">Another Post</Link></span>
      <span><Link to="/post2">Another Long Post</Link></span>
    </div>
    </div>
  )
}
export default Home
Lance

By: Lance

Hi, I'm Lance Raney, a dedicated Fullstack Developer based in Oklahoma with over 15 years of exp

Read more...