import { Component } from '@angular/core';
import { WrReveal } from 'ngwr/animations/reveal';
@Component({ imports: [WrReveal] })
export class MyComponent {}Reveal
A headline whose letters rise into place one after another from first paint, with no script: built for above the fold, where the server HTML already holds the pieces and the motion starts before the bundle arrives.
Installation
Import the class, and @use the entry point in your global styles. Nothing warns you when the @use is missing.
Basic
<wr-reveal> is inline, so it sits inside your heading and takes its font. Pass the text as text: it is split into graphemes in the template, each piece carries its index, and the stylesheet turns that into a delay. When the last piece lands the pieces are swapped for the plain text, so the headline at rest is exactly the text it would have been.
<h1><wr-reveal text="Components that bind straight to Signal Forms." /></h1>Words
by="words" rises one word at a time, 70 ms apart instead of 28.
<h1><wr-reveal text="One word at a time." by="words" /></h1>Masked
masked clips each word at a padded line box, so a letter comes up from under the line instead of fading in where it stands. Descenders and accents at rest sit inside the padding.
<h1><wr-reveal text="Up from under the line." masked /></h1>One sequence from several runs
A headline with markup inside it is several runs. Give each run the count of pieces before it as start, and they play as one sequence. An inline element that is not text, a logo chip, joins the sequence as class wr-reveal__item with --wr-reveal-i set inline. A sequence longer than 1.2 s shrinks its gap; set the same stagger on every run so the gap is one gap.
<h1>
<span class="wr-reveal__item" style="--wr-reveal-i: 0"><wr-tag>Angular</wr-tag></span>
<wr-reveal text="components for" start="1" />
<em><wr-reveal text="Signal Forms" start="15" /></em>
</h1>On scroll
trigger="view" keeps the pieces visible and plays them the first time most of the host is in the viewport, for a heading further down the page. load, the default, plays from first paint. The offset, the duration and the easing are CSS variables.
<h2><wr-reveal text="Plays when it scrolls into view." trigger="view" /></h2>h1 .wr-reveal {
--wr-reveal-offset: 0.5em;
--wr-reveal-duration: 0.8s;
}Accessibility
| Part | Behaviour |
|---|---|
| Screen readers | While the pieces play they are aria-hidden, and a visually hidden copy of the text stands beside them, so the headline is announced once. At rest the host holds the plain text. |
| Reduced motion | Under prefers-reduced-motion: reduce the stylesheet plays nothing and the host swaps to the plain text at once. The demos on this page follow the same setting. |
| Server and no script | The pieces are in the server HTML and the animation is CSS, so it starts at first paint and runs on through hydration. Without script the pieces simply end fully visible. |
| Wrapping | The letters of one word sit in a no-wrap wrapper and the spaces between words stay real text, so the lines break where plain text would. |
API
| Name | Description | Type | Default |
|---|---|---|---|
textrequired | The text of this run. Breaking spaces stay real spaces, so it wraps as plain text would. | string | — |
by | What enters one at a time: a grapheme, or a word. In letter mode the letters of one word sit in a no-wrap wrapper, so a word never breaks across lines mid-word. | WrStaggerBy | 'letters' |
masked | Each word clips its pieces at a padded line box, so a letter comes up from under the line instead of fading in where it stands. Descenders and accents at rest sit inside the padding. | boolean | false |
start | The index of this run's first piece. A headline made of several runs passes each one the count the runs before it used, so they play as one sequence. | number | 0 |
stagger | Gap between the start of one piece and the next, in ms. Unset, the mode decides: 28 for letters, 70 for words. Either way the sequence up to this run's last piece spreads over 1.2 s at most; a long sequence of several runs sets the same stagger on each, so the gap is one gap. | number | null | null |
delay | Pause before the first piece of the sequence, in ms. | number | 0 |
trigger | load plays from first paint, with no script. view keeps the pieces visible and arms them the first time most of the host is in the viewport; an __item outside the host does not follow it. | WrRevealTrigger | 'load' |
CSS variables
Set these on the element itself, with a rule more specific than its Declared on selector. In a global stylesheet, put a class of yours on an ancestor it really has: <body> for an overlay panel, which renders outside your markup. In a component stylesheet the selector alone works, but only for an element in that component's own template. A value on a wrapper or :root is shadowed, because ngwr/animations/reveal declares each default on its own element.
| Variable | Default | Declared on |
|---|---|---|
--wr-reveal-delay | 0ms | .wr-reveal and inline on the element, written by the component from its inputs or its state — a rule holds only until the component writes |
--wr-reveal-duration | 0.6s | .wr-reveal |
--wr-reveal-ease | var(--wr-ease-out) | .wr-reveal |
--wr-reveal-gap | 28ms | .wr-reveal and inline on the element, written by the component from its inputs or its state — a rule holds only until the component writes |
--wr-reveal-offset | 0.35em | .wr-reveal +1 variant override |
See also
Animation Blur RevealA text comes in piece by piece the first time it scrolls into view: each word, or each letter, from blurred and a little below its place to sharp and in place.Guide Server-side renderingPrerender and hydrate an ngwr app without mismatches.Guide MotionEasing and duration tokens for your transitions and animations.Component BadgeA small label for a count or a status.