Creating a Dynamic Horizontal Scroll Percentage Indicator with React and Framer Motion
Table of contents
The Idea
Creating a visually appealing and functional portfolio website is essential for showcasing your skills and projects. I recently explored website designs from popular examples for my portfolio (devpulkit.in) and found one animation that really excites me: the horizontal scroll percentage indicator. It is useful for tracking how much of the webpage you have scrolled.
The concept
As you can see here, it basically sits at the top of the webpage, and yes, it is as minimalist as it looks.
The Implementation
In this article, we'll implement this using React and Framer Motion.
I have my react project bootstrapped, starting by installing
npm i framer-motion
To get a good viewport to observe the scroll effect, I am adding a test height.
export default function App() {
return (
<main>
<div
style={{
height: "300vh",
}}
/>
</main>
);
}
Now let's add the main div that's gonna act like the scroll indicator
import { motion } from "framer-motion";
export default function App() {
return (
<main>
<motion.div
style={{
position: "fixed",
top: 0,
left: 0,
width: "20vw",
height: "10px",
backgroundColor: "black",
borderRadius: "0 10px 10px 0",
}}
/>
<div
style={{
height: "300vh",
}}
/>
</main>
);
}
You can read more about The <motion /> component, but in a nutshell, it is a component from Framer Motion that allows you to animate elements in a simple and declarative way.
And the styles are simple. The element is fixed at the top left of the screen, with a width of 0 (the main property that will act like a slider) and a height of 10 pixels. It has a black background and rounded corners on the right side.
Now let's animate it to move when we scroll. We'll use the useScroll()
hook from framer-motion.
import { useScroll} from "framer-motion";
const { scrollYProgress } = useScroll();
Now, to animate the changing values received from scrollYProgress
, we will use the useTransform
hook from framer-motion.
const width = useTransform(scrollYProgress, [0, 1], ["0%", "100%"]);
Here, the width will provide an animated value based on scrollYProgress
. As you scroll from the top to the bottom of the page, the width changes from "0%" to "100%". This is done by mapping the scrollYProgress
values (which range from 0 to 1) to the corresponding width values.
import { motion, useScroll, useTransform } from "framer-motion";
export default function App() {
const { scrollYProgress } = useScroll();
const width = useTransform(scrollYProgress, [0, 1], ["0%", "102%"]);
return (
<main>
<motion.div
style={{
position: "fixed",
top: 0,
left: 0,
height: "10px",
backgroundColor: "black",
borderRadius: "0 10px 10px 0",
width,
}}
/>
<div
style={{
height: "300vh",
}}
/>
</main>
);
}
So, we use the width as a style prop for the motion.div
. And that's pretty much it for animating the scroll indicator.
The Output
And there you have it! You've just created a sleek horizontal scroll percentage indicator with React and Framer Motion. Now your portfolio site is not only functional but also has that extra touch of interactivity. Happy coding, and may your scrolls always be smooth! ๐โจ
Subscribe to my newsletter
Read articles from Pulkit directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Pulkit
Pulkit
Hi there! ๐ I'm Pulkit, a passionate web and app developer specializing in MERN and React Native technologies. With a keen interest in open-source contributions and competitive programming, I love building innovative solutions and sharing my knowledge with the community. Follow along for insights, tutorials, and updates on my coding journey!