Installation
pnpm dlx shadcn@latest add https://dithercn.dev/r/starfield.jsonUsage
import { Starfield } from "@/components/dithercn/starfield";
export function Hero() {
return (
<section className="relative isolate min-h-[480px]">
<Starfield className="absolute inset-0 -z-10" />
<h1>Your headline</h1>
</section>
);
}Stars sit on three grids of different sizes. Far stars are small, dim and slow; near stars are brighter, move faster and the brightest get a small cross. A faint haze of dithered dust drifts behind them.
Each star snaps to one palette colour, so it never flickers between dither thresholds as it moves. The last palette colour is the brightest star, the middle ones are dimmer stars and the haze.
Examples
Behind a sign-in form
A slower drift to the lower left and a stronger haze. The form has a translucent background so stars show through its edges.
A quiet sky
drift={0} holds the stars in place, and twinkle={1} lets them pulse fully. No haze, fewer stars, in neutral foreground colours.
Props
| Prop | Type | Default |
|---|---|---|
| density How many stars, from 0 to 2. | Type: number | Default 1 |
| twinkle How much each star pulses, from 0 (steady) to 1. | Type: number | Default 0.6 |
| angle Direction the stars drift, in degrees as in CSS: 0 is up, 90 right. | Type: number | Default 270 |
| drift Drift speed of the nearest layer, in cells per second. The others move at 0.6 and 0.3 of it. 0 holds them still. | Type: number | Default 1.6 |
| nebula Strength of the dust haze behind the stars, from 0 to 1. | Type: number | Default 0.5 |
| palette Colours from paper to ink: palette names such as "blue", CSS variable names, or any CSS colour. | Type: [DitherColor, DitherColor, ...DitherColor[]] | Default ["--dither-paper", "--chart-2", "--dither-ink"] |
| matrix The threshold pattern. See Dither engine. | Type: "bayer2" | "bayer4" | "bayer8" | "blue-noise" | Default "blue-noise" |
| levels Tones before dithering. The default keeps every palette colour exact so stars stay solid. | Type: number | Default 16 per palette step |
| cell Size of one dither cell in CSS pixels. | Type: number | Default --dither-cell |
| speed How fast time runs, for both drift and twinkle. | Type: number | Default 1 |
| animate false draws one still frame. | Type: boolean | Default true |
| className Size and position. The starfield fills this box. | Type: string | Default – |
Notes
- The starfield is decorative and hidden from assistive technology. Put real text on top of it, not inside it.
- With reduced motion turned on, it draws one still frame and stops.
- It pauses when scrolled out of view or when the tab is hidden, and releases its WebGL context when far offscreen. Without WebGL it shows tiled CSS dots.
- Twinkle rates are random per star and slow, between about 3 and 12 seconds a pulse, so nothing flashes.