SVG✨ Premium

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.

CSSGradientOrganic

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

Journaling app sign-in — a full-screen stained glass with one cell following the pointer — Voronoi Pattern example 1

① Journaling app sign-in — a full-screen stained glass with one cell following the pointer

WhenThe sign-in screen opens: fourteen purple and blue cells drift behind the “Welcome back” card, and one of them moves with the mouse.
WhyA sign-in screen is empty by nature; the stained glass dresses it without distracting, and the cell answering the pointer adds a touch of life while you type your address.
Settingsdata-points="14" data-pointer="follow", data-colors with 7 cool hues, --vrn-height: 360px, --vrn-line: 3px, --vrn-bg: #120c1c. The card lets the pointer through to the background, except over the field and the button.
Web radio — a generated cover for each of the week's selections — Voronoi Pattern example 2

② Web radio — a generated cover for each of the week's selections

WhenThe selections page shows three cards; each cover is a small 8-cell diagram moving gently, in the palette of its mood.
WhyNo illustrator needed for every playlist: one colour list per selection is enough, and no two covers are ever the same.
SettingsThree 156 px roots (--vrn-height: 156px), data-points="8" data-speed="10", --vrn-line: 3px, --vrn-hue-speed: 16s, and one data-colors per card (night blues, sea blues, ambers).
Candle shop — a “Free delivery this weekend” strip at the top of the page — Voronoi Pattern example 3

③ Candle shop — a “Free delivery this weekend” strip at the top of the page

WhenThe 34 px strip stays at the top of every page during the offer; its warm shards slide slowly behind the message.
WhyAn announcement strip has to be noticed without blinking: slow movement and wax-like tones catch the eye, and the message sits in a dark, readable pill.
Settingsdata-points="18" data-speed="14", data-colors with 6 copper and brick tones, --vrn-height: 34px, --vrn-line: 1.5px, --vrn-seed: transparent to hide the dots.

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. The data-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.

Chrome 64+✓ Full (measured)
Firefox 69+✓ Full (measured)
Safari 13.1+✓ Full (measured on WebKit)
Edge 79+✓ Full (Chrome engine)
Safari iOS 13.4+✓ Not checked on a device
Chrome Android 64+✓ Full (measured at 390 px, touch)

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):

index.html — structure
<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 / propertyDefaultEffect
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

Yes. Each cell is the exact polygon of the points closest to its seed, computed by cutting the area along the bisectors between seeds. Seeds are visible (small light dots): you can check that every joint lies halfway between the two seeds it separates.
Not with the current settings: seeds start at random and drift. For a map of fixed zones, edit the build() function to read your coordinates and set data-speed="0".
With 12 seeds there are 132 polygon cuts per frame, well under a millisecond. The cost grows with the square of the seed count: at 60, expect nearly 27 times more. The work stops as soon as the diagram leaves the screen.