Apple Watch Website in Framer

Apple Watch Website in Framer

Animation

Apple Watch Website in Framer

I recreated the Apple Watch website in Framer, using very little code (almost none). Feel free to remix this project and see for yourself how capable Framer is. Explore how far you can go with this tool in terms of building complex animations and effects.

image of Nandi Muzsik

Created by

Apple Watch Website in Framer
Apple Watch Website in Framer
Apple Watch Website in Framer

About the resource

This website is 99% no-code. The only element that required code is the 3D render video that begins playing as you start scrolling down the page.

For this, I used the video component in Framer and applied a code override to it. I've provided the code below for you to copy and use in your projects.

Video scroll scrub override

You can also copy this code to create a code override from scratch in your project, which will enable the video to progress as you scroll down the website.

About the resource

This website is 99% no-code. The only element that required code is the 3D render video that begins playing as you start scrolling down the page.

For this, I used the video component in Framer and applied a code override to it. I've provided the code below for you to copy and use in your projects.

Video scroll scrub override

You can also copy this code to create a code override from scratch in your project, which will enable the video to progress as you scroll down the website.

About the resource

This website is 99% no-code. The only element that required code is the 3D render video that begins playing as you start scrolling down the page.

For this, I used the video component in Framer and applied a code override to it. I've provided the code below for you to copy and use in your projects.

Video scroll scrub override

You can also copy this code to create a code override from scratch in your project, which will enable the video to progress as you scroll down the website.

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 = 0
    const distance = 6000
    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 = 0
    const distance = 6000
    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 = 0
    const distance = 6000
    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} />
    }
}

Framer Navigator

Learn the fundamentals of Framer for free.

Build your ideas with ease by learning the basics of website building with Framer.

Nandi portrait's background
Nandi's portrait

Framer Navigator

Learn the fundamentals of Framer for free.

Build your ideas with ease by learning the basics of website building with Framer.

Nandi portrait's background
Nandi's portrait

Framer Navigator

Learn the fundamentals of Framer for free.

Build your ideas with ease by learning the basics of website building with Framer.

Nandi portrait's background
Nandi's portrait

More resources

More resources

    3D Staircase Scroll Animation in Framer

    3D Staircase Scroll Animation in Framer

    Animation

    3D Staircase Scroll Animation in Framer

    3D Staircase Scroll Animation in Framer

    Animation

    3D Staircase Scroll Animation in Framer

    3D Staircase Scroll Animation in Framer

    Animation

    Interactive 3D Hero Animation in Framer

    Interactive 3D Hero Animation in Framer

    Animation

    Interactive 3D Hero Animation in Framer

    Interactive 3D Hero Animation in Framer

    Animation

    Interactive 3D Hero Animation in Framer

    Interactive 3D Hero Animation in Framer

    Animation