CSS & layout

A polyfill for CSS random(), while the browsers catch up

A polyfill for CSS random(), while the browsers catch up

You want a wall of scattered stars, or ten paragraphs each nudged a fraction of a degree so the layout stops looking mechanical, and CSS today gives you two bad choices. Bake N variants and rotate through them with :nth-child. Or drop into JavaScript and set inline styles. Neither is layout. One is combinatorics; the other is a workaround.

CSS random() is the primitive that fixes that. Lee Meyer's post on CSS-Tricks tours the function and then builds a polyfill so you can start authoring against it before every engine ships — and, more usefully, so you learn what its caching keywords do before they start biting you.

The signature and the small print

Meyer's examples walk through the shape of the function. A range with an optional step:

--random-star-size: random(1px, 7px, 1px);

1px to 7px, in 1px increments. Drop the step and you get a continuous range:

--random-top: random(0%, 100%);
--random-left: random(0%, 100%);

Units can mix, as long as they resolve:

--random-rotation: random(2turn, 10turn, 20deg);

And var() references work inside the arguments, so a random value can be pinned to something you already computed:

--random-grid-area: random(1, var(--rows), 1) / random(1, var(--columns), 1);

Random column and random row, both bounded by the actual track counts. No JavaScript in the loop.

The keyword that decides how often the dice roll

The bit that separates random() from Math.random() in a stylesheet is what happens when the same rule matches many elements. By default each element gets its own value. The element-shared keyword flips that:

--random-rotation: random(element-shared, -45deg, 45deg);

Now every element that reads this custom property shares a single rolled value — the whole set tilts the same way. Useful when you want a group to feel randomized as a group, not a pile of independent individuals.

You can also key the sharing with a custom identifier, so two different properties on the same element roll together:

--random-height: random(--side, 40px, 100px);
--random-width: random(--side, 40px, 100px);

Both properties resolve against the --side key. Height and width get the same number. Squares, not rectangles.

That keyword is the part of the API worth memorizing. The units and the step are easy; the caching model is what will decide whether your layout reads as scattered or as suspiciously uniform.

Where it ships today

Meyer notes Safari 26.2 was the first browser to ship random(), in late 2025. Chromium has experimental support for random() and custom functions. Firefox has work in progress. Neither has committed to a timeline.

That gap is why the polyfill exists.

How the polyfill hooks in

The polyfill (css-random-polyfill, built on @csstools/css-calc) is a JavaScript package that reads computed styles on page load and substitutes concrete values in for the random() calls. It has two conventions you have to opt into: elements you want processed carry a .randomized marker class, and the custom properties holding the random() calls use a --random prefix. Inline random() calls inside a regular property are not processed. You route through a custom property first, and the polyfill reads that.

The indirection is not how the native feature will feel — but it maps onto how you should be writing random() anyway. Named custom properties for your random values, so a designer, or you next quarter, can see what each roll is for.

What to try, and what still has to land

If you want to feel out the semantics before every engine ships, wire up a small scatter demo. One custom property per axis. element-shared on the rotation. A keyed identifier on any pair that has to pair up. Read your own CSS out loud and check whether "shared" means what you think it does. That is the part that will trip you when the feature goes cross-browser and you can no longer blame the polyfill.

What is still missing is engine parity. Once Chromium and Gecko catch up to what Safari already ships, the polyfill retires and the same declarations keep working. Until then, the value of writing against it is not the visual effect. It is being fluent in the caching keywords by the time they matter.

Source: CSS-Tricks (css-tricks.com)

Related
CSS & layout

Animating border-image finally works if you register the gradient stop

Preethi's new CSS-Tricks piece animates a gradient border-image by wrapping one of its stops in a typed custom property. The trick unlocks a moving decorative border in pure CSS, and hits a wall the moment your box has rounded corners.

August 11, 2026
Browser releases

Safari Technology Preview 251 lands @supports at-rule(), random() with caching, corner-shape and object-view-box

WebKit's 26 August preview adds an at-rule test to @supports, property-scoped caching on random(), the random-item(), ident() and inherit() functions, the corner-shape and object-view-box properties, comma-separated @container conditions, white-space-trim in the white-space shorthand, and HighlightRegistry.highlightsFromPoint().

September 7, 2026
CSS & layout

Anchor positioning lets a resizing grid animate its reflow

A demo on bram.us animates an auto-fill grid's reflow on resize with CSS anchor positioning and a transition on inset. No JavaScript, no View Transitions, and interruptible.

September 8, 2026