In his moral philosophy book How to Be Perfect—a non-fiction companion to his hit television comedy The Good Place—creator Mike Schur dedicates a chapter titled "The Luck of the Draw" to examining how the myth of meritocracy leads individuals to routinely underestimate the role luck plays in their successes. Schur’s philosophical exploration mirrors a broader reality in natural systems and modern computing: deterministic predictability often fails to capture the true nature of reality. In quantum mechanics, physics famously suggests that nature plays dice with the universe. In web design, an intriguing parallel has emerged as user interfaces increasingly embrace controlled chaos and subtle non-determinism.
From dynamic web layouts that subtly shift each time a user visits to generative user interfaces being tested across platforms like Google Search, nondeterministic design is having a distinct moment. As ancient philosopher Heraclitus famously observed, one cannot step into the same river twice. Web designers are applying this principle to the digital canvas, crafting experiences that feel alive precisely because they avoid exact repetition. Yet, achieving presentational randomness on the web has historically required heavy JavaScript frameworks or complex build processes, introducing friction to what should ideally be simple design enhancements.
Real-world use cases for randomness
In web development consulting, greenfield projects frequently serve as an early indicator of emerging design trends and enterprise priorities. Across client engagements, requests for presentational non-determinism have steadily moved from experimental ideas to practical requirements. A classic example is the ubiquitous celebratory confetti burst triggered upon running a randomized draw. While conceptually simple, client requirements often demand that every single floating particle strictly aligns with brand guidelines while maintaining organic unpredictability.
Engineers frequently discover that off-the-shelf JavaScript plugins fall short when fine-grained styling and brand rules are introduced. On recent client projects, teams have had to ditch lightweight third-party scripts to roll custom confetti engines from scratch. This friction underscores an ongoing tension in user interface engineering: balancing the desire for organic presentational chaos with the strict demands of design control.
This practical challenge raises a broader architectural question for the web platform: why shouldn’t controlled presentational randomness exist directly in CSS?
The custodians of CSS standards have long maintained a philosophy of "paving the cowpaths"—taking common user interface patterns developed through custom scripts and formalizing them into declarative CSS specifications. In late 2025, this philosophy reached a significant milestone when Apple’s WebKit engine became the first to support the native CSS random() function as part of the Safari 26.2 release. The update emphasized solving everyday design patterns using declarative HTML and CSS alone, reducing reliance on third-party JavaScript libraries and complex build tooling.
/* Example of native CSS random syntax */
.particle
width: random(2px, 10px);
opacity: random(0.2, 0.9);
Since Safari’s initial deployment, web developers have demonstrated practical applications for native randomness. Web developer Schalk Neethling showcased fine-grained confetti controls built purely with CSS random(), while developer Alvaro Montoro highlighted how native randomness aligns with the W3C Technical Architecture Group’s Rule of Least Power. That principle dictates that web features should be solved using the least powerful language capable of expressing them—favoring declarative CSS over imperative JavaScript wherever possible.
However, cross-browser availability remains a major bottleneck. Half a year after Safari introduced native CSS random(), standard implementation timelines for competing browsers remain uncertain. While public issue trackers confirm active development work within Chromium and Firefox, neither browser engine has offered a definitive release timeline or enabled public runtime flags for the feature.
This browser disparity creates a practical dilemma for front-end developers. While Safari users on modern OS updates can render native CSS random() declarations, developers working across Windows, Linux, or Android environments cannot test these native implementations locally without polyfills or fallbacks. Furthermore, the specification itself—governed by the CSS Values and Units Module Level 5—remains an Editor’s Draft, where syntactical options for caching, keying semantics, and base value intervals are still subject to potential breaking changes.
/* Advanced keying and caching semantics in the CSS Values Level 5 draft */
.item
--random-width: random(--shared-key, 100px, 300px);
Polyfilling CSS features has historically been fraught with technical landmines. Standard polyfilling approaches often require fetching external stylesheets, parsing non-standard syntax at runtime, and rewriting document styles on the fly—frequently introducing performance penalties or rendering artifacts.
Let’s polyfill CSS random()
The browser ecosystem presents a historical reversal in the case of CSS random(). Front-end engineers are accustomed to testing emergent web features first in Chromium-based browsers before waiting for WebKit implementation. For CSS random(), the reverse occurred, leading developers on non-Apple platforms to watch Safari-exclusive demos from afar.
Furthermore, even within the Apple ecosystem, Safari updates remain tightly coupled to operating system releases. Users on older hardware or delayed OS update schedules cannot access native WebKit feature additions immediately. To bridge this divide, an open-source client-side solution was released in the form of the css-random-polyfill package, designed to bring cross-browser support to random() expressions today.
The polyfill builds directly upon open-source research and WebKit Preview demonstrations initially shared by Apple’s WebKit team, adapting native syntax into a backwards-compatible format that operates safely across Chrome, Firefox, and legacy browsers.
Demo: Random starfield
One of the central showcase examples released by the WebKit team features a dynamic starfield: a sky of randomly scattered stars that fade in and out at unpredictable intervals. In this scene, four-pointed accent stars tilt at a shared, randomly assigned angle, while all ambient stars cast subtle drop-shadows with randomly generated color hues using the oklch() color space.
To make this original Safari-exclusive demonstration function across all modern engines, the implementation uses a lightweight client script while decorating target elements with a dedicated .randomized marker class:
<!-- Include the polyfill script to parse CSS random expressions at load time -->
<script src="https://unpkg.com/css-random-polyfill@latest/dist/css-random-polyfill.js"></script>
<!-- Target elements marked for processing -->
<div class="randomized star"></div>
<div class="randomized star"></div>
<div class="randomized star fourpointed"></div>
<div class="randomized star fourpointed"></div>
On the styling side, rather than introducing custom, non-standard CSS selectors that require heavy runtime translation, the polyfill leverages valid CSS custom property declarations. By prefixing variable names with --random, the CSS syntax remains valid under standard CSS parsing rules, even in engines that have no native understanding of the random() function:
.star
--random-star-size: random(1px, 7px, 1px);
background-color: white;
border-radius: 50%;
aspect-ratio: 1/1;
width: var(--random-star-size);
position: fixed;
--random-top: random(0%, 100%);
--random-left: random(0%, 100%);
top: var(--random-top);
left: var(--random-left);
--random-hue: random(0, 360);
filter: drop-shadow(0px 0px calc(var(--random-star-size) * 0.7) oklch(0.7 0.2 var(--random-hue)))
drop-shadow(0px 0px calc(var(--random-star-size) * 3) white);
mix-blend-mode: hard-light;
--random-speed: random(2s, 5s);
animation: fade-in var(--random-speed);
animation-iteration-count: infinite;
--random-delay: random(2s, 5s);
animation-delay: var(--random-delay);
animation-direction: normal;
This starfield configuration demonstrates critical features of the CSS Values Level 5 spec, including step intervals—such as restricting generated values to whole integers between 1px and 7px:
--random-star-size: random(1px, 7px, 1px);
It also demonstrates the element-shared caching keyword, ensuring that every element matching the rule shares the exact same rotation value:
.star.fourpointed
--random-rotation: random(element-shared, -45deg, 45deg);
rotate: var(--random-rotation);
Crucially, the polyfill operates conditionally. When loaded inside a browser with native random() support (such as modern Safari), the script steps aside entirely, allowing the native WebKit engine to handle value resolution natively. If native support eventually reaches universal baseline status across all major browsers, developers can remove the polyfill script tag without altering their underlying stylesheet logic.
Demo: Random colored grid cells
Industry commentators, including web designer Chris Coyier, praised the visual impact of declarative randomness in early WebKit demos. While a randomized twinkling starfield demonstrates subtle atmospheric background effects, other examples test the boundaries of complex layout systems.
A secondary test case involves a 100×100 CSS Grid layout where individual grid cells receive randomized color values and dimensions. This scenario tests multi-value substitution and inline custom property references within single function calls. For instance, developers can construct a shorthand grid-area assignment by nesting variable calls directly inside random() expressions:
.rectangle
--random-grid-area: random(1, var(--rows), 1) / random(1, var(--columns), 1);
grid-area: var(--random-grid-area);
In this implementation, the polyfill parses custom variables passed as constraints (var(--rows) and var(--columns)), resolving mathematical parameters before assigning computed positions across the grid container.
Demo: Wheel of fortune
Another core demonstration comes from Safari team engineer Tim Nguyen, who presented early implementation details at Web Directions 2025. His interactive example features a spinning wheel of fortune that lands on a dynamically calculated angle using mixed unit dimensions.
@keyframes spin
from
rotate: 0deg;
to
rotate: var(--random-rotation);
#wheel
--random-rotation: random(2turn, 10turn, 20deg);
This demonstration highlights a key requirement of the CSS Values Level 5 specification: supporting mixed, compatible units within the same mathematical expression. The function accepts a minimum parameter in turns (2turn), a maximum parameter in turns (10turn), and a step interval in degrees (20deg).
Under CSS typed arithmetic rules, parameters are valid as long as they resolve to the same underlying data type—in this case, angular dimension values. The polyfill calculates unit conversions dynamically, converting turns and degrees into unified values prior to applying computed styles.
To maintain simplicity, the initial release of css-random-polyfill calculates values against computed styles present during the document’s initial DOM load. While dynamic updates tied to dynamic mutation observers or runtime state changes remain a potential area for future enhancement, evaluating initial computed styles fulfills the majority of presentational use cases without introducing persistent runtime overhead.
Demo: Random squares
In an example illustrating basic usage patterns, Chris Coyier crafted a minimal demo featuring randomly positioned, colored squares. Modifying this minimal test case allows developers to evaluate custom key sharing—a mechanism defined in the CSS spec to synchronized random distributions across distinct properties.
--random-height: random(--side, 40px, 100px);
--random-width: random(--side, 40px, 100px);
width: var(--random-height);
height: var(--random-width);
By providing a custom identifier (--side) as the first argument, both the height and width calls reference the exact same generated value for a given element, ensuring that generated rectangles retain a perfect 1:1 aspect ratio without relying on separate utility classes.
Chromium-only bonus demo: Simulate random-item using a custom CSS function
While generating numbers within defined ranges solves many presentational needs, developers frequently require selecting non-numeric values—such as discrete color keywords, string values, or layout keywords—from an arbitrary list.
To address this, the W3C draft specification outlines a complementary function: random-item(). The function accepts caching options followed by an arbitrary list of parameters:
/* Draft syntax for picking discrete values */
color: random-item(element-shared, red, blue, green);
Currently, random-item() lacks implementation in mainstream stable browsers, appearing only experimentally in Safari Technology Preview releases. However, in Chromium environments where modern CSS features like CSS custom functions (@function) and style queries (style()) are active, developers can simulate random-item() behavior by combining random() with conditional logic.
--random-index: random(element-shared, 1, 5, 1);
--random-color: --item(var(--random-index), aqua, purple, pink, grey, green);
The underlying custom function utilizes inline conditional evaluations to map an integer index to an arbitrary parameter slot:
@function --item(--index,
--arg-1: ,
--arg-2: ,
--arg-3: ,
--arg-4: ,
--arg-5: ,
--arg-6: ,
--arg-7: ,
--arg-8: ,
--arg-9: ,
--arg-10: )
result: if(
style(--index: 1): var(--arg-1);
style(--index: 2): var(--arg-2);
style(--index: 3): var(--arg-3);
style(--index: 4): var(--arg-4);
style(--index: 5): var(--arg-5);
style(--index: 6): var(--arg-6);
style(--index: 7): var(--arg-7);
style(--index: 8): var(--arg-8);
style(--index: 9): var(--arg-9);
else: var(--arg-10);
);
Historically, techniques for selecting array items in CSS—such as methods pioneered by CSS developer Temani Afif—relied on clever mathematical workarounds constrained specifically to color data types. By contrast, leveraging user-defined functions alongside random() offers a general-purpose mechanism for selecting arbitrary data types from structural lists using declarative web standards.
How the polyfill works
Building a client-side polyfill for CSS properties without modifying native browser rendering pipelines requires leveraging low-level features of modern browser APIs. Rather than authoring a custom CSS parsing engine from scratch, css-random-polyfill utilizes existing open-source tooling from the CSSTools ecosystem.
Specifically, the polyfill incorporates @csstools/css-calc, a standalone mathematical evaluation engine maintained as part of the PostCSS plugin ecosystem. While originally built for build-time CSS transformations, recent updates brought full compliance with the updated caching and resolution rules in the CSS Values and Units Module Level 5.
import calc from "@csstools/css-calc";
const calcFn = calc;
// Feature detection: Check if the engine natively supports CSS random()
if (!CSS.supports("width", "random(0px, 100px)"))
// Inject a temporary stylesheet to prevent Flash of Unstyled Content (FOUC)
const styleTag = document.createElement("style");
styleTag.textContent = ".randomized display: none; ";
document.head.appendChild(styleTag);
const elementIDs = new WeakMap();
const documentID = crypto.randomUUID();
// Query and process marked elements
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,
crypto,
);
element.style.setProperty(propertyName, value);
);
);
// Restore visibility once styles are applied
if (styleTag.parentNode)
styleTag.parentNode.removeChild(styleTag);
function resolveRandom(css, element, propertyName, documentID, elementIDs, calcFn, crypto ) --))([^,]+),/gi,
(_, expression) => `random(fixed $Math.random(), $expression,`
);
return calcFn(patchedCss,
precision: 5,
toCanonicalUnits: true,
randomCaching:
documentID,
elementID: elementIDs.getOrInsert(element, `element-$crypto.randomUUID()`),
propertyName,
,
);
The polyfill’s execution pipeline follows distinct operational steps:
- Feature Detection: The script executes
CSS.supports("width", "random(0px, 100px)")to evaluate native browser capability. If the browser returnstrue, execution halts immediately, yielding entirely to the native browser engine. - FOUC Prevention: In non-supporting browsers, the script temporarily injects a
<style>block setting.randomized display: none;to prevent unstyled elements from jumping during initial paint. - DOM Inspection & Scoping: The script iterates across all elements bearing the
.randomizedclass, initializing a unique UUID context for the document and mapping element instances using a nativeWeakMap. - Computed Style Extraction: Using
getComputedStyle(), the script reads inline property values assigned to variables prefixed with--random. Because custom properties accept arbitrary token streams as valid syntax under standard CSS specs, browsers retain these unparsedrandom()strings intact within the computed style object. - Expression Resolution: The polyfill passes the retrieved CSS string through
@csstools/css-calc, providing tracking keys, element identifiers, and cryptographic scope identifiers. The evaluation function transforms unit types, resolves intervals, calculates deterministic or non-deterministic seeds, and returns finalized CSS values (such as42pxoroklch(0.7 0.2 180)). - Style Application & Unmasking: The resolved final values are written directly back to the element’s inline
styleobject, overriding the pending custom property, and the temporary hiding style block is removed from the DOM.
By restricting input values to valid CSS custom properties starting with --random, the polyfill bypasses traditional CSS polyfill architectural flaws. It avoids making secondary network requests for CSS files, eliminates the need to re-parse raw style tags, and leaves global stylesheet rules intact.
The Future of Declarative Randomness
The emergence of open-source polyfills for CSS random() marks a practical shift in how developers can approach nondeterministic web design. Rather than waiting years for cross-browser vendor parity across Apple, Google, and Mozilla engines, designers and engineers can begin implementing declarative randomness into production codebases today using standard CSS syntax conventions.
As standard bodies continue refining the CSS Values and Units Module Level 5 specification, client-side polyfills provide an important real-world testing ground. By lowering the barrier to entry for presentational randomness, the web platform moves one step closer to making organic, unpredictable, and dynamic user interfaces accessible to every designer through pure HTML and CSS.