Skip to content
Added 13 Sept 2026
Back to library
iridescence
Iridescence
Filters & Blend Modes

Iridescence

Featured

Thin-film interference: one phase read by three cosines a third of a turn apart, so the hue sweeps the whole palette instead of crossfading between two ends of it.

Filters & Blend Modesiridescentoil slickholographicrainbowfilmshader
lines of CSS
24lines of CSS
dependencies
0dependencies
browser, for years
Everybrowser, for years
no motion at all
Noneno motion at all
Backdrop
Fragment shader, 3 files, no dependencies. The first one is this design. The other two are the runtime, shared by every shader effect in the catalog — copy them once and the next design you add is a single file. The HTML and CSS on this page are the preview surface and the gradient shown if WebGL is unavailable; they are not a substitute for these.
components/iridescence.tsx
'use client'

/**
 * Iridescence — thin-film interference, which is why the colours cycle.
 *
 * A soap bubble is not coloured. What you see is the film's thickness
 * deciding which wavelengths cancel and which reinforce, so the hue is a
 * function of the *phase*, and the three channels are the same function
 * offset by a third of a turn. That is the entire model here: one phase,
 * three cosines at 120° apart, each weighting a palette colour.
 *
 * Because the three colours are sampled from one continuous phase, the
 * result sweeps through the palette rather than crossfading between two
 * ends of it — a gradient cannot do that, and it is the difference between
 * "oil slick" and "purple to pink".
 */

import * as React from 'react'

import { ShaderSurface } from './shader-surface'
import type { GLProgram } from './shader-runtime'

export const IRIDESCENCE_PROGRAM: GLProgram = {
  id: 'iridescence',
  kind: 'webgl',
  speed: 1,
  light: { c0: '#38bdf8', c1: '#f472b6', c2: '#facc15', bg: '#f8fafc' },
  dark: { c0: '#0ea5e9', c1: '#db2777', c2: '#a3e635', bg: '#07050d' },
  fragment: `
vec4 render(vec2 uv) {
  vec2 p = aspect(uv);
  float t = u_time * 0.18;

  // Stand-in for the film's thickness: a warped field, so the bands bend
  // and pool the way a real film does over an uneven surface.
  vec2 w = vec2(fbm(p * 1.35 + vec2(t, 0.0)), fbm(p * 1.35 + vec2(0.0, t * 0.8)));
  float phase = 6.5 * (w.x - w.y) + length(p) * 2.1 + t * 0.7;

  float a = 0.5 + 0.5 * cos(phase);
  float b = 0.5 + 0.5 * cos(phase + 2.0944);
  float c = 0.5 + 0.5 * cos(phase + 4.1888);

  vec3 col = u_c0 * a + u_c1 * b + u_c2 * c;
  col = mix(u_bg, col, 0.88);

  // A slow grain over the top. Without it the bands are too clean and the
  // surface reads as plastic rather than as a film on something.
  col *= 0.78 + 0.32 * fbm(p * 2.6 - t);

  return vec4(col, 1.0);
}
`,
}

export function Iridescence({ className }: { className?: string }) {
  return <ShaderSurface program={IRIDESCENCE_PROGRAM} className={className} />
}

What's included

  • The markup and the stylesheet, in whichever framework you pick
  • No runtime dependencies

Works with

  • React
  • Vue
  • Svelte
  • Tailwind
  • styled-components
  • Plain CSS

npx hoverlab add iridescence

Or over MCP, from your editor's agent — no account needed.

License

Free to read, copy and install, for personal and non-commercial projects. Shipping it in client work or a paid product needs Pro ($79 once). The source lands in your repo and stops being ours — no attribution, nothing to upgrade.

Was this useful?

Motion safety

Not profiled. Canvas / WebGL effect: its deliverable is a shader, and the motion profile only reads CSS.

32 more effects in Filters & Blend Modes

All of them free to read, copy and install — no account, no locked tiles, no watermarked preview. The whole catalog is open, and so are the API and the CLI.

Browse Filters & Blend Modes

Shipping one commercially

Copying the code is free. Putting it in client work or a paid product is what Pro is for — the licence, not the access.

  • A commercial licence for everything in the catalog
  • Unlimited bundle exports, in Vue, Svelte and Tailwind
  • One payment — no subscription, nothing to renew
Pro — $79 once