Reveal
Content that arrives as it scrolls into view.
On this page
A reveal is content that arrives as it scrolls into view: it fades in and rises the last few pixels while its first stretch crosses the edge of the viewport, and is at rest from then on. It is one class and a scroll-driven animation. Nothing observes the element and no class is added to it: the position of the scroll is the clock.
Reveal
<div class="flex flex-col gap-md max-w(420) mx-auto"> <p class="m(0) fg-text-muted text-sm text-center py-xl">Scroll down</p> <article class="card mt(240)"> <header class="card-header"> <h3 class="card-title">Native first</h3> <p class="card-description">Every overlay is a dialog or a popover, opened without script.</p> </header> </article> <article class="card reveal"> <header class="card-header"> <h3 class="card-title">One material</h3> <p class="card-description">Surfaces step apart on a ladder of light, in both themes.</p> </header> </article> <article class="card reveal"> <header class="card-header"> <h3 class="card-title">Contracts</h3> <p class="card-description">Each stylesheet says what it promises in a file beside it.</p> </header> </article> <article class="card reveal" style="--reveal-scale: .96"> <header class="card-header"> <h3 class="card-title">Yours to change</h3> <p class="card-description">Tokens retune every component; the source is there to own.</p> </header> </article> <p class="m(0) fg-text-muted text-sm text-center py-xl">The end</p></div>#How it works
The element's animation runs on its own view timeline, animation-timeline: view(), over the range in which it enters the scroller. Three consequences follow from the scroll being the clock:
- What is already in view when the page opens does not move at all: its entry is over before the first frame.
- Scrolling back plays the animation backwards. Nothing has to be reset.
- There is no delay to tune and nothing to stagger: elements that enter one after another arrive one after another.
The animation is finished within the first 12rem of the element entering, set by --reveal-range, so a tall section does not fade for a whole screen. An element shorter than that has arrived once all of it is in view, which means the last thing on a page always arrives.
#Tuning
Three properties tune it, on the element or on a parent of several:
--reveal-distanceis how far it rises, 16px by default. Set0for a fade alone.--reveal-scaleis the size it arrives from..96suits a picture or a card; text should not be scaled.--reveal-rangeis how much of the element has entered when it has arrived.
#When to use it
Use a reveal on whole blocks of a long page: a section of a landing page, a row of cards, a figure. Use it sparingly. A page on which everything arrives is a page on which nothing is at rest, and a reader who scrolls fast waits for it.
Do not put it on text a reader needs at once, on anything inside a dialog or a menu, or on content that changes size as it loads.
#Without scroll-driven animations
In a browser without animation-timeline: view(), and for a reader who asks the system for reduced motion, the class does nothing and the content is simply there. The same holds in print. So the content never depends on the animation: no opacity is set outside it.
#Accessibility
- The content is in the document and in the accessibility tree from the start; only its opacity and its position change while it enters.
- With
prefers-reduced-motion: reducethere is no fade and no travel. - Keep the travel small. A large distance on a large block is motion across much of the viewport, which some readers find hard to look at.
#Classes
| Class | Description |
|---|---|
reveal | An element that fades in and rises 16px while its first stretch enters the viewport, and is at rest from then on |
#Custom properties
| Property | Default | Description |
|---|---|---|
--reveal-distance | 1rem | How far it rises; 0 for a fade alone |
--reveal-scale | 1 | The size it arrives from, such as .96 for a picture |
--reveal-range | 12rem | How much of the element has entered when it has arrived; an element shorter than this has arrived once all of it is in view |