Halftone Bloom
FreeA photo rendered as a field of glowing dots that blooms open, settles to a pale stage, then warms to your colour.
Code
Updates live with your settings.
Preparing the code…
How to use
- 1
Install the dependency
npm i three - 2
Add the files
Copy the files from the Code section into a folder named
halftone-bloom/in your project. They are plain TypeScript; the React wrapper is one file and the engine does not depend on it. - 3
Drop in the component
Place
<HalftoneBloom />inside a positioned container with a size; it fills the container. Every setting is a prop, and changing a prop updates the running effect. - 4
Other frameworks
Vue, Svelte, Astro or plain HTML: use the engine directly, or copy the AI Prompt and let your assistant write the wrapper for your stack. The prompt carries this exact code.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| image | string (URL) | "lily.jpg" | A light subject on a near-black background. The effect reads brightness only. |
| fit | number 0.3–1 | 0.92 | Largest share of the height the picture may fill. |
| scale | number 0.5–1.6 | 1 | Multiplier on the picture's size. |
| dotPitch | number 3–24 px | 6 | Distance between dot centres. |
| dotSize | number 0.3–0.9 | 0.58 | Largest dot radius as a share of the pitch. |
| black | number 0–0.5 | 0.06 | Brightness treated as black. Raise it if the background is grey. |
| white | number 0.4–1 | 1 | Brightness treated as white. |
| gamma | number 0.4–3 | 1.15 | Curve on the mid-tones. Higher makes mid dots smaller. |
| detail | number 0–1.5 | 0.6 | Boosts edges and veins against their surroundings. |
| soften | number 0–2 | 0.25 | Extra blur when sampling, in mip levels. Smooths blotchy pictures. |
| lift | number 0–1 | 0 | Floor for dark but coloured details so they keep their dots. |
| accent | string (#hex) | "#d30078" | Colour of the final wash. The deep-to-pale ramp is derived from it. |
| pale | string (#hex) | "#ffd9e8" | Colour of the middle stage, before the wash. |
| background | string (#hex) | "#0a0a0a" | Page colour painted behind the dots. |
| keepColor | number 0–1 | 0.7 | Share of the picture's own colour kept in the final stage. |
| saturation | number 0–2 | 1.25 | Saturation of that colour. 1 is as shot. |
| vivid | boolean | false | Keep the picture's own colours all the way through: no pale stage, no wash. |
| tint | number 0–1 | 0 | Strength of two extra hues in the final stage. |
| tintShadow | string (#hex) | "#ffffff" | Laid over the dim dots. |
| tintLight | string (#hex) | "#ffffff" | Laid over the brightest dots. |
| glow | number 0–2 | 1 | Strength of the wide, soft haze behind the dots. |
| bloom | number 0–1 | 0.24 | Glow around the brightest dots. |
| bloomRadius | number 0–1 | 0.9 | How far the bloom reaches. |
| bloomKnee | number 0–0.5 | 0.01 | How gradually dots enter the bloom. Wider stops halos flickering. |
| speed | number 0.25–3 x | 1 | 1 plays the bloom in about eight seconds. |
| reveal | "radial" | "sweep" | "none" | "radial" | Shape of the bloom-in. |
| twinkle | number 0–1 | 1 | Live shimmer kept once settled. 0 holds every dot steady. |
| sway | number 0–1 | 1 | Breathing and sway of the whole picture. |
| hover | number 0–1 | 1 | How much nearby dots swell toward the pointer. |
| loop | boolean | false | Replay the intro a few seconds after it settles. |
| trigger | "load" | "inview" | "click" | "load" | When the intro plays. |
| quietZone | number 0–1 | 0 | How much the dots behind a headline dim. 0 turns the zone off. |
| quietZoneY | number 0–1 | 0.53 | Vertical centre as a share of the height. |
| quietZoneWidth | number 0.1–1 | 0.6 | Share of the host width. |
| quietZoneHeight | number 0.05–1 | 0.44 | Share of the host height. |
| maxDpr | number 1–2 | 2 | Cap on device pixel ratio. 1 is roughly four times cheaper than 2 on retina screens. |
Performance
- Bundle
- ~160 KB gzipped, almost all of it three
- Cost
- Medium
- Renders on
- GPU (WebGL)
- Reduced motion
- Respected
- Depends on three ^0.186.0.
- One full-screen fragment shader plus a bloom pass; the cost scales with the canvas area, so cap maxDpr on large screens.
- Pauses when off-screen or when the tab is hidden.
- With prefers-reduced-motion the picture appears settled and nothing moves.
Related
- VinesSoon
Organic & Nature
Tendrils that grow along the edges of a section and curl toward the pointer.
- Ink TrailSoon
Cursor & Pointer
A soft ink line that follows the cursor and fades like a wet brushstroke.
- FirefliesFree
Particles
Soft points of light that wander, pulse and move away from the pointer. Warm by default, white for a quiet background.