Backgrounds
Grid Dots
A pure-CSS grid, dot or cross pattern container with a radial fade — a zero-JS decorative backdrop for hero and section surfaces.
Preview in your theme
Loading preview…
Installation
npx shadcn@latest add https://ui.zyeon.ai/r/grid-dots.jsonPrompt
The prompt behind this component — paste it into your AI assistant to recreate or adapt it.
Build a React + TypeScript + Tailwind "GridDots" component — a decorative
grid / dot-matrix / crosshair pattern container. Pure CSS, no dependencies
beyond the cn() class merger.
Contract
- export function GridDots — props extend React.HTMLAttributes<HTMLDivElement>
(root spreads the rest), plus:
- variant?: "grid" | "dots" | "cross" (default "grid")
- cell?: number — tile spacing in px (default 32)
- fade?: boolean — radial mask dissolving the pattern toward the edges
(default true)
- children render in a content layer above the pattern; className merges
into the root via cn().
- No hooks, no events, no browser APIs — do NOT add "use client". It stays a
React Server Component and ships zero client JS.
Behavior
- Root is cn("relative isolate overflow-hidden", className): isolate scopes
the internal z-index, overflow-hidden clips the pattern to consumer-rounded
corners. The component sets no size or padding — the consumer's className
owns dimensions.
- Two layers inside: an absolute inset-0 pattern layer (aria-hidden,
pointer-events-none) and a relative z-10 wrapper around children.
- Each pattern is a background-image recipe tiled at `cell × cell` px via
background-size:
- grid: two 1px line gradients — linear-gradient(90deg, line 1px,
transparent 1px) plus linear-gradient(0deg, same).
- dots: radial-gradient(circle, ink 1.5px, transparent 1.5px).
- cross: the conic-gradient quadrant trick — conic-gradient(at 1px Npx,
transparent 75%, stroke 0) paints an exact 1px × N rectangle (hard stop
at 270°, axis-aligned), a second layer paints N × 1px, and per-layer
background-position centers both in the tile. Arm length
N = max(4, round(cell / 4)) so the mark scales with density.
- fade=true sets mask-image and -webkit-mask-image to
radial-gradient(ellipse at center, black, transparent 75%); fade=false lets
the pattern run edge to edge.
- Static by design: nothing animates, so there is nothing to gate behind
prefers-reduced-motion.
Rendering & styling
- Never hardcode pattern colors. Every ink derives from the theme:
color-mix(in oklab, var(--foreground) N%, transparent) with N = 10 for grid
lines, 16 for cross strokes, 22 for dots — sparser marks get more alpha so
the three variants read at equal visual weight. Dark mode adapts for free
because --foreground flips with the theme.
- The mask gradient uses only the black / transparent keywords — a mask reads
the alpha channel, it is not a rendered color.
- The content wrapper is plain relative z-10 and imposes no layout, so
consumer flex/grid classes on the root position children as usual.
Customization levers
- Contrast: the three color-mix percentages are the only ink knobs; stay in
the 6–25% band or the ornament starts competing with content.
- Ink token: swap var(--foreground) for var(--primary) (brand-tinted paper)
or var(--border) (even quieter); the recipe stays identical.
- Density: cell is the single rhythm knob (24–80px is the useful range);
the cross arm length follows it automatically.
- Mask shape: replace the radial mask with
linear-gradient(to bottom, black, transparent) for a top-anchored fade
under a navbar, or move the ellipse center (e.g. "at 50% 0%") to spotlight
a hero headline.
- Hero pairing: give the root the section's min-height plus centering flex
classes via className, stack headline + CTA as children, and keep fade=true
so the pattern stays clean against adjacent sections.
- Line weight: the 1px / 1.5px stops can grow to 2px for a bolder blueprint
look — raise cell at the same time to keep the surface calm.Concepts
- Layered decoration — the pattern lives in an absolute,
aria-hidden,pointer-events-nonelayer beneath arelative z-10content wrapper, so assistive tech and pointer events only ever meet the content. - Zero-JS background — no hooks, events, or browser APIs means the component stays a React Server Component: the ornament is pure paint and adds nothing to the client bundle.
- Token-derived contrast — every mark is
color-mix(in oklab, var(--foreground) N%, transparent); one source token yields correct low contrast in both color schemes, and re-theming is a token swap, not a rewrite. - Tile-density lever — a single
cellnumber feedsbackground-sizefor every variant, so pattern rhythm scales without touching the gradient recipes. - Radial mask fade —
mask-imagecuts alpha, not color: the pattern dissolves toward the edges so the centered content stays focal and section boundaries stay clean. - Conic quadrant trick — with axis-aligned hard stops, a
conic-gradientpaints an exact rectangle, letting two layers compose a crosshair per tile with no SVG asset.