Rolling the Dice with CSS random()

Random functions in programming languages are amazing.


This content originally appeared on WebKit and was authored by WebKit

Random functions in programming languages are amazing. You can use them to generate variations, to make things feel spontaneous and fresh. Until now there was no way to create a random number in CSS. Now, the random() function is on its way. You’ll be able to create a random animation delay, layout content at a random place on the screen, create a random color, or anything you want — all without any JavaScript.

The Basics

This new function has three arguments in this pattern: random(min, max, step). You state a minimum and maximum value to define the range from which the random number will be chosen. You can use any type of number (integer, percentage, length, angle, etc.) as long as all three arguments match. The step argument is optional, but is particularly useful for when you want to ensure round numbers.

For example, random(0, 100, 2) will choose an even number between 0 and 100, while random(0turn, 1turn) will be a fraction of a turn — basically, any decimal between 0 and 360 degrees.

Let’s take a look at how to use random() by going through several demos. We’ll start by creating a field of stars out of HTML and CSS.

A star field with CSS and HTML

A pure CSS star field using randomly placed circles, glow effects and four-pointed stars
<html>
<body>
    <div class=star></div>
    <div class=star></div><div class=star></div>
  </body>
</html>

We’ll start by creating an HTML element for each star. Then paint the sky and style the stars with white circles of any size for now to act as stars. Setting the star to be fixed positioning will make it easy to place them randomly.

body {
  background-color: black;
}

.star {
  background-color: white;
  border-radius: 50%;
  aspect-ratio: 1/1;
  width: 3px;
  position: fixed;
}    

Now we’ll distribute the stars by setting the top and left properties to a random value, in this case 0-100% for top (Y-axis) and a separate random value for left (X-axis). By default, each random() function will generate different random values using a different random base value generated from a uniform distribution.

.star {
  background-color: white;
  border-radius: 50%;
  aspect-ratio: 1/1; 
  width: 3px;
  position: fixed;
  top: random(0%, 100%);
  left: random(0%, 100%);
}
Randomly placed dots

For a more dynamic look, make the size of the “stars” random as well.

.star {
   background-color: white;
   border-radius: 50%;
   aspect-ratio: 1/1; 
   width: random(2px, 10px, 1px);
   position: fixed;
   top: random(0%, 100%);
   left: random(0%, 100%);
 }

Notice that the top and left random values used percentages. But for width you can select a random size based on pixels instead. Just remember that whatever unit you use needs to be the same for each parameter. The third argument used in the example above is used to ensure star sizes are in 1px increments for a well-rounded number to give a better spread of sizes for more variety.

Randomly sized circles for stars

The idea can be taken further by adding some special effects, like adding a subtle glow to the stars with layered drop shadows and blending effects.

.star {
    --star-size: random(--random-star-size, 1px, 7px, 1px);
    background-color: white;
    border-radius: 50%;
    aspect-ratio: 1/1;
    width: var(--star-size);
    position: fixed;
    top: random(0%, 100%);
    left: random(0%, 100%);
    filter: drop-shadow(0px 0px calc(var(--star-size) * 0.5) oklch(0.7 0.2 random(0, 100))) 
            drop-shadow(0px 0px calc(var(--star-size) * 2) white);
    mix-blend-mode: hard-light;
}

Shared randomness and custom properties

The --star-size custom property allows re-using the randomly generated pixel size, but there are some important details to using custom properties with random(). First, you’ll see what looks like another custom property as the first parameter of the random() function. The --random-star-size name used here is known as an ident. It’s used to ensure the random value generated is used in the other random() function calls where the same ident is provided.

You might be asking, why is that necessary here? It’s important to realize that setting a custom property to a CSS function isn’t like other programming languages where a variable stores a result. Custom properties are more like a simple text replacement mechanism. That means wherever you are calling that custom property with var() what’s actually happening is something more like text substitution, replacing the var() with a duplicate of the property you declared. In the case of this example, that means another random() call, not the resulting value of the function.

Back to the example, an ideal blur effect for the glow will need to be based on whatever the random size of the star ends up being. That’s doable using a calc() to use a factor of the star size for the blur size of the layered drop shadows. Doing that means depends on getting the same value of randomness so using the named ident is the right approach.

The first drop shadow also uses random() to select a hue with oklch() to add vibrant colors that are composited over a soft white glow with a hard-light blend mode. The combination adds a subtle, but dynamic colorization to the stars.

Random glowing circles for stars

Using a named ident shares the randomness across the properties of a single element. It’s one of the many ways to share randomness. The random() function has variety of approaches depending on your needs. You can also use the element-shared value to share a random value for a given property across all matched elements, or mix the two to share the value everywhere. Unlike a named ident, which will share the value whenever the ident is used, element-shared will share the random value for a given property across all the elements it applies to.

One way to see this work in the star field example is to add some four-pointed stars with a simple glyph.

.star.fourpointed {
    clip-path: shape(from 50% 0%,line to 50.27% 3.25%, …);
    --star-size: random(--random-four-point-size, 20px, 60px, 1px);
    rotate: random(element-shared, -45deg, 45deg);
}
Randomly placed and rotated four-pointed stars

A CSS shape() is used to define the four-pointed glyph that will clip the circular white background. The star size can still be random but will need boosted to an order of magnitude larger to feel right. A more realistic styling for these stars comes from finding a way to mimic the diffraction rays that are seen in images of stars. They all angle the same way for may important physics reasons. So while a static degree of rotation could be assigned, it’s a tad more fun and dynamic to assign one randomly. But doing that effectively means finding a way to use the same random angle for all of the four-pointed stars.

That’s where element-shared comes into play. The element-shared value generates a random value shared by all elements for that property. That makes all of the four-pointed stars rotate with the same random angle.

Here’s the complete version of the star field example that you can experiment with: https://codepen.io/jdatapple/pen/YPyELeV

Randomly placed rectangles

There are lots of other ways to make use of random(). Building on some of the concepts of the star field example, you can explore using random() with layout tools like grid.

Randomly placed, randomly colored rectangles

In this variant example, the webpage area is equally divided into 100 rows and 100 columns. Then randomly colored rectangles are positioned at random in the grid:

.grid {
  display: grid;
  --rows: 100;
  --columns: 100;
  grid-template-rows: repeat(var(--rows), 1fr);
  grid-template-columns: repeat(var(--columns), 1fr);
  width: 100vw;
  height: 100vh;
}

.rectangle {
  background-color: lch(100% 90% random(0deg, 360deg));
  grid-area: random(1, var(--rows), 1) / random(1, var(--columns), 1);
}

You can view the final result on any browser that supports random(): https://codepen.io/ntim/pen/dPYGJxj

Stacks of Photos

Another example of making use of random() is creating stacks of photos that are randomly placed and oriented to look like they’ve been tossed on top of each other. You can spend a lot of time setting all of the photos just so, or let the computer procedurally generate it each time the page is loaded.

Stacks of desert landscape photos with images randomly rotated with randomly offset placement
.stack img {
    width: 100%;
    grid-column: 1;
    grid-row: 1;
    border: 10px solid hsl(0, 100%, 100%);
    box-shadow: 10px 10px 40px hsl(0, 0%, 0%, 20%);

    --random-rotate: rotate(random(-1 * var(--rotate-offset), var(--rotate-offset)));

    transition: .3s ease-out;
    transform: var(--random-rotate);
    transform-origin: random(0%, 100%) random(0%, 100%);
}

More than that, it’s also straightforward to include randomness in interactivity. Adding random translation to the hover state of the images adds to the whimsy:

.stack:hover img {
    transform: var(--random-rotate) translateX(random(-1 * var(--translate-offset), var(--translate-offset))) translateY(random(-1 * var(--translate-offset), var(--translate-offset)));
}

Wheel of Fortune

Random rotation example of a wheel sliced into 20 pieces with emoji placed in every other slice and a green spin button

The random() function can even be used to create interactive elements that need unpredictable outcomes. The wheel of fortune demo showcases this perfectly.

@keyframes spin {
    from {
        rotate: 0deg;
    }
    to {
        rotate: 10turn; /* Fallback for browsers that don't support `random()` */
        rotate: random(2turn, 10turn, by 20deg);
    }
}

When the “SPIN” button is clicked, the @keyframe animation uses random() to generate a rotation value that sets when and where the wheel lands. This example highlights the growing capabilities available in modern CSS defining all of the interactivity, randomness, and animation in the stylesheet.

You can see the demo in action here: https://codepen.io/ntim/pen/WbQrMow

A handy randomness reference

There are lots of different ways to use random() depending on what you need and different ways to share the randomness between elements.

Maximum randomness

Both properties get a different value, and it’s different per element too, so you get lots of random rectangles.

.random-rect {
  width: random(100px, 200px);
  height: random(100px, 200px);
}

Shared by name within an element

Using an ident both properties get the same value, but it’s still different per element, so you get lots of random squares.

.random-square {
    width: random(--foo, 100px, 200px);
    height: random(--foo, 100px, 200px);
}

Shared between elements within a property

With element-shared both properties get different values, but they’re shared by every element, so you get lots of identical rectangles of a single random size.

.shared-random-rect {
    width: random(element-shared, 100px, 200px);
    height: random(element-shared, 100px, 200px);
}

Shared by name globally

Using both a named ident and element-shared means both properties get the same value, and every element shares the random value, so you get lots of identical squares of a single random size.

.shared-random-squares {
    width: random(--foo element-shared, 100px, 200px);
    height: random(--foo element-shared, 100px, 200px);
}

Try it out and tell us how it goes

You can try out the random() function today in Safari Technology Preview! However, it’s important to note that there are ongoing discussions in the CSS Working Group about the specification, and several open issues remain about whether this approach best serves developers’ needs.

While the examples above demonstrate the exciting possibilities, we’re actively asking for feedback from the web development community to help shape the final direction, and you can help. If you experiment with random() in Safari Technology Preview, we’d love to hear about your experience. What works well? What feels awkward? Does the way shared values are expressed make sense to you? Do you have use cases that are missing? Or better suggestions for the name of element-shared? Your feedback will directly influence how this feature moves forward from its current form. This is a chance for you to help shape CSS—try it out and let us know what you think.

You can share your feedback with me, Jon Davis, on Bluesky / Mastodon, or our other evangelists — Jen Simmons, on Bluesky / Mastodon, or Saron Yitbarek, on BlueSky. You can also follow WebKit on LinkedIn. If you find a bug or problem, please file a WebKit bug report.


This content originally appeared on WebKit and was authored by WebKit


Print Share Comment Cite Upload Translate Updates
APA

WebKit | Sciencx (2025-08-21T19:02:33+00:00) Rolling the Dice with CSS random(). Retrieved from https://www.scien.cx/2025/08/21/rolling-the-dice-with-css-random/

MLA
" » Rolling the Dice with CSS random()." WebKit | Sciencx - Thursday August 21, 2025, https://www.scien.cx/2025/08/21/rolling-the-dice-with-css-random/
HARVARD
WebKit | Sciencx Thursday August 21, 2025 » Rolling the Dice with CSS random()., viewed ,<https://www.scien.cx/2025/08/21/rolling-the-dice-with-css-random/>
VANCOUVER
WebKit | Sciencx - » Rolling the Dice with CSS random(). [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/08/21/rolling-the-dice-with-css-random/
CHICAGO
" » Rolling the Dice with CSS random()." WebKit | Sciencx - Accessed . https://www.scien.cx/2025/08/21/rolling-the-dice-with-css-random/
IEEE
" » Rolling the Dice with CSS random()." WebKit | Sciencx [Online]. Available: https://www.scien.cx/2025/08/21/rolling-the-dice-with-css-random/. [Accessed: ]
rf:citation
» Rolling the Dice with CSS random() | WebKit | Sciencx | https://www.scien.cx/2025/08/21/rolling-the-dice-with-css-random/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.