Cursor Grid
PointerA field of cells that light up under the cursor and fade where it has been, with a slow idle sweep when nothing is touched.
A field of dots behind content, faded toward the edges, with an optional slow pulse. One tiled radial gradient and a mask; pure CSS. Fills its positioned parent.
Dots.
Live, from the library itself: scroll, hover, navigate away and back. The demo is never gated.
Adjust · props are custom properties, set inline, so you edit the running instance
JavaScript of its own
0 B
CSS 4.6 kB raw including the base tokens. Measured from a production build, and again in CI for every change that can move it.
Browser support
Chrome 120 · Firefox 53 · Safari 15.4; needs mask-image.
One command adds the integration, the base tokens and every component. Then import what you use.
npx astro add moonarcpnpm astro add moonarcbunx astro add moonarc---
import DotPattern from '@moonarc/core/DotPattern';
---
<section class="relative">
<DotPattern pulse={5} />
<h2 class="relative">Above the dots</h2>
</section>Owns the file, no dependency. The registry item also installs the base tokens.
npx shadcn@latest add https://moonarc.dev/r/dot-pattern.jsonThe CLI needs a components.json and the @/* alias, which Setup has. The file lands in src/components/moonarc/.
The whole component. Self-contained styles in a cascade layer so your classes always win; it imports nothing.
---
/**
* DotPattern — a field of dots behind content, faded at the edges, with an
* optional slow pulse. Zero JS: one radial gradient tiled, and a mask.
* Fills its positioned parent.
*/
import type { HTMLAttributes } from 'astro/types';
interface Props extends HTMLAttributes<'div'> {
/** Distance between dots in px. */
size?: number;
/** Dot radius in px. */
radius?: number;
/** Dot colour. */
color?: string;
/** Fade toward the edges. */
fade?: boolean;
/** Pulse period in seconds; 0 keeps it still. */
pulse?: number;
}
const { size = 20, radius = 1, color = 'var(--ma-glow)', fade = true, pulse = 0, class: className, style, ...rest } = Astro.props;
const vars = [`--ma-dp-size:${size}px`, `--ma-dp-r:${radius}px`, `--ma-dp-color:${color}`, `--ma-dp-pulse:${pulse}s`, typeof style === 'string' ? style : ''].filter(Boolean).join(';');
---
<div class:list={['ma-dot-pattern', className]} aria-hidden="true" data-fade={fade ? '' : undefined} data-pulse={pulse > 0 ? '' : undefined} style={vars} {...rest}></div>
<style is:global>
@layer components {
:where(.ma-dot-pattern) {
position: absolute;
inset: 0;
pointer-events: none;
background-image: radial-gradient(circle, var(--ma-dp-color, var(--ma-glow)) var(--ma-dp-r, 1px), transparent calc(var(--ma-dp-r, 1px) + 0.5px));
background-size: var(--ma-dp-size, 20px) var(--ma-dp-size, 20px);
}
:where(.ma-dot-pattern[data-fade]) {
mask-image: radial-gradient(ellipse at center, #000 30%, transparent 75%);
}
:where(.ma-dot-pattern[data-pulse]) {
animation: ma-dot-pattern var(--ma-dp-pulse, 4s) var(--ma-ease-in-out) infinite alternate;
}
@media (prefers-reduced-motion: reduce) {
:where(.ma-dot-pattern) {
animation: none;
}
}
}
@keyframes ma-dot-pattern {
from {
opacity: 0.5;
}
to {
opacity: 1;
}
}
</style>| Prop | Type | Default | Description |
|---|---|---|---|
size | number | 20 | Distance between dots in px. |
radius | number | 1 | Dot radius in px. |
color | string | var(--ma-glow) | Dot colour; the token is theme-aware. |
fade | boolean | true | Radial mask toward the edges. |
pulse | number | 0 | Seconds per pulse (opacity 0.5 ↔ 1); 0 keeps it still. |
No pulse.
ClientRouterCSS-only; nothing to rebind.
Replaces: DotPattern (Magic UI) · DotBackground (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.
A hairline grid behind content, faded toward the edges, optionally drifting one cell at a time.
Film grain over a gradient or image, blended and flickering at 12 fps.
Also: view transitions · how costs are measured · browser support · accessibility policy · five-minute setup · MCP for agents · this page as Markdown