Components
Reveal
Scroll-based viewport entry animations using IntersectionObserver and CSS transitions.
Reveal triggers CSS entry transitions using IntersectionObserver when elements scroll into the viewport.
How it works
- Add
data-revealordata-reveal-eachto HTML elements. - The
Revealscript observes elements and sets calculated CSS delay variables. - When scrolled into view, the element receives the
.in-viewportclass. - CSS transitions in
reveal.cssanimate the element to visible.
Setup
Load index.js as an ES module and include index.css:
<link rel="stylesheet" href="./zazz/index.css" />
<script type="module" src="./zazz/index.js"></script>Reveal initializes automatically when the DOM loads.
Single elements
<div data-reveal="slide-up">Slides up into view</div>
<div data-reveal="fade">Fades in</div>
<div data-reveal="slide-left">Slides in from right</div>Animation types
| Value | Effect |
|---|---|
slide-up | Translate up from below |
slide-down | Translate down from above |
slide-left | Translate left from the right |
slide-right | Translate right from the left |
fade | Opacity fade |
grow | Scale up from smaller |
shrink | Scale down from larger |
Stagger groups
Animate child elements sequentially using data-reveal-each:
<div data-reveal-each="fade" data-reveal-step="100">
<div>Item 1 (first)</div>
<div>Item 2 (100ms delay)</div>
<div>Item 3 (200ms delay)</div>
</div>Set data-reveal-order="reversed" to animate children in reverse order.
Element transition isolation
Reveal controls transition-* properties to handle delays and durations. To apply hover transitions (such as borders or background changes) without conflicting with scroll reveals, place the reveal attribute on a parent container:
<div data-reveal-each="slide-up">
<a class="bg-card border rounded-md transition hover:border-primary">Card 1</a>
<a class="bg-card border rounded-md transition hover:border-primary">Card 2</a>
</div>Configuration attributes
| Attribute | Default | Purpose |
|---|---|---|
data-reveal-duration | --ui-reveal-global-duration | Animation duration |
data-reveal-wait | 0 | Base delay before starting (ms) |
data-reveal-step | 80 | Delay step between children (ms) |
data-reveal-ease | --ui-reveal-global-ease | Timing function |
data-reveal-distance | 1rem | Slide translation distance |
data-reveal-scale | None | Scale value for grow/shrink |
data-reveal-margin | 0px | Observer rootMargin |
data-reveal-threshold | 0.2 | Intersection threshold (0 to 1) |
data-reveal-order | None | Set to "reversed" for reversed stagger sequence |
Global tokens
:root {
--ui-reveal-global-duration: var(--default-transition-duration);
--ui-reveal-global-ease: var(--default-transition-timing-function);
--ui-reveal-global-wait: 0ms;
--ui-reveal-global-distance: 1rem;
--ui-reveal-global-grow: 0.97;
--ui-reveal-global-shrink: 1.03;
}Dynamic updates
To observe newly inserted DOM elements:
Reveal.getAutoInstance()?.refresh();