Voronoi Pattern
A true Voronoi diagram in SVG: twelve points drift slowly and every cell, recomputed each frame, keeps a gradient centred on its point.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. SVG has 30 effects, including 3 free. Explore the category →
3 usage examples



How it works
A Voronoi diagram splits a surface into cells: each cell gathers every spot that is closer to its point (its seed) than to any other seed. The script computes it exactly. For each seed it starts from the area's rectangle and cuts it, one after another, along the perpendicular bisector that separates it from every other seed; what remains is the cell's polygon, written into an SVG <polygon>. With 12 seeds that makes 132 cuts per frame, a negligible amount of work.
Seeds start at a random position and heading, travel at 18 px per second (data-speed) and bounce off the edges. Movement is multiplied by the time since the previous frame, capped at 50 ms: same speed on a 60 Hz or 120 Hz screen, no leap when you come back to the tab. Each cell has a radialGradient centred on its seed, from its full colour down to 18% opacity; joints are drawn in the background colour and a small light dot marks each seed. On top, the hue drifts slowly (hue-rotate from 0 to 60° and back, over 10 s).
The area takes its parent's width and the --vrn-height height (300 px). A ResizeObserver resets the SVG coordinates and the seed positions whenever the area changes size, including when it comes out of a closed tab or accordion. An IntersectionObserver stops the work while the diagram is off screen. Every copy has its own gradients with random ids, so two diagrams on one page never steal each other's colours. With data-pointer="follow", the first seed follows the pointer while it hovers the area: its cell moves under the mouse and pushes its neighbours aside.
Accessibility
- Decorative background: the SVG carries
aria-hidden="true"and holds no text. If the diagram goes with a heading, write that heading in the page, not in the drawing. - Reduced motion: under
prefers-reduced-motion: reduce, seeds stop moving and the hue no longer drifts; the diagram is drawn once, crisp. Thedata-pointer="follow"option stays active, because the user is the one moving the cell. - Keyboard: nothing to activate. Pointer following is a visual extra with no keyboard counterpart, and no information depends on it.
- Touch: with
data-pointer="follow", a tap puts the cell under the finger and a short drag pulls it along; as soon as the browser starts scrolling the page, it ends the tracking and the cell drifts on from there. Scrolling is never blocked. - Text on top: cells are vivid. Give text its own background (card, dark pill), as in the examples.
Browser compatibility
SVG drawn from JavaScript, no canvas and no library. ResizeObserver (Chrome 64, Firefox 69, Safari 13.1) sets the minimum versions taken from MDN data; Pointer Events (Safari 13) and IntersectionObserver (Safari 12.1) are older. Measured in Chromium 151, Firefox 153 and WebKit 26.5: 12 cells per copy, two independent copies, pointer tracking on the second copy, coordinates reset when the area grows from 400 to 800 px, still under reduced motion.
Without JavaScript the area only shows its background colour. Without ResizeObserver the diagram follows window resizes but not those of its own container; without IntersectionObserver it keeps computing off screen.
The code
HTML structure to paste into your page (the CSS + JS come with your purchase):
<div class="fx-0613-root" data-points="12">
<svg class="vrn-svg" aria-hidden="true"></svg>
</div>
One-time payment, no subscription — the code is yours forever
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
data-points (root) |
12 | Number of seeds, hence cells (2 to 60). Above 30 in a small area, cells turn into shards. |
data-speed (root) |
18 | Seed speed in pixels per second; 0 gives a still diagram. |
data-colors (root) |
#6366f1, #8b5cf6, #d946ef, #06b6d4, #f43f5e, #22c55e, #f59e0b | Cell colours, comma separated, handed out in turn. |
data-pointer="follow" (root) |
absent | The first seed follows the pointer while hovering, then goes back to drifting. |
--vrn-line |
2px | Width of the joints between cells, drawn in the --vrn-bg colour. |
--vrn-seed |
rgba(255,255,255,.75) | Colour of the dots marking the seeds; transparent hides them. |
--vrn-hue-speed |
10s | Length of one round trip of the hue drift (0 → 60° → 0). |
--vrn-height / --vrn-bg |
300px / #0a0a0f | Area height, and colour of the joints and background. |
FAQ
build() function to read your coordinates and set data-speed="0".