Scroll animation website performance: how premium scroll motion stays at 60fps
Scroll animation website performance comes down to one rule: motion that only changes transform and opacity runs on the GPU compositor and costs almost nothing, while motion that changes size, position, or shadows forces the browser to recompute layout on every scroll tick and stutters. A scroll-driven site can hold a steady 60fps on a mid-range phone if it is engineered around that rule, and it will lag on a flagship laptop if it is not. This article explains how premium scroll motion is built to stay smooth: compositing, scrubbed video done properly, lazy loading of heavy scenes, reduced-motion handling, and the Core Web Vitals impact. It ends with an audit you can run in your browser and five questions that expose whether an agency engineers motion or fakes it.
Scroll animation is free on the compositor and expensive on the main thread
A browser draws a page in stages: it computes layout (where every box sits), paints pixels into layers, then composites those layers onto the screen. The compositor runs on its own thread and can move, scale, rotate, and fade a layer without asking the main thread for anything. So a scroll effect built from transform and opacity keeps animating even while JavaScript is busy. The Chrome team demonstrated this with a deliberately heavy main-thread workload: scroll-event listener animations froze, while native scroll timelines kept moving.
Everything else is expensive. Animating width, height, top, left, margin, box-shadow, font-size, or a CSS custom property forces layout or paint on every frame. At 60fps each frame has a budget of roughly 16 milliseconds, and a single layout pass on a complex page can eat most of it. That is where the jerky, delayed parallax you have seen on agency sites comes from. It is not too much animation. It is the wrong kind of animation.
- Rule one: only transform and opacity change per scroll tick. Everything else is set once, before the scene starts.
- Rule two: the scroll position is read once per frame, never inside a loop that also writes to the DOM, or the browser is forced into repeated layout recalculations.
- Rule three: promote animated elements to their own layer with will-change: transform sparingly, and only for the duration of the scene. Too many layers costs memory, especially on phones.
Scrubbing a raw video element on scroll is why most scroll video stutters
The hero effect buyers ask for most is scrubbed video: a product shot or film that plays forward and backward as the visitor scrolls. The naive build sets video.currentTime from the scroll position. It stutters because seeking a compressed video means decoding from the nearest keyframe forward, and browsers throttle how often they honor a seek. On iOS Safari the result is often a frozen frame with occasional jumps.
Done right, scroll video is one of three things. The first is an image sequence: a few hundred frames exported as compressed images, decoded once, then drawn to a canvas at the frame matching the scroll position. This is the most reliable across browsers and the heaviest in bytes, so it needs aggressive compression and lazy loading. The second is a video encoded with a keyframe on every frame (an all-intra encode), which makes seeking cheap enough to scrub, at the cost of a larger file. The third is a WebGL or Canvas scene rendered live, which is the lightest to download and the most demanding to engineer.
Whichever route is chosen, the scroll position should not drive the frame directly. A good implementation interpolates toward the target frame across a few animation frames, so fast scrolling produces smooth motion instead of skipped frames. The site you are reading this on is a scroll-driven example of the craft.
Heavy scroll scenes must be lazy loaded or they wreck the load time
An image sequence for a single hero scene can easily reach 10 to 30 megabytes at desktop resolution. Loaded up front, that pushes Largest Contentful Paint (LCP) into the red and drains mobile data. Engineered sites treat these assets as a budget problem, not a download.
- Serve a single poster frame as the LCP image, preloaded, so the page looks finished within a second while the sequence loads behind it.
- Fetch the sequence in priority order: the first 10 to 20 frames immediately, the rest as the visitor approaches the scene, using IntersectionObserver with a generous root margin.
- Serve smaller frame sets to phones. A 1920px sequence on a 390px-wide screen is wasted bandwidth and wasted decode time.
- Use modern formats such as AVIF or WebP for sequences and a modern codec for video, with fallbacks.
- Scenes below the fold load only when they are about to enter view, never on page load.
A reasonable target for a cinematic homepage is that the first screen is interactive in under two seconds on a 4G connection, with heavy scenes streaming in afterward. If an agency cannot tell you what their pages weigh, they have not measured. The related question of what these builds cost is covered in how much a custom website costs.
Use the lightest tool that does the job: class toggle, then CSS timelines, then ScrollTrigger
Most scroll effects on most sites are reveals: an element fades and slides in as it enters the viewport. That needs no library. An IntersectionObserver toggles a class, a CSS transition on transform and opacity does the rest, and the cost is close to zero. Choosing a heavier tool for this is a sign the builder reaches for the familiar rather than the right.
Native CSS scroll-driven animations (the animation-timeline property with scroll() and view() timelines) are the next step up. They link an animation's progress to scroll position with no JavaScript, and they run off the main thread when animating transform and opacity. They are the right choice for parallax, progress bars, and scroll-linked reveals. Support has landed in Chromium browsers and Safari, and Firefox has been catching up, so check current browser support at build time and ship a fallback: wrap the CSS in @supports (animation-timeline: scroll()) and detect the same property in JavaScript before relying on it.
GSAP ScrollTrigger earns its weight for the hard cases: pinned sections, horizontal scroll, choreographed timelines with many elements, and scrubbed canvas scenes. Its scrub option smooths scroll input, and its pinning is more robust than hand-rolled sticky positioning. The costs are a JavaScript dependency, main-thread work per frame (still cheap if you animate transforms only), and the discipline to kill triggers on route change in single-page apps or memory leaks follow. Framer Motion covers similar ground for React teams with a smaller feature set for scroll choreography.
Smooth-scroll libraries (Lenis, Locomotive Scroll) deserve caution. They hijack native scrolling to add inertia, which is the single most common cause of the floaty, laggy feel people complain about. They also interfere with keyboard scrolling, find-in-page, and assistive technology. If a site uses one, it should be the deliberate choice of someone who has measured the trade, not the default.
Each scroll effect carries a specific Core Web Vitals risk, and each has a fix
Google's Core Web Vitals do not penalize animation. They penalize slow LCP, layout shift (CLS), and slow interaction response (INP). Scroll motion touches all three in predictable ways.
- Reveal effects: elements that start at opacity: 0 can delay or hide the LCP candidate. Fix: the hero text and hero image are visible on first paint, and reveals apply only below the fold.
- Pinned sections: pin spacing added by JavaScript after load shifts everything below it. Fix: reserve the pin height in CSS before the script runs.
- Parallax: images translated outside their container force repaint if they are not on their own layer. Fix: transform only, with overflow clipping on the parent.
- Horizontal scroll sections: these often stall INP because scroll handlers do layout reads. Fix: measure once on resize, cache widths, animate with transform.
- Video scrubbing: decode work on the main thread blocks input. Fix: pre-decoded frames on canvas, or an all-intra encode, and interpolation as described above.
Does a heavy scroll site hurt rankings? Not because of the motion itself. It hurts if the motion drags LCP past 2.5 seconds or CLS above 0.1, and an engineered build stays inside those thresholds. Whether the effects earn their keep commercially is a separate question, covered in when cinematic website design pays off.
Mobile is where scroll performance is won or lost
Most agency demos run on a fast Mac. Most of your visitors are on a phone with a fraction of the CPU, thermal throttling after a minute of use, and a browser that manages memory aggressively. Every technique above matters more here.
- iOS Safari resizes the viewport as the address bar collapses. Scenes sized with 100vh jump; use 100dvh or measure once and lock the height.
- Touch scrolling has momentum. Scrubbed scenes must handle very fast position changes without skipping, which is what interpolation is for.
- High refresh displays (90Hz and 120Hz) shrink the frame budget. Motion that just fits at 60fps on desktop will drop frames on a modern phone unless it stays on the compositor.
- Layer count matters more. Too many will-change promotions exhaust GPU memory and Safari will silently drop them.
- Test on a real mid-range Android and an older iPhone, not just the DevTools throttle.
Reduced motion means reducing motion, not switching the site off
Scroll-linked motion can trigger vestibular symptoms: nausea, dizziness, headaches. The operating system exposes a preference for it, and the CSS query prefers-reduced-motion reads it. A lazy build ignores it. A slightly better build hides every animation and leaves a broken, empty-looking page. A properly engineered build swaps large translations and parallax for simple fades, freezes scrubbed video on its best frame, and keeps the layout intact.
Keyboard and screen reader users also need pinned sections to remain reachable. Focus should never get trapped in a pinned scene, tabbing should move through content in reading order, and anything revealed by scroll must exist in the DOM for assistive technology whether or not the animation has played. These are cheap to get right during the build and expensive to retrofit.
A ten-minute audit anyone can run on a live site
You do not need to be an engineer to check an agency's claims. Open one of their live sites in Chrome and use the built-in tools.
- Open DevTools, go to the Performance panel, enable 4x CPU throttling, record while scrolling the full page, and stop. Long red bars in the main track are dropped frames.
- In the same panel, look at the frames chart. Steady green at 60fps is engineered; frequent dips or a sawtooth is not.
- Open the Rendering panel and enable paint flashing. Scroll. Large areas flashing green on every tick mean paint work that should be on the compositor.
- Enable layout shift regions in the same panel. Blue flashes during scroll are CLS you will pay for.
- Open the Layers panel and count the layers. Dozens of promoted layers on a phone-sized viewport is a memory problem waiting to happen.
- Run Lighthouse on mobile. LCP above 2.5 seconds or CLS above 0.1 on a marketing homepage is a fail.
- Turn on reduced motion in your OS and reload. The site should still be complete and readable.
- Tab through the page with the keyboard. If focus vanishes inside a pinned section, accessibility was not engineered.
- Open the site on a mid-range phone over mobile data. Note how long until the first screen is usable.
- Scroll fast, then slowly, then reverse. Scrubbed scenes should follow without jumps in either direction.
Five questions expose whether an agency engineers motion or fakes it
- What properties do your scroll effects animate, and how do you keep them on the compositor? The answer should be transform and opacity, with specifics.
- How do you build scrubbed video, and how does it behave on iOS Safari? Look for canvas frame sequences or all-intra encodes and interpolation, not currentTime.
- What does your homepage weigh, and what loads before the first screen is interactive? They should have numbers.
- What happens when a visitor has reduced motion enabled? The answer should describe a reduced experience, not a disabled one.
- Which real devices do you test on, and what are your Core Web Vitals on the last three sites you shipped?
Kaev builds cinematic websites on exactly these principles.
Common questions
Do scroll animations slow down a website?
Only when they are built wrong. Effects that animate transform and opacity run on the GPU compositor and cost almost nothing. Effects that change size, position, shadows, or fonts force layout and paint on every scroll tick and cause visible stutter. The design does not decide the performance; the implementation does.
Do scroll animations hurt SEO or Core Web Vitals?
Not directly. Google measures LCP, CLS, and INP, not animation. Scroll effects hurt those scores when hero content starts hidden, pinning shifts layout after load, or scroll handlers block input. An engineered build keeps LCP under 2.5 seconds and CLS under 0.1 with the effects intact.
How do you make scroll-scrubbed video smooth?
Avoid seeking a normal video element. Use a pre-decoded image sequence drawn to canvas, or a video encoded with a keyframe on every frame, and interpolate toward the target frame rather than jumping to it. Lazy load the frames and serve smaller sets to phones.
Should I use GSAP ScrollTrigger or CSS scroll-driven animations?
Use the lightest tool that works. A class toggle with IntersectionObserver covers simple reveals. Native CSS scroll timelines handle parallax and progress effects with no JavaScript, with a fallback for browsers that lack support. ScrollTrigger is worth its weight for pinning, horizontal scroll, and choreographed scenes.
What is a good frame rate for scroll animation on mobile?
A steady 60fps with no dropped frames under CPU throttling, and no stalls on 120Hz phones. Test on a real mid-range Android and an older iPhone, because a fast laptop hides nearly every problem.
If you want a scroll-driven site that holds 60fps on a phone and passes Core Web Vitals, tell us about the project and we will scope it on a 30-minute call.