Scrolling to the page-top is achievable in two ways.
- Using the browser's window.scrollTo()
- 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. <div ref={refToTop}>
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