Installation
pnpm dlx shadcn@latest add https://dithercn.dev/r/dither-card.jsonUsage
import { DitherCard } from "@/components/dithercn/dither-card";
import { CardContent, CardHeader, CardTitle } from "@/components/ui/card";
export function Revenue() {
return (
<DitherCard glow="top-right" interactive>
<CardHeader>
<CardTitle>Monthly revenue</CardTitle>
</CardHeader>
<CardContent>$48,210</CardContent>
</DitherCard>
);
}DitherCard has the same spacing, border and colours as shadcn's Card, so CardHeader, CardContent and CardFooter fit inside it. It does not depend on them: plain markup works too.
The glow is a stack of rings, each filled with a denser dither than the one below it. The rim is a wider stack masked to a band one cell wide inside the border: it is dense where the glow sits and thins out round the card, so the edge catches the light. Set radius if you round the card differently, so the rim follows the corners. With interactive, a second, larger stack switches on ring by ring when the card is hovered or something inside it has focus, so the glow grows outward through the levels.
Examples
Corners and edges
glow takes any corner, or top and bottom for a wide glow along an edge. Hover each card to see it grow.
Colour and texture
color takes a palette name or any CSS colour, and fill changes the texture. On the left, green with blue noise and 2 pixel cells for a fine, even grain. On the right, orange with a hatched fill: every ring shares the hatching, and where the rings overlap near the edge the lines build up.
Props
| Prop | Type | Default |
|---|---|---|
| glow Where the glow sits. | Type: "top-left" | "top-right" | "bottom-left" | "bottom-right" | "top" | "bottom" | Default "top-left" |
| reach How far the glow spreads from its origin, in pixels. | Type: number | Default 240 |
| strength Densest dither level, at the origin, from 0 to 1. | Type: number | Default 0.5 |
| rim Light the border with dither, densest near the glow. | Type: boolean | Default true |
| radius Corner radius in pixels. The rim follows it. | Type: number | Default 14 |
| interactive Grow the glow on hover and when the card has focus inside. | Type: boolean | Default false |
| color Glow colour: a palette name such as "green", a CSS variable name, or any CSS colour. | Type: DitherColor | Default "ink" |
| fill Texture of the glow. Gradient steps through dither levels; the others stack one texture and fade it by overlap. | Type: "gradient" | "dotted" | "hatched" | "solid" | Default "gradient" |
| matrix The threshold pattern. | Type: "bayer2" | "bayer4" | "bayer8" | "blue-noise" | Default "bayer4" |
| cell Size of one dither cell in CSS pixels. | Type: number | Default 3 |
Notes
- The glow is decorative and hidden from assistive technology. The card itself is a plain
div; make the content inside it, not the card, the link or button. - The hover glow only runs on devices that can hover. Keyboard users get the same effect when focus moves inside the card.
- With reduced motion turned on, the hover glow switches on in one step instead of ring by ring.
- The glow is static SVG, so it renders on the server and costs nothing while idle.