DitherButton uses a tiny canvas painter to render a 4x4 ordered (Bayer) dither, animated as a slow rotating sine wave. The label sits in a knockout panel with a hard offset shadow so it stays readable on top of the moving pattern. Colors are read from the current --color-foreground / --color-background tokens so it tracks the active theme.
Preview
DitherButton
Interactive
Variants
Because the dither colors are read from the resolved color and background-color of the canvas, you can re-skin the button by overriding text/background utilities via className.
Rounded pill
Pill
Rounded full + extra padding
Hot pink
Hot pink
Magenta dither on deep navy
Tiny chip
Chip
Compact size with thin border
Chunky dither
Chunky
Big particles via ditherSize={10}
Fine dither
Fine
Tight particles via ditherSize={2}
Install
Add the item with the shadcn CLI.
npx shadcn@latest add @evilbuttons/dither-buttonUsage
import DitherButton from "@/components/evil-buttons/dither-button";
export function ButtonDemo() {
return <DitherButton>Launch</DitherButton>;
}Props
The component spreads any <button> HTML attributes.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | The visible button label or content. |
className | string | - | Extra classes passed to the button. |
ditherColor | string (hex) | - | Override the dither "on" pixel color (e.g. #ff0066). Falls back to the resolved color. |
ditherOpacity | number (0–1) | 1 | CSS opacity applied to the dither canvas. |
ditherSize | number (1–32) | 4 | Pixel scale of the dither particles. Higher = chunkier blocks. |
Notes
- Renders at
1/4the visual resolution withimage-rendering: pixelatedfor crisp pixel edges. - Honors
prefers-reduced-motionby drawing a single static frame. - The dither colors follow the resolved CSS
colorandbackground-colorof the canvas, so themes work out of the box.
Registry
The registry item includes components/evil-buttons/dither-button.tsx and installs clsx and tailwind-merge as dependencies.