When I'm thinking about the things I learned way too late in my React journey. There is one feature that immediately comes to my mind - scrolling. I decided to sum up everything I know about the scrolling and scroll effects. And put it in this blog post. Let's start with the single most asked question about scrolling. How to scroll to an element in React app?
Scroll to an Element in React
The way to scroll to an element in React is a little different than other frameworks. The most simple way is to use ref
to store the reference of the element that you want to scroll to. And call myRef.current.scrollIntoView()
to scroll it into the view.
The whole implementation using a functional component.
App.jsx
import React, { useRef } from 'react';
const App = () => {
const scollToRef = useRef();
return (
<div className="container">
<button onClick={() => scollToRef.current.scrollIntoView()}>
Scroll
</button>
<div ref={scollToRef}>You scrolled to me</div>
</div>
);
};
export default App;
And here is the class-based version.
App.jsx
import React, { createRef } from 'react';
class App extends Component {
constructor(props) {
super(props);
this.scollToRef = createRef();
}
render() {
return (
<div className="container">
<button onClick={() => this.scollToRef.current.scrollIntoView()}>
Scroll
</button>
<div ref={this.scollToRef}>You scrolled to me</div>
</div>
);
}
}
export default App;
Scrolling to an element is a powerful technique and I can see a lot of applications for it. But sometimes, you don't want to scroll to a specific element. What should you do in this case? You'll find out in the next section.
Scroll to an Exact Location
React provides a scrollTo
function that lets you scroll to a given location. A good application for this function is to scroll to the bottom of the page, or back to the top. This function takes two arguments: the first is the position of where you want to scroll and the second is the animation duration (optional). The syntax for this function is as follows: scrollTo(x, y)
.
info
The usage in React isn't any different from other frameworks. This is because of the fact that scrollTo
function can be accessed directly from Window
object.
App.jsx
import React from "react";
const App = () => {
return (
<div className="container">
<button onClick={() => window.scrollTo(0, window.innerHeight)}>
Scroll to bottom
</button>
<button onClick={() => window.scrollTo(0, 0)}>Scroll top top</button>
</div>
);
};
export default App;
tip
You can also call scrollTo
function with ScrollToOptions
object as a parameter. I'm using this when I need to specify additional scrolling behavior, e.g. smooth scrolling.
App.jsx
import React from "react";
const App = () => {
return (
<div className="container">
<button
onClick={() =>
window.scrollTo({
left: 0,
top: window.innerHeight,
behavior: "smooth",
})
}
>
Scroll to bottom
</button>
<button
onClick={() =>
window.scrollTo({
left: 0,
top: 0,
behavior: "smooth",
})
}
>
Scroll top top
</button>
</div>
);
};
export default App;
Benefits of Scroll Effect
Websites are made to be navigated by scrolling down. However, this can cause eye strain and is mentally taxing for the user. To combat this, many new websites implement a "scrolling effect" that scrolls in a smooth linear path so you don't have to scroll as often or as fast and find what you're looking for more efficiently.
The idea of the scrolling effect is that it encourages users to scan through different areas of a website. Not just focus on one area at a time. Websites often use this effect to highlight certain parts of their page or draw attention to content that they want their users to look at next.
Popular Scrolling Libraries for React
As the popularity of React has grown, so has the number of libraries that are available for it. Below is a list of some popular scrolling libraries that you can use in your React project.
Scroll Magic
ScrollMagic is a JavaScript library that makes it super easy to react to the user's current scroll position. It is perfect if you want to:
- Animate based on scroll position.
- Pin an element starting at a specific scroll position.
- Toggle CSS classes based on scroll position.
- Add parallax effects to your website.
- Create an infinitely scrolling page.
- Add callbacks at specific scroll positions or while scrolling past a specific section.
React Scroll
With more than 200k weekly downloads and 3.5k start on Github, it's safe to say that react-scroll is the most popular React scrolling library out there. It covers a lot of common use cases like:
- Scrolling to an exact page location
- Scrolling to an element
- Scrolling to an element within the container
- Callbacks at specific scroll positions or while scrolling past a specific section.
note
This library covers many use-cases. However, I tried to put together the most basic example. And this is how the implementation goes.
ReactScroll.jsx
import React, { Component } from "react";
import {
Link,
Element,
Events,
animateScroll as scroll,
scroller,
} from "react-scroll";
import "./ReactScroll.css";
class ReactScroll extends Component {
componentDidMount() {
Events.scrollEvent.register("begin", () => {
console.log("begin", arguments);
});
Events.scrollEvent.register("end", () => {
console.log("end", arguments);
});
}
scrollToTop = () => {
scroll.scrollToTop();
};
scrollTo = () => {
scroller.scrollTo("scroll-to-element", {
duration: 800,
delay: 0,
smooth: "easeInOutQuart",
});
};
scrollToWithContainer = () => {
let goToContainer = new Promise((resolve) => {
Events.scrollEvent.register("end", () => {
resolve();
Events.scrollEvent.remove("end");
});
scroller.scrollTo("scroll-container", {
duration: 800,
delay: 0,
smooth: "easeInOutQuart",
});
});
goToContainer.then(() =>
scroller.scrollTo("scroll-container-second-element", {
duration: 800,
delay: 0,
smooth: "easeInOutQuart",
containerId: "scroll-container",
})
);
};
componentWillUnmount() {
Events.scrollEvent.remove("begin");
Events.scrollEvent.remove("end");
}
render() {
return (
<main className="react-scroll-page">
<nav>
<ul>
<li>
<Link to="section-1" spy={true} smooth={true}>
Section 1
</Link>
</li>
<li>
<Link to="section-2" spy={true} smooth={true}>
Section 2
</Link>
</li>
<li>
<Link to="section-3" spy={true} smooth={true}>
Section 3
</Link>
</li>
<li>
<button onClick={scroll.scrollToBottom}>Scroll To Bottom</button>
</li>
<li>
<button onClick={scroll.scrollToTop}>Scroll To Top</button>
</li>
<li>
<button onClick={() => scroll.scrollMore(500)}>
Scroll 500 More!
</button>
</li>
<li>
<button onClick={() => scroll.scrollMore(-500)}>
Scroll 500 Less!
</button>
</li>
<li>
<button
to="scroll-container-second"
onClick={() => this.scrollToWithContainer()}
>
Scroll to second element within container
</button>
</li>
</ul>
</nav>
<Element name="section-1" className="page-section page-section-1">
Section 1
</Element>
<Element name="section-2" className="page-section page-section-2">
Section 2
</Element>
<Element name="section-3" className="page-section page-section-3">
Section 3
</Element>
<Element className="container" id="scroll-container">
<Element name="scroll-container-first">
First element inside container
</Element>
<Element name="scroll-container-second">
Second element inside container
</Element>
<Element name="scroll-container-third">
Third element inside container
</Element>
</Element>
</main>
);
}
}
export default ReactScroll;
As you can see from the examples, it's possible to:
- Scroll between sections.
- Scrolling to the top.
- Scrolling to the bottom.
But that's not all. You can also:
- Off scroll position in a positive or negative direction.
- Scroll to an element within the container.
React Hash Scroll
React Hash Scroll is a popular library used in many React projects. It aims to be the simplest way to implement hash routing.
The library makes it easier for developers to make their web app work with hash navigation. With just a few lines of code, we can achieve smooth navigation between different page sections.
HashScrollPage.jsx
import React from "react";
import { Link } from "react-router-dom";
import { HashScroll } from "react-hash-scroll";
const HashScrollPage = () => {
return (
<main className="page">
<nav>
<ul>
<li>
<Link to="/hash-scroll#hash-section-1">Go To Section 1</Link>
</li>
<li>
<Link to="/hash-scroll#hash-section-2">Go To Section 2</Link>
</li>
<li>
<Link to="/hash-scroll#hash-section-3">Go To Section 3</Link>
</li>
</ul>
</nav>
<article>
<HashScroll hash="#hash-section-1">
<section>Section 1</section>
</HashScroll>
<HashScroll hash="#hash-section-2">
<section>Section 2</section>
</HashScroll>
<HashScroll hash="#hash-section-3">
<section>Section 3</section>
</HashScroll>
</article>
</main>
);
};
export default HashScrollPage;
With a little bit of CSS magic, the code above will result in the following.
React Scroll Parallax
React scroll parallax library provides components to create parallax scroll effects for any DOM elements. It uses a single scroll listener to add vertical or horizontal scroll offsets to elements based on their position in the viewport. It's optimized for performance and works for both client/server-side rendered apps. (source: React scroll parallax)
If you're a fan of the parallax effect. I guarantee you'll love this library. With just a little bit of code (and much more design skills), you can achieve stunning results like the example below. Credits to jscottsmith
Concluding Thoughts
Every time I'm building user interfaces, I'm telling myself one thing. It's your job as a developer to make the user experience as smooth as possible. If it means taking the user by the hand and pointing him to every single piece of content on my website, so be it.
Navigating between different pages of the website is pretty straightforward and can be done using links. But when it comes to navigation between different places on the same page, scrolling is the way to go. And today, you learned how to do it. You learned how to scroll to an element in React app. You learned how to scroll into a specific position. And you also learned what libraries are available for scrolling. Now, it's up to you to get to work and start using this knowledge in your react app.