---
title: "A sparkly backdrop from one div and mask-composite"
description: "jhey's CSS trick: intersect a grid-of-dots mask with a Perlin-noise mask using mask-composite, then animate mask-position. The dots twinkle, and it's a single element instead of thousands of animated nodes."
date: "2026-05-30"
tags: ["css", "mask", "animation", "frontend"]
---

[jhey](https://x.com/jh3yy/status/1722397114532048959) posted a CSS trick I had
to rebuild: a whole shimmering starfield in one element, no canvas and no
thousands of animated divs. Here it is:

## The trick is intersecting two masks

The element itself is just a gradient. What makes it sparkle is two stacked
mask layers and one underused property, `mask-composite`.

```css
.canvas {
  background: var(--gradient);
  mask: var(--dots), var(--noise);
  mask-composite: intersect; /* keep only where BOTH masks show */
  animation: flicker 8s infinite;
}
```

`mask-composite: intersect` works like it does in SVG: it combines the layers
and keeps only their overlap. So a pixel survives only if the dots mask *and*
the noise mask are both opaque there.

The dots are a single repeated radial-gradient:

```css
mask: radial-gradient(circle at 50% 50%, white 2px, transparent 2.5px)
      50% 50% / 40px 40px;
```

And the noise is a tile of Perlin noise. jhey used a generated `noise.png`. I
skipped the image entirely and generated it inline with an SVG `feTurbulence`
filter, so the whole thing ships as CSS:

```css
mask: url("data:image/svg+xml,…feTurbulence…") 50% 50% / 256px 256px;
```

## Then animate the noise

Intersect the two and you get a static scatter of dots. The last move is to
animate the noise layer's position so the "bright" region drifts across the
grid, lighting up different dots each frame:

```css
@keyframes flicker {
  to { mask-position: 50% 50%, 120px 90px; }
}
```

The first value pins the dots; the second slides the noise. That drift is the
twinkle.

## Why it's nice

One element does the work of thousands. There's no per-dot DOM node, no
canvas, no JS loop, so it stays cheap even across a big area, and it degrades to
a calm static field under `prefers-reduced-motion`. Swap the gradient for your
brand colors, or point the same masks at text to make words shimmer.

Recreated from [jhey](https://x.com/jh3yy/status/1722397114532048959). Grab the
component on the [Sparkle Field](/components/sparkle-field) page.
