Installation
pnpm dlx shadcn@latest add https://dithercn.dev/r/smoke.jsonUsage
import { Smoke } from "@/components/dithercn/smoke";
export function Footer() {
return (
<footer className="relative isolate min-h-[360px]">
<Smoke className="absolute inset-0 -z-10" />
</footer>
);
}The smoke is thickest at the bottom and thins out as it climbs. Light from the upper left catches one side of each plume and leaves the other in shadow. The thickest parts stop short of solid ink, so the dither always shows.
Examples
Behind a headline
A lower height keeps the smoke in the bottom half, and a lower density makes it lighter. Negative wind blows it to the left.
Embers
Four warm colours turn the smoke into the glow above a fire. Blue noise gives an even grain instead of the Bayer grid.
Props
| Prop | Type | Default |
|---|---|---|
| scale Size of the plumes. Higher values make more, smaller ones. | Type: number | Default 1 |
| height How high the smoke climbs before it thins out, from 0 to 1. | Type: number | Default 0.8 |
| wind Sideways drift. Negative blows left, positive right. | Type: number | Default 0.2 |
| density How thick the smoke is, from 0 to 1.5. | Type: number | Default 1 |
| 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", "--dither-ink"] |
| matrix The threshold pattern. See Dither engine. | Type: "bayer2" | "bayer4" | "bayer8" | "blue-noise" | Default "bayer4" |
| cell Size of one dither cell in CSS pixels. | Type: number | Default --dither-cell |
| speed How fast it moves. | Type: number | Default 1 |
| animate false draws one still frame. | Type: boolean | Default true |
| className Size and position. The background fills this box. | Type: string | Default – |
Notes
- It 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 a soft CSS haze in the same colours.
- It costs one small draw per frame at 30 fps, at one pixel per dither cell. See Performance.