Scroll Reveal

Elements fade in and rise as they enter the viewport — driven by CSS alone.

← All motions

Scroll Reveal

The most requested effect on any landing page, and the one AI builders most often get wrong — they reach for a scroll listener when the browser can do it on the compositor thread for free.

trigger: scroll CSS scroll-driven animations 0 lines of JS

Live demo

Scroll down ↓
01

Section one

Each block fades in and lifts as its top edge crosses into view.

02

Section two

The animation is bound to this panel's scrollport, not to a timer.

03

Section three

Scroll back up and it reverses automatically. There is no state to reset.

04

Section four

That reversibility is what separates scroll-driven animation from a one-shot reveal.

end of panel

The prompt

Add a scroll reveal effect to the page. Each content block should start with opacity 0 and translateY(28px), and animate to opacity 1 and translateY(0) as it enters the viewport.

Implementation requirements:
- Use CSS scroll-driven animations: animation-timeline: view() with animation-range: entry 10% cover 35%. Do not use a scroll event listener.
- Include animation-fill-mode: both so elements are visible before and after the range.
- Add a @supports fallback for browsers without animation-timeline using IntersectionObserver, threshold 0.25.
- Animate only opacity and transform — never top, margin or height.
- Respect prefers-reduced-motion: when reduced motion is requested, show all content immediately with no animation.
- Stagger consecutive blocks by 60ms using animation-delay.
Do not apply this to content above the fold; the first screen must be readable without waiting.

What actually makes it work

Compatibility and performance

BrowserSupport
Chrome / Edge115+ — full support, runs on the compositor
Safari26+ — supported; earlier versions fall back
FirefoxBehind a flag — the fallback path is what users get

Because the fallback exists, this is safe to ship today. The cost of the CSS path is close to zero: no scroll listener, no layout reads, no jank when the main thread is busy. The IntersectionObserver fallback does cost a callback per threshold crossing, which is why the threshold is coarse (0.25) rather than continuous.

When not to use it

Don't animate the first viewport. A visitor who has to wait 400ms to read your headline has already decided the page is slow. Above the fold should be static.

Don't reveal everything. If every paragraph fades in, the page feels like a slideshow and the effect stops signalling anything. Reserve it for distinct sections, two to five per page.

Don't hide content that carries SEO weight. Text that starts at opacity: 0 is still in the DOM and still indexed, but a user who lands mid-page from a search result may see blank space. Anchor jumps and back-navigation should bypass the animation.