Very Early Playing with random() in CSS
Very Early Playing with random() in CSS êŽë š
WebKit/Safari has rolled out a preview version of random()
in CSS.
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.
Upon first play, itâs great!
Note
This is only in Safari Technical Preview right now. Iâll post videos below so you can see it, and link to live demos.
CSS processors like Sass have been able to do this for ages, but itâs not nearly as nice in that context.
- The
random()
numbers in Sass are only calculated at compile time. So they are only random at the time. Refreshing the page doesnât mean newly random values. - Random numbers are usually paired with a loop. So if you want 1,000 randomly placed elements, you need 1,000
:nth-child()
selectors with a randomly generated value in each, meaning bulky CSS.
With random()
in vanilla CSS, no such loops are needed and making the code quite simple and satisfying.
I found a 12-year-old Sass demo of mine playing with random()
that is like this:

chriscoyier
) compiled to over 200 lines of CSS.But now itâs just like this:

chriscoyier
)Much of the magic, to me, is how each matching element gets its own random values. So if you had three things like this:
<div class="thing"></div>
<div class="thing"></div>
<div class="thing"></div>
Then this simple CSS could make them all quite different:
.thing {
position: absolute;
background: red;
width: 100px;
height: 100px;
top: random(10px, 200px);
left: random(100px, 400px);
background: rgb(
random(0, 255),
random(0, 255),
random(0, 255)
)
}
The blog post doesnât mention âunitlessâ numbers like Iâve used above for the color, but they work fine. If youâre using units, they need to be the same across all parameters.
The âstarfieldâ demo in the blog post is pretty darn compelling!
I found another old demo where I used a bit of randomized animation-delay
where in the SCSS syntax I did it like this:
animation-delay: (random(10) / 40) + s;
Notice I had to append the âsâ character at the end to get units there. Now in vanilla CSS you just declare the range with the units on it, like:
animation-delay: calc(random(0s, 10s) / 40);
And it works great (chriscoyier
)!
The feature does have a spec, and Iâm pleased that it has covered many things that I hadnât considered before but are clearly good ideas. The blog post covers this nicely, but allow me to re-iterate:
.random-rect {
width: random(100px, 200px);
height: random(100px, 200px);
}
Both the width
and height
will be different random values. But if you want them to be the same random value, you can set a custom ident value that will âcacheâ that value for one element:
.random-square {
width: random(--foo, 100px, 200px);
height: random(--foo, 100px, 200px);
}
Nice!
But if you had 20 of these elements, how could you make sure all had the same random values? Well there is a special keyword for that, ensuring all matched elements share the same random values:
.shared-random-rect {
width: random(element-shared, 100px, 200px);
height: random(element-shared, 100px, 200px);
}
But in that case, all matched elements would share the same random values, but the width
and height
wouldnât be equal. So youâd do both to make sure itâs all equal:
.shared-random-squares {
width: random(--foo element-shared, 100px, 200px);
height: random(--foo element-shared, 100px, 200px);
}
Thatâs all very nicely considered, I think.
Ranges are also handled with a final parameter:
top: random(10px, 100px, 20px);
transition-delay: random(0s, 5s, 1s);
The top
value above can only be: 10px, 30px, 50px, 70px, or 90px.
The transition-delay
value above can only be: 0s, 1s, 2s, 3s, 4s, or 5s.
Otherwise you can get decimal values of either which might be more random than you want. Even 1px
for random pixel values as an increment seems to be suggested.
Note
Note the WebKit blog has a code sample with by 20deg
in it, which I think is a typo as that doesnât work for me.
I didnât have a chance to try it yet â but doesnât it make you wanna force a re-render and see if it will work with document.startViewTransition
??