View Timeline Reveal
Scroll reveals on a real CSS view timeline — off the main thread, and visible by default where it is not supported.
- Category
- Animations
- Added
- 2026-09-21
- Deps
- none
- Updated
- 2026-09-21
This is a viberdy Pro component
The live preview, the props panel and the write-up are open to everyone. The full source, the AI prompt and CLI install are part of Pro.
Props
"use client";
import { useId, type ReactNode } from "react";
/**
* Scroll-linked reveals on a CSS VIEW TIMELINE — no observer, no rAF, no JS at
* all once the stylesheet is in.
*
* The reason to reach for this over an IntersectionObserver is not tidiness:
* scroll-driven animations are driven off the main thread. A JS reveal competes
* with hydration, image decode and everything else on the thread, which is
* exactly when a long page is being scrolled fast.
*/
export function ViewTimelineReveal({
children,
distance = 28,
start = 8,
end = 34,
// ---------------------------------------------------------------
// Full source available with a viberdy Pro subscription.
// https://viberdy.dev/pricing
// ---------------------------------------------------------------
}About this animation
Scroll reveals have been an IntersectionObserver and a class toggle for a decade, and CSS scroll-driven animations replace both — not because they are tidier but because they are driven off the main thread, which matters precisely when a long page is being scrolled quickly and the thread is busy with hydration and image decode. Using them well comes down to one rule about where the hidden state lives. The tempting shape is to set opacity to zero on the element and let the animation bring it back; that turns every browser without support into a page of invisible content, which is the worst outcome a progressive enhancement can produce. Confining the start state to the animation's own from-keyframe, filling in both directions, and wrapping the declaration in a feature query inverts it: the element is visible by default and the hidden state only ever exists where the animation actually runs. The range is expressed with the named timeline ranges rather than pixels, so it stays correct at every viewport size, and the whole declaration sits inside a reduced-motion query so the animation is opt-in — which means reduced motion needs no separate branch at all, since the element is already visible and simply stays that way. Class and keyframe names are scoped per instance, or two wrappers with different ranges quietly share one timing.
Curator’s note
Put opacity:0 on the element instead of in the keyframe and every unsupported browser gets a blank page. That is the whole lesson.
Pairs well with
Matched on shared tags and category — the entries most likely to be used alongside this one.
Stagger Reveal Group
animationsA wrapper that reveals its children one after another as the group scrolls into view.
Vertical Timeline Reveal
sectionsA scroll-triggered vertical timeline whose dots and cards reveal in sequence.
Scroll-Linked Image Mask Reveal
sectionsAn image whose circular clip-path mask grows and shrinks in lockstep with scroll.