import { Component } from '@angular/core';
import { WrIridescence } from 'ngwr/bits/iridescence';
@Component({ imports: [WrIridescence] })
export class MyComponent {}Iridescence
Folded silk behind your content, its hue turning with each fold, stirred by the pointer.
Installation
Import the class, and @use the entry point in your global styles. Nothing warns you when the @use is missing.
Playground
Put it first in a positioned box; it fills that box. Give the content after it a position of its own, or the silk paints over it. Move the pointer across it to stir the folds.
<section style="position: relative; min-height: 18rem; overflow: hidden">
<wr-iridescence
[speed]="1"
[amplitude]="1"
/>
</section>Customize
Behind a hero
Copy goes on a card, because text on the light default needs a card or a scrim (see Text contrast). The pointer still stirs the folds around it, and the card keeps every click.
<section class="hero">
<wr-iridescence />
<wr-card class="hero__card">
<h3>Drape it behind the launch</h3>
<p>The folds stay behind the card, and the button stays clickable.</p>
<wr-btn color="primary">Get started</wr-btn>
</wr-card>
</section>
<style>
.hero {
position: relative;
display: grid;
place-items: center;
min-height: 22rem;
padding: 2rem;
overflow: hidden;
}
.hero__card { max-width: 26rem; text-align: center; }
</style>Tint
color is multiplied over the picture, so white leaves it as it is. It takes any CSS colour, and a theme token follows the colour scheme. Pass an opaque colour: the canvas drops alpha and the stand-in keeps it.
<section style="position: relative; min-height: 12rem; overflow: hidden">
<wr-iridescence color="var(--wr-color-primary)" />
</section>Text contrast
On the default tints, --wr-color-on-surface holds 4.5:1 in the dark scheme and not in the light one, so text on the light default needs a scrim or a card.
| Scheme | Tint | Text | Median pixel | Worst 1% of pixels | Same, worst frame | Worst pixel |
|---|---|---|---|---|---|---|
| Light | #ffffff | #111827 | 8.57:1 | 3.93:1 | 2.80:1 | 2.64:1 |
| Dark | #5c669e | #e9ebef | 7.18:1 | 5.01:1 | 4.89:1 | 4.80:1 |
Measured in Chromium with a software renderer (SwiftShader) at 320×180: 240 phase combinations with the pointer at rest and 960 frames with it at the four corners, each figure the lower of the two. Worst 1% is the 1st-percentile pixel in light and the 99th in dark. Not measured: a real GPU, prefers-contrast: more, an amplitude other than 1, any other tint or text colour.
The CSS stand-in under the canvas, shown before the first frame and without WebGL2, reads 4.55:1 in light and 5.28:1 in dark at those percentiles, in a 960×540 screenshot sampled every 37th pixel.
API
| Name | Description | Type | Default |
|---|---|---|---|
color | Tint multiplied over the picture, any opaque CSS colour: the canvas drops alpha and the stand-in keeps it. Unset, empty or blank, it follows the theme. | string | null | null |
speed | Speed of the folds; 0 holds them, a negative value reverses them. Changing it never jumps them. | number | 1 |
amplitude | How hard the pointer stirs the folds; 0 leaves the pointer out, a negative value stirs the other way. | number | 1 |
followPointer | Whether the pointer stirs the folds at all. | boolean | true |
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/bits/iridescence declares each default on its own element.
| Variable | Default | Declared on |
|---|---|---|
--wr-iridescence-color | light-dark(#ffffff, #5c669e) | .wr-iridescence |
See also
Animation AuroraAn animated aurora background for a hero or a section.Animation ThreadsThin lines flowing behind your content like strands in a current.Animation WavesDrifting lines behind your content that bend around the pointer.Animation Ripple GridGrid lines behind your content that the pointer sends ripples through.Component CardA surface that groups related content.Util resolveCssColorResolves a CSS colour, such as a var() or light-dark(), to a value a canvas can paint with.