import { Component } from '@angular/core';
import { WrFallingLetters } from 'ngwr/animations/falling-letters';
@Component({ imports: [WrFallingLetters] })
export class MyComponent {}Falling Letters
Click a line of text and its letters let go: each one drops with gravity, drifts and tumbles a little, and lands on whatever already lies under it, so the letters pile into a heap on the floor of a container. Click again, or wait, and every letter springs back to its place.
Installation
Import the class, and @use the entry point in your global styles. Nothing warns you when the @use is missing.
Basic
Put wrFallingLetters on the element that holds the text. The floor and the walls are the content box of the host's parent, measured when the fall starts, so give the line a container with room under it. No physics engine: a letter's path is gravity plus a drift and a spin drawn from a fixed sequence by its index, so the same text falls the same way every time. Letters meet on the floor, a letter that lands fast hops once or twice, and the heap lies still for rest ms, 4000 unset, before springing back.
<section class="arena">
<p wrFallingLetters>Click this line and watch it fall.</p>
</section>A descendant as the target
A selector as the directive's value points it at one descendant of the host instead, for a paragraph a library component draws. The target is looked up once after the first render by its public BEM class; a selector that matches nothing turns the effect off.
<wr-result-404 wrFallingLetters=".wr-result__description" />Floor
floor is a selector for the element whose content box is the floor and the walls, found with closest from the host; unset, the host's parent. On a display: contents host that is the box around it. On a wr-* host write it as a binding, since a static attribute that is not one of the component's inputs fails check:attrs.
<main>
<p wrFallingLetters [floor]="'main'" rest="2000">Lands on the floor of <code>main</code>.</p>
</main>Accessibility
| Part | Behaviour |
|---|---|
| Screen readers | The authored nodes are moved into an invisible wrapper that holds exactly their space, still the real text for a screen reader and the clipboard. The pieces are aria-hidden, out of the selection and under no pointer, so a button a letter falls across stays clickable. |
| Reduced motion | Under prefers-reduced-motion: reduce a click does nothing, and a preference that flips mid-fall puts the text back at once. The demos on this page follow the same setting. |
| Layout | The line never moves: the pieces are positioned from the target's own box and move by transform alone, so nothing under them reflows. When the last letter is back, the same node objects go back where they were, so a binding inside the text keeps working. |
| Server | Nothing happens on the server or when the target has no box. The click listener is added in the browser, after the first render. |
API
| Name | Description | Type | Default |
|---|---|---|---|
wrFallingLetters | A selector for one descendant of the host whose letters fall instead of the host's own, written as the directive's value: wrFallingLetters=".wr-result__description". Resolved once after the first render with querySelector; a selector that matches nothing turns the effect off. Unset or empty, the host. | string | null | null |
floor | A selector for the element whose content box is the floor and the walls, found with closest from the host. Unset, the host's parent element: on a display: contents host that is the box around it. On a wr-* host write it as a binding ([floor]="'main'"), since a static attribute that is not one of the component's inputs fails check:attrs. | string | null | null |
rest | How long the heap lies still before the letters spring back on their own, in ms. | number | 4000 |
See also
Animation GlitchA short piece of text that looks like a broken signal while the pointer is over it: two tinted copies cut into thin slices jump sideways while the text leans a little, and the moment the pointer leaves everything snaps back clean.Component ResultA full-size outcome screen, with ready-made 404, 403 and 500 pages.Guide MotionEasing and duration tokens for your transitions and animations.