AnimationComponentCSSAdded in v15.7

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.

import { Component } from '@angular/core';
import { WrReveal } from 'ngwr/animations/reveal';

@Component({ imports: [WrReveal] })
export class MyComponent {}

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>

Components that bind straight to Signal Forms.

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>

One word at a time.

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>

Up from under the line.

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>

Angularcomponents forSignal Forms

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;
}

Plays when it scrolls into view.

Accessibility

PartBehaviour
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

NameDescriptionTypeDefault
textrequiredThe text of this run. Breaking spaces stay real spaces, so it wraps as plain text would.string—
byWhat 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'
maskedEach 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.booleanfalse
startThe 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.number0
staggerGap 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 | nullnull
delayPause before the first piece of the sequence, in ms.number0
triggerload 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.

VariableDefaultDeclared on
--wr-reveal-delay0ms.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-duration0.6s.wr-reveal
--wr-reveal-easevar(--wr-ease-out).wr-reveal
--wr-reveal-gap28ms.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-offset0.35em.wr-reveal +1 variant override

See also