Skip to content

Components / Backgrounds

Grid Pattern

A hairline grid behind content, faded toward the edges, optionally drifting one cell at a time. Two repeating gradients and a mask; pure CSS. Fills its positioned parent.

Live demo

Grid.

Live, from the library itself: scroll, hover, navigate away and back. The demo is never gated.

Measured

JavaScript of its own

0 B

CSS 4.7 kB raw including the base tokens. Measured from a production build, and again in CI for every change that can move it.

Browser support

Baseline · widely available

Chrome 120 · Firefox 53 · Safari 15.4; needs mask-image.

Install

One command adds the integration, the base tokens and every component. Then import what you use.

npx astro add moonarc
pnpm astro add moonarc
bunx astro add moonarc
src/pages/index.astro
---
import GridPattern from '@moonarc/core/GridPattern';
---
<section class="relative">
  <GridPattern size={40} drift={12} />
  <h2 class="relative">Above the grid</h2>
</section>
Copy it into your project instead (shadcn registry)

Owns the file, no dependency. The registry item also installs the base tokens.

terminal
npx shadcn@latest add https://moonarc.dev/r/grid-pattern.json

The CLI needs a components.json and the @/* alias, which Setup has. The file lands in src/components/moonarc/.

Source

The whole component. Self-contained styles in a cascade layer so your classes always win; it imports nothing.

GridPattern.astro
---
/**
 * GridPattern — a hairline grid behind content, faded at the edges, with an
 * optional slow drift. Zero JS: two repeating gradients and a mask. Fills
 * its positioned parent.
 */
import type { HTMLAttributes } from 'astro/types';

interface Props extends HTMLAttributes<'div'> {
  /** Cell size in px. */
  size?: number;
  /** Line colour. */
  color?: string;
  /** Fade the grid toward the edges with a radial mask. */
  fade?: boolean;
  /** Drift one cell every `drift` seconds; 0 keeps it still. */
  drift?: number;
}

const { size = 32, color = 'var(--ma-edge)', fade = true, drift = 0, class: className, style, ...rest } = Astro.props;
const vars = [`--ma-gp-size:${size}px`, `--ma-gp-color:${color}`, `--ma-gp-drift:${drift}s`, typeof style === 'string' ? style : ''].filter(Boolean).join(';');
---

<div class:list={['ma-grid-pattern', className]} aria-hidden="true" data-fade={fade ? '' : undefined} data-drift={drift > 0 ? '' : undefined} style={vars} {...rest}></div>

<style is:global>
  @layer components {
    :where(.ma-grid-pattern) {
      position: absolute;
      inset: 0;
      pointer-events: none;
      background-image:
        linear-gradient(to right, var(--ma-gp-color, var(--ma-edge)) 1px, transparent 1px),
        linear-gradient(to bottom, var(--ma-gp-color, var(--ma-edge)) 1px, transparent 1px);
      background-size: var(--ma-gp-size, 32px) var(--ma-gp-size, 32px);
    }
    :where(.ma-grid-pattern[data-fade]) {
      mask-image: radial-gradient(ellipse at center, #000 30%, transparent 75%);
    }
    :where(.ma-grid-pattern[data-drift]) {
      animation: ma-grid-pattern var(--ma-gp-drift, 8s) linear infinite;
    }
    @media (prefers-reduced-motion: reduce) {
      :where(.ma-grid-pattern) {
        animation: none;
      }
    }
  }

  @keyframes ma-grid-pattern {
    to {
      background-position: var(--ma-gp-size, 32px) var(--ma-gp-size, 32px);
    }
  }
</style>

Props

PropTypeDefaultDescription
sizenumber32Cell size in px.
colorstringvar(--ma-edge)Line colour; the token is theme-aware.
fadebooleantrueRadial mask so the grid dissolves toward the edges.
driftnumber0Seconds per one-cell drift; 0 keeps it still. Linear, so the loop has no visible seam.

Reduced motion

The grid holds still.

With ClientRouter

CSS-only; nothing to rebind.

Why it is built this way

Replaces: GridPattern (Magic UI) · GridBackground (Aceternity). See the migration table.

A field of cells that light up under the cursor and fade where it has been, with a slow idle sweep when nothing is touched.

every browserpointeralways

Dot Pattern

Backgrounds

A field of dots behind content, faded toward the edges, with an optional slow pulse.

every browseralways

Noise

Backgrounds

Film grain over a gradient or image, blended and flickering at 12 fps.

every browseralways

Also: view transitions · how costs are measured · browser support · accessibility policy · five-minute setup · MCP for agents · this page as Markdown