Opens in a new tab

Guide

Scroll animations with CSS and JavaScript: how a CSS scroll animation works, with or without a script

How scroll animations work in CSS and JavaScript: scroll-timeline, IntersectionObserver, SVG on scroll, and what you can skip by setting them in Bricks instead.

John Diaz · Updated October 2026 ·

On this page

If you build in Bricks, you can skip the code: scroll animations are a setting in the panel. This guide is for understanding what happens underneath — and for sites that are not built in Bricks at all.

Scroll animations in CSS and HTML: what actually moves when the page scrolls

Until scroll-driven animations landed, CSS had no way to react to the scroll on its own: something had to turn scroll position into a value the style could use — a class that gets added, a custom property that gets written — and that is still the compatible way to do it today. Newer browsers can also keep a scroll timeline themselves. Either way, the motion is ordinary CSS.

Three ways to animate on scroll: a CSS class toggled by a script, CSS scroll-timeline, or full JavaScript

ApproachWhat drives itWhere it falls short
Class toggled by a scriptIntersectionObserver adds a class when the element appearsPlays once; it does not follow the scroll
CSS scroll-timelineThe browser ties keyframes to scroll progressSupport is still partial; needs a fallback
Full JavaScriptYour code reads scroll position every frameMost work, and the easiest to make janky

CSS scroll-driven animations with animation-timeline: scroll() and view()

With animation-timeline the browser drives the keyframes from the scroll itself. view() runs the animation while the element crosses the screen; scroll() follows the whole page.

@keyframes reveal {
  from { opacity: 0; translate: 0 40px; }
  to   { opacity: 1; translate: 0 0; }
}

.card {
  animation: reveal linear both;
  animation-timeline: view();
  animation-range: entry 0% cover 40%;
}

It is the cleanest version of a scroll animation — no script at all — and the catch is support: it is not in every browser your visitors use yet, so plan what happens where it is missing.

JavaScript scroll: IntersectionObserver vs scroll events, and when a script is still needed

For a reveal that plays once, an IntersectionObserver is enough and cheap: the browser tells you when the element enters the screen, and you add a class.

const io = new IntersectionObserver((entries) => {
  entries.forEach((e) => {
    if (!e.isIntersecting) return;
    e.target.classList.add('is-in');
    io.unobserve(e.target);   // plays once
  });
});
document.querySelectorAll('.card').forEach((el) => io.observe(el));

For motion that follows the scroll — a sticky scene, a card stack, a video that scrubs — you need the scroll position itself, read on every frame and written into a custom property the CSS reads back.

Scroll down animations: reveals, fades and indicators that fire as the page moves

The everyday case is a reveal: fade, slide or zoom, once, as the element arrives. Keep them short and keep the content in the HTML. Fade, slide and zoom reveals are the same shape underneath — transform and opacity, driven by a class — while a mask reveal animates clip-path instead.

SVG animation on scroll: move, scale and reveal vector graphics (path drawing is not included)

An SVG is an element like any other: it moves, scales and reveals on scroll the same way. What is a different job is drawing a path — animating stroke-dashoffset so a line draws itself. Fancy Animations does not do that one; it needs its own CSS.

Build it in Bricks without code: ScrollTrigger classes with from/to, start/end, parent and a CSS-sticky stage

Do it without code

The same three approaches, as panel settings

In Bricks the reveal, the scroll-driven motion and the sticky scene are all controls: pick an animation, set from and to, start and end, and tick Covered by next sibling for a sticky card stack, or Sequence children when children should take turns. The stage itself you pin with CSS position: sticky.

Control: from / to, start / end

Animations without GSAP: a lighter alternative and what you give up

GSAP with ScrollTrigger is a timeline engine: sequencing, easing curves, scrub, snap, complex scenes choreographed in code. What most sites actually need is a few reveals and one sticky scene. Fancy Animations covers that with CSS and two small scripts, about 10 KB gzipped together, from the panel.

What you give up is the timeline: if your scene needs several elements choreographed against each other in code, a library is still the right tool — beyond what Sequence children and stagger already cover.

Scroll animations and Core Web Vitals: the pitfalls that cost you

Three things cost real points, and all three are avoidable. Content hidden by default and revealed by script: if the script is slow or blocked, the page is empty. Layout shift: animating width, height or top makes the browser lay the page out again — animate transform and opacity instead. Main-thread work: heavy per-frame JavaScript competes with everything else the page is doing.

Browser support: why Fancy Animations does not depend on experimental CSS

animation-timeline is the future of this, and it is not evenly supported yet. A plugin that relied on it would work beautifully in some browsers and not at all in others, so Fancy Animations drives CSS with its own small script: the same result everywhere, today.

Go further: scroll animations for Bricks, Etch and Gutenberg

Scroll animations shows every control live, sticky scenes and stacked cards is the scene people ask for most, and the template library has them built.

Stacked cards template
Stacked cards — the sticky scene from this guide, already built Open the template

What is it called when a website moves as you scroll?

Scroll-driven or scroll-triggered animation; when layers move at different speeds it is called parallax. This guide covers the CSS and JavaScript behind both.

Can I do scroll animations with CSS only?

Yes, with animation-timeline: scroll() and view(), but browser support is still uneven. A tiny script that toggles classes or sets a CSS variable works everywhere today.

Is GSAP the best animation library?

It is the most complete, but most Bricks sites need a few reveals and a sticky scene, not a timeline engine. CSS plus two small scripts, about 10 KB gzipped together, covers that without the weight or the learning curve.

Do scroll animations hurt SEO or Core Web Vitals?

Only when content starts hidden, layouts shift or heavy JavaScript blocks the main thread. Keep content visible by default, animate with transforms and opacity, and keep scripts small.

Can I animate an SVG path drawing itself on scroll?

Not with Fancy Animations: it moves, scales and reveals SVG like any element, but stroke-dashoffset drawing needs custom code. The guide shows where that line is.

How do I start a scroll animation in Bricks without writing code?

Add the Fancy Animations ScrollTrigger controls to the element: from and to values, start and end positions, and position: sticky on the stage if you need a pinned scene.

Add Bricks Builder animations to your next site

From $179, one payment, every update for life. 14-day refund.