Apple Vision Pro Scroll Animation

Apple Vision Pro Scroll Animation

Apple Vision Pro Scroll Animation

Apple Vision Pro Scroll Animation

Website animation

Website animation

Website animation

Website animation

Apple Vision Pro Scroll Animation

Apple Vision Pro Scroll Animation

Apple Vision Pro Scroll Animation

Apple Vision Pro Scroll Animation

This is the scroll animation from the Apple Vision Pro site, recreated in Framer. Feel free to remix the project and check out how it's built.

This is the scroll animation from the Apple Vision Pro site, recreated in Framer. Feel free to remix the project and check out how it's built.

This is the scroll animation from the Apple Vision Pro site, recreated in Framer. Feel free to remix the project and check out how it's built.

This is the scroll animation from the Apple Vision Pro site, recreated in Framer. Feel free to remix the project and check out how it's built.

Apple Vision Pro Scroll Animation
Apple Vision Pro Scroll Animation
Apple Vision Pro Scroll Animation
Apple Vision Pro Scroll Animation

Features

The scroll animation effect leverages a mix of native Framer effects and some code overrides.

Elements of Vision Pro are moved using scroll transforms, triggered by scroll sections.

The video plays on scroll due to a scroll scrub code override applied to it.

I also employed sticky positioning, ensuring that the Vision Pro headset stays at the top of the viewport during the animation. An additional code override on the sticky container assures that the top value remains at 50vh, meaning the section halts in the center of the viewport.

You can copy both overrides from below.

Step 01 outline

Step / 01

Remix the project.

Step 2 outline

Step / 02

See how it's built.

Step 3 outline

Step / 03

Try recreating it for practice, or copy and paste it to your project.

Code override for the scroll scrub video effect

Go ahead and copy the code, then create a new override in your project to start from scratch.

You can edit the "startY" and "distance" variables to alter when the video starts playing and the duration it takes to play the entire video.

import type { ComponentType } from "react"
import { useState, useEffect } from "react"
import type { MotionValue, Transition } from "framer-motion"
import { useViewportScroll, useTransform } from "framer-motion"
import { gsap } from "gsap"

export function withScrolledProgress(Component): ComponentType {
    const startY = 1000
    const distance = 1500
    const endY = startY + distance
    return (props) => {
        const { scrollY } = useViewportScroll()
        const progress = useTransform(scrollY, [startY, endY], [0, 1])
        useEffect(() => {
            const video = document.getElementById("video") as HTMLVideoElement
            gsap.to(video, {
                scrollTrigger: {
                    trigger: ".scroll-container",
                    start: "top top",
                    end: "bottom bottom",
                    scrub: 1,
                    markers: true,
                },
                keyframes: [
                    { progress: 0 },
                    { progress: 0.1 },
                    { progress: 0.2 },
                    { progress: 0.3 },
                    { progress: 0.4 },
                    { progress: 0.5 },
                    { progress: 0.6 },
                    { progress: 0.7 },
                    { progress: 0.8 },
                    { progress: 0.9 },
                    { progress: 1 },
                ],
                ease: "linear",
                duration: 10,
            })

            return () => {
                gsap.killTweensOf(video)
            }
        }, [scrollY, distance])

        return <Component {...props} progress={progress} />
    }
}
import type { ComponentType } from "react"
import { useState, useEffect } from "react"
import type { MotionValue, Transition } from "framer-motion"
import { useViewportScroll, useTransform } from "framer-motion"
import { gsap } from "gsap"

export function withScrolledProgress(Component): ComponentType {
    const startY = 1000
    const distance = 1500
    const endY = startY + distance
    return (props) => {
        const { scrollY } = useViewportScroll()
        const progress = useTransform(scrollY, [startY, endY], [0, 1])
        useEffect(() => {
            const video = document.getElementById("video") as HTMLVideoElement
            gsap.to(video, {
                scrollTrigger: {
                    trigger: ".scroll-container",
                    start: "top top",
                    end: "bottom bottom",
                    scrub: 1,
                    markers: true,
                },
                keyframes: [
                    { progress: 0 },
                    { progress: 0.1 },
                    { progress: 0.2 },
                    { progress: 0.3 },
                    { progress: 0.4 },
                    { progress: 0.5 },
                    { progress: 0.6 },
                    { progress: 0.7 },
                    { progress: 0.8 },
                    { progress: 0.9 },
                    { progress: 1 },
                ],
                ease: "linear",
                duration: 10,
            })

            return () => {
                gsap.killTweensOf(video)
            }
        }, [scrollY, distance])

        return <Component {...props} progress={progress} />
    }
}

Code override for sticky container

Go ahead and copy the code, then create a new override in your project to start from scratch.

This code basically makes the frame stop with a 50vh (50% of the given viewport) distance from the top of the viewport.

import type { ComponentType } from "react"

export function withStickyTop(Component): ComponentType {
    return (props) => {
        return (
            <Component {...props} style={{ position: "sticky", top: "50vh" }} />
        )
    }
}
import type { ComponentType } from "react"

export function withStickyTop(Component): ComponentType {
    return (props) => {
        return (
            <Component {...props} style={{ position: "sticky", top: "50vh" }} />
        )
    }
}

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.