Why CSS random() Matters
For years, developers have reached for JavaScript to add controlled randomness to UIs—confetti bursts, scattered starfields, randomized grid layouts. But CSS is on a mission to absorb common UI patterns into declarative standards, and random() is the latest step.
Safari became the first browser to support CSS random() in late 2025, but Chrome and Firefox are still working on it. If you want to use this feature today across all browsers, you need a polyfill. This guide shows you how.
Evidence: This article is based on the original CSS-Tricks post about the css-random-polyfill package.

How the Polyfill Works
The polyfill leverages a clever property of CSS: custom properties can hold any string value, even if the browser doesn't understand the syntax. JavaScript can read these values via getComputedStyle() and replace them.
Here's the core logic:
import { calc } from "@csstools/css-calc";
if (!CSS.supports("width", "random(0px, 100px)")) {
// Hide elements while we resolve random values
const styleTag = document.createElement("style");
styleTag.textContent = ".randomized { display: none; }";
document.head.appendChild(styleTag);
const elementIDs = new WeakMap();
const documentID = crypto.randomUUID();
document.querySelectorAll(".randomized").forEach((element) => {
const styles = getComputedStyle(element);
[...styles]
.filter((property) => property.startsWith("--random"))
.forEach((propertyName) => {
const css = styles.getPropertyValue(propertyName);
const value = resolveRandom(css, {
element,
propertyName,
documentID,
elementIDs,
calcFn: calc,
crypto,
});
element.style.setProperty(propertyName, value);
});
});
// Unhide elements
if (styleTag.parentNode) {
styleTag.parentNode.removeChild(styleTag);
}
}
Step-by-Step Breakdown
- Feature detection: If the browser natively supports
random(), do nothing. - Hide elements: Temporarily hide
.randomizedelements to prevent flicker. - Read custom properties: Loop through all
--randomprefixed properties. - Resolve values: Use
@csstools/css-calcto interpret therandom()expression. - Apply inline styles: Set the resolved value back on the element.
- Unhide: Remove the temporary style tag.
The key insight is that CSS custom properties are extremely permissive—they accept any string, even invalid syntax. This gives JavaScript a clean extension point without needing to parse stylesheets.

Limitations and Caveats
- Editor's draft status: CSS
random()is still in early exploration. Major breaking changes are expected. - Dynamic updates: The polyfill only processes computed styles on initial page load. Dynamic DOM changes won't be re-evaluated.
- Distribution quirk: The underlying
@csstools/css-calclibrary doesn't always generate evenly distributed values without a base parameter—the polyfill patches this by injecting a random base. - Not a full implementation: The polyfill supports a subset of native
random()syntax. Once native support goes baseline, you can remove the script and your CSS will still work.
Next Steps
- Try the starfield demo to see the polyfill in action.
- Explore
random-item()(Chromium-only bonus) combined with CSS custom functions for list-based random selection. - Keep an eye on Chrome and Firefox implementation timelines.
Related reading: If you're interested in responsible AI tooling, check out our guide on responsible developer AI coding tools. For workflow automation, see Introducing Daggr: Build AI Workflows in Code.

Conclusion
CSS random() is a glimpse into a more declarative future for web design. While native support is still limited to Safari, the polyfill lets you experiment today—and your code will remain compatible when native support lands.
The approach also reveals a broader pattern: using CSS custom properties as a bridge between declarative CSS and imperative JavaScript. This technique can be applied to other emerging CSS features waiting for cross-browser support.
Happy randomizing!