# Ripple Grid

> A faint square grid of thin lines behind a page's content. A click or a tap on the parent sends a ring out from that point: as the wave passes, the lines bend outward and brighten a little toward the primary colour; the ring widens, fades, and the grid lies flat again. Several rings add up where they cross.

Source: https://ngwr.dev/animations/ripple-grid  
Kind: Animation, Component, Canvas  
Added in v15.7

## Installation

Import the class, and `@use` the entry point in your global styles. Nothing warns you when the `@use` is missing.

```typescript
import { Component } from '@angular/core';
import { WrRippleGrid } from 'ngwr/animations/ripple-grid';

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

```scss
@use 'ngwr/animations/ripple-grid';
```

## Basic

Put `<wr-ripple-grid />` first inside the region it should fill. The parent takes the click, passively and never stopped, so a link or a button over the grid works as before and still starts a ring under the pointer; a keyboard activation is a click with no point and rings nothing. One 2D canvas, drawn on the CPU every frame while something moves and idle otherwise: the frame loop runs only while a ring is alive, on screen and with the document visible; at rest the flat grid is drawn once, as straight lines.

```angular-html
<main class="not-found">
  <wr-ripple-grid />
  <wr-result-404 />
</main>
```

## The parent

The host is absolute, `inset: 0`, at `z-index: -1`, under no pointer and masked out at the edges. The parent provides two things: it is positioned, so the host fills it, and isolated, so the host's negative z-index lands at the floor of the parent's own stacking context, under the content and over the page background.

```scss
.not-found {
  position: relative;
  isolation: isolate;
}
```

## Spacing

`spacing` is the distance between two grid lines, in px, 32 unset; the grid is centred, so the margins at the edges are equal. A finer grid bends in more places as the wave passes, a coarser one reads as a few lines moving. The two colours are the `--wr-ripple-grid-ink` and `--wr-ripple-grid-glow` hooks, set on the host, where the defaults are declared, and read through `resolveCssColorChannels` and re-read when the scheme changes. The wave's speed, band, height and life are the model's numbers, not inputs.

```angular-html
<wr-ripple-grid spacing="20" />
<wr-ripple-grid spacing="48" />
```

## Accessibility

| Part | Behaviour |
| --- | --- |
| Screen readers | Decorative: the host is `aria-hidden`, holds no text, takes no pointer and is never focusable. The click listener on the parent is passive and stops nothing, so every control over the grid behaves as before. |
| Reduced motion | Under `prefers-reduced-motion: reduce` only the flat grid is drawn and a click rings nothing; a preference that flips mid-flight drops the live rings at once. |
| Contrast | A line shows its ink at a fifth, so the text over the grid reads as it does on the plain surface. Under `forced-colors: active` nothing is drawn. |
| Server | The server renders the empty canvas, absolutely positioned, so the browser's first draw shifts no layout. |

## API

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `spacing` | Distance between two grid lines, in px. | `number` | `32` |

## 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/ripple-grid` declares each default on its own element.

| Variable | Default | Declared on |
| --- | --- | --- |
| `--wr-ripple-grid-glow` | `var(--wr-color-primary)` | `.wr-ripple-grid` |
| `--wr-ripple-grid-ink` | `var(--wr-color-on-surface-muted)` | `.wr-ripple-grid` |

## See also

- [Dot Grid](https://ngwr.dev/animations/dot-grid) — An even field of small, faint dots behind a section's content.
- [Result](https://ngwr.dev/reference/components/result) — A full-size outcome screen, with ready-made 404, 403 and 500 pages.
- [Motion](https://ngwr.dev/guides/tokens/motion) — Easing and duration tokens for your transitions and animations.
