Dither
stable 1.4 kB<hk-dither>A Bayer 4×4 threshold matrix over a drifting gradient. Drawn as cells rather than per-pixel on purpose: a true per-pixel dither means writing millions of bytes into an ImageData every frame, which is exactly what makes a background library unusable. A 4px cell is visually identical here and costs a sixteenth.
#background#canvas#decorative
Live demo
Running in this page — interact with it.
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
| color | string | '#dc2626' | Base colour. Any hex the background derives its palette from. |
| speed | number | 1 | Animation multiplier. 0 freezes on the first frame. |
| opacity | number | 1 | Canvas opacity — these sit behind real content. |
| paused | boolean | false | Stops the loop without unmounting. |
| pixelSize | number | 4 | Cell edge in px. Larger is chunkier and cheaper. |
| noise | number | 0.08 | Extra sparkle, 0–1. Hashed per cell, not random per frame. |
| intensity | number | 0.34 | Cell opacity. Dithering stays binary per cell, so subtlety comes from alpha. |
| sparsity | number | 0.34 | Raises the threshold so fewer cells light up. 0–1, higher is sparser. |
Theming
Component tokens, each falling back to a global one:
| Property | Default | Controls |
|---|---|---|
| --hk-bg-color | #dc2626 | Base hue. Every background derives its palette from it. |
Accessibility
- The canvas is aria-hidden — a decorative layer must never be announced.
- Under prefers-reduced-motion it paints one frame and never starts the loop.
- The loop stops when the element scrolls out of view and when the tab is hidden, so an offscreen background costs nothing.
- Frames run outside the Angular zone, so animating never triggers change detection in the rest of the app.