Scroll Progress Bar Override

Scroll Progress Bar Override

Scroll Progress Bar Override

Scroll Progress Bar Override

Effect

Effect

Effect

Effect

Scroll Progress Bar Override

Scroll Progress Bar Override

Scroll Progress Bar Override

Scroll Progress Bar Override

This is a demo website showing you how to create a scroll progress bar in Framer that reflects your position on the page. Feel free to remix the file, copy the progress bar into your own site, and follow the set-up instructions listed below.

You can click this link to get the starter file I used in the tutorial video, so you can follow along.

This is a demo website showing you how to create a scroll progress bar in Framer that reflects your position on the page. Feel free to remix the file, copy the progress bar into your own site, and follow the set-up instructions listed below.

You can click this link to get the starter file I used in the tutorial video, so you can follow along.

This is a demo website showing you how to create a scroll progress bar in Framer that reflects your position on the page. Feel free to remix the file, copy the progress bar into your own site, and follow the set-up instructions listed below.

You can click this link to get the starter file I used in the tutorial video, so you can follow along.

This is a demo website showing you how to create a scroll progress bar in Framer that reflects your position on the page. Feel free to remix the file, copy the progress bar into your own site, and follow the set-up instructions listed below.

You can click this link to get the starter file I used in the tutorial video, so you can follow along.

Scroll Progress Bar Override
Scroll Progress Bar Override
Scroll Progress Bar Override
Scroll Progress Bar Override

Features

First, there's the progress bar itself, which we'll position at the top of the website with fixed positioning.

Next, there's a frame nested within the progress bar, known as the "line". We're going to animate this "line" from 0% width to 100% width as you scroll down the site with a code override applied to the frame.

Finally, there's an additional "head" frame within the 'line' frame. This acts like a glow at the end of the scroll bar line. We'll position this absolutely and pin it to the right side of the "line".

The code override works by transforming the 'line' frame's width from 0% to 100% between the "start" and "end" scroll sections on your site.

So, you'll need to add a scroll section called "start" where you want the progress bar animation to kick off, and a scroll section called "end" where the scroll bar should reach the right edge of the page.

Just copy and paste the code override from below into your file.

Watch the full video tutorial for more guidance.

Step 01 outline

Step / 01

Remix the project.

Step 2 outline

Step / 02

Copy the progress bar.

Step 3 outline

Step / 03

Paste in your project and customize it.

Code override for the scroll progress bar line

Copy this code and paste it into a new override in your Framer project. Next, apply it to the 'line' frame that's within the progress bar.

import type { ComponentType } from "react"
import { useState, useEffect, useRef } from "react"

export function withProgress(Component): ComponentType {
    return (props) => {
        const [progress, setProgress] = useState(0)
        const [isScrolling, setIsScrolling] = useState(false)
        const prevScrollY = useRef(0)

        useEffect(() => {
            const calculateProgress = () => {
                const startEl = document.getElementById("start")
                const endEl = document.getElementById("end")
                if (startEl && endEl) {
                    const sectionHeight = endEl.offsetTop - startEl.offsetTop
                    const scrollDistance =
                        window.pageYOffset || document.documentElement.scrollTop
                    const sectionScrollDistance =
                        scrollDistance - startEl.offsetTop
                    const sectionProgress =
                        (sectionScrollDistance / sectionHeight) * 100
                    setProgress(sectionProgress)
                }
            }

            const handleScroll = () => {
                const scrollY =
                    window.pageYOffset || document.documentElement.scrollTop
                if (scrollY !== prevScrollY.current) {
                    prevScrollY.current = scrollY
                    calculateProgress()
                    setIsScrolling(true)
                }
            }

            const handleScrollEnd = () => {
                setIsScrolling(false)
            }

            calculateProgress()

            window.addEventListener("scroll", handleScroll)
            window.addEventListener("scrollend", handleScrollEnd)

            return () => {
                window.removeEventListener("scroll", handleScroll)
                window.removeEventListener("scrollend", handleScrollEnd)
            }
        }, [])

        return (
            <Component
                {...props}
                style={{
                    width: `${progress}%`,
                    transition: isScrolling ? "none" : "width 0.5s ease-in-out",
                }}
            />
        )
    }
}
import type { ComponentType } from "react"
import { useState, useEffect, useRef } from "react"

export function withProgress(Component): ComponentType {
    return (props) => {
        const [progress, setProgress] = useState(0)
        const [isScrolling, setIsScrolling] = useState(false)
        const prevScrollY = useRef(0)

        useEffect(() => {
            const calculateProgress = () => {
                const startEl = document.getElementById("start")
                const endEl = document.getElementById("end")
                if (startEl && endEl) {
                    const sectionHeight = endEl.offsetTop - startEl.offsetTop
                    const scrollDistance =
                        window.pageYOffset || document.documentElement.scrollTop
                    const sectionScrollDistance =
                        scrollDistance - startEl.offsetTop
                    const sectionProgress =
                        (sectionScrollDistance / sectionHeight) * 100
                    setProgress(sectionProgress)
                }
            }

            const handleScroll = () => {
                const scrollY =
                    window.pageYOffset || document.documentElement.scrollTop
                if (scrollY !== prevScrollY.current) {
                    prevScrollY.current = scrollY
                    calculateProgress()
                    setIsScrolling(true)
                }
            }

            const handleScrollEnd = () => {
                setIsScrolling(false)
            }

            calculateProgress()

            window.addEventListener("scroll", handleScroll)
            window.addEventListener("scrollend", handleScrollEnd)

            return () => {
                window.removeEventListener("scroll", handleScroll)
                window.removeEventListener("scrollend", handleScrollEnd)
            }
        }, [])

        return (
            <Component
                {...props}
                style={{
                    width: `${progress}%`,
                    transition: isScrolling ? "none" : "width 0.5s ease-in-out",
                }}
            />
        )
    }
}

Free Framer Course

Learn how to create stunning websites with ease by learning the fundamentals of Framer.

Free
Framer Course

Learn how to create stunning websites with ease by learning the fundamentals of Framer.

Free Framer Course

Learn how to create stunning websites with ease by learning the fundamentals of Framer.