Pangram verdict · v3.3
We believe that this document is fully human-written
AI likelihood · overall
HumanArticle text · 2,021 words · 6 segments analyzed
CSS is getting a random() function that lets you set properties with a random value, letting you make interesting and creative new designs. It's available in Polypane 29+ for testing, as well as in Chromium 148+ with experimental features enabled.Safari 26.2+ also support random(), but doesn't fully support all the demos I show in this article. Firefox currently has no support for random().Use Polypane 29+, Safari 26.2 or Chromium 148+ with experimental features enabled to try out the demos in this article. If you want to see the demos in action, you can get Polypane and try it for free.I made some demosI spend a few weeks coming up with different examples of how to use random() to create interesting designs, patterns and backgrounds.A note on the code examplesWe're using random() directly in the code examples below, and don't have a fallback for browsers that don't support it yet. If you want to see the examples in action, you can get Polypane and try it for free.The code examples have fully editable CSS, but only show the relevant CSS for each effect (for example the bokeh below does show the positioning, but not the border-radius).You can edit the CSS in the examples to see how it works. In the code example we only show the most relevant CSS, but if you copy the code you'll get the full HTML and CSS for the example. Click the 'randomize' button to reload the example with a new random value for each property.A note on browser supportThe implementation in browsers is ongoing, and it's behind the experimental web features flag for a reason.Some of the demos don't work well in Safari.
We're pretty sure some of the examples below won't survive upcoming changes to the implementation and we needed to do some trickery to make sure we support both Polypane 29 (based on Chromium 148) and later versions of Chromium since the implementation evolved between version 148, 149 and 150.We'll keep this article evergreen but if you're in the future right now and notice some of the demos no longer work, please let us know and we'll update the article!Bokeh effectWhen I saw that random() was available in Polypane 29, I immediately wanted to try it out.One of my favorite "random design" type things is bokeh, which is a photography effect that creates out-of-focus light spots. I thought it would be fun to try to create a bokeh effect using random(). So I grabbed the MDN page on random() and got to work.If you look at a bokeh effect, it's essentially a bunch of circles that differ in a few ways:the position of the circlesthe size of the circlesthe color of the circlesthe out-of-focus-ness of the circlesthe rate at which they change (if it's an animated bokeh)PositionThe position of the circles is easiest: set them to position:absolute, and then use random() in the left and top properties. This will place the circles at random positions:The random() function in its simplest form takes a minimum (0%) and a maximum (100%) and returns a random value between those values.Note: The minimum size here is 0, but it has to include the % to make sure both values are of the same type. If you just put random(0, 100%), it would be invalid because the minimum is a <number> and the maximum is a <percentage>.SizeEach circle in a bokeh effect has a different size, but it's still a circle. So if we want to use random() to set the size, we need to make sure that the width and height are the same value.My idea was to 'store' the random value in a custom property (like --size: random(50px, 20vmin)) and then use that custom property for both the width and height.
That way, the width and height will always be the same value.Or so I thought.Yikes, width and height are different!When you set a custom property to a random value, it will generate a new random value every time you use that custom property, not just when you declare it.To fix this, we have to add a custom keyword to the random function called element-scoped.This tells the browser to generate one random value per element. So each element gets a different random value, but the width and height of each element will be the same:Note: element-scoped is not the final name for this feature, but it's the one currently supported in Polypane and Safari. It will be renamed to per-element. Neither is yet part of the MDN docs, though a PR has been submitted to add it.Position, revisitedI wanted to start with the position because it was simplest, but the position actually has an issue: if a circle starts at 99% from the left and has a size of 100px, it will overflow the container and cause scrollbars.To fix this, we can use calc() to subtract the size of the circle from the position:We don't know exactly what the size of the circle is, but because --size is the same for this element in each property, we can use it to be sure that the circles are always fully within the container.The color of the circlesFor the colors of the circles, I wanted all of them to be roughly the same lightness and saturation, but each circle to have a different hue. So I used the hsl() function with random() for the hue value.Additionally, when you look at images of bokeh, some circles are more visible and some are less visible. So I also added a random opacity:The hue in HSL is just a number, so it doesn't need a unit. The same goes for opacity.Note: We've increased the number of circles in this and the next few examples so the effect is more clearly visible.Out-of-focus-nessNext up, some of the circles in a bokeh image are really sharp while others are more blurry.In CSS, we can achieve a blur effect with the filter: blur() function. When you add a blur you also lose some of the vibrancy that some of the colors have, so I also added a contrast() filter to make some of the circles more vibrant.
Lastly, I added a mix-blend-mode to make the circles blend together using "plus-lighter", That increases the brightness of the circles where they overlap, which makes it look more like real bokeh:That blur helps make the circles look more like actual bokeh circles, and the contrast makes some of them look more vibrant and some of them look more dull, which adds to the effect.For contrast we specifically chose a range where most random values would increase the contrast (the 100% to 200% range) and only a handful of circles would have a contrast value that decreases the contrast (the 50% to 100% range).AnimationFinally, I wanted to add some animation to the bokeh circles. When you look at bokeh through a camera and you increase and decrease the focus, some circles become larger and more blurry, while others become smaller and sharper.The easiest way to do that is with a simple pulse animation. We only need to define the 50% keyframe. The 0% and 100% keyframes will be the default state of the element (a scale of 1).@keyframes pulse { 50% { scale: 1.2; } }We can re-use this same animation for all circles, because we can set the animation timing and the animation delay to a random value for each circle. This way, each circle will pulse at a different rate and start at a different time, which makes the animation look more natural:.bokeh { animation: pulse random(2s, 5s) ease-in-out infinite; animation-delay: random(-5s, 0s); }We let the animation run infinitely so it just keeps looping with an ease-in-out timing function to smooth out the start and end of each pulse. By setting a random negative delay, some circles will start the animation somewhere in the middle, which makes it look more natural as you refresh the page. If we only used no delay or a positive delay, all circles would start their animation by growing.
Combining it allSo when we combine all of these properties together, we get this:Note For animations like the one above that have animations, we show a "show demo" button to activate the preview, for two reasons: 1) the animation can be distracting or annoying and 2) it can be performance-intensive.Falling flower petalsWe have a cherry tree in our backyard, and when the wind blows in spring, the petals fall off the tree and float down to the ground. It's very soothing.I thought it would be fun to try to recreate that effect using random(), and lets front-load the final animation so you can see what we're trying to achieve:Note In Safari sometimes you don't see any petals in the demos. If that happens, click randomize a few times. I don't know why this happens, but it seems to be a Safari bug.Lets look at what parts need to be random to achieve this result.The petals all need to start at a different position off-screenThey should all be a slightly different size and should look a little differentThey all need to move vaguely in the same direction as if blown by the wind, but each petal should fall slightly differentlyThey should fall at different speedsThey should randomly twirl as they fallStarting positionThe starting position of each petal should be above the current viewport, and then randomly across the width of the viewport so that they each fall from a different place.For the top value we can use a fixed one so they all start at the same place, and then for the horizontal starting value, we'll use a custom property, since we're going to reuse it once we get to the falling animation.We'll use element-scoped so that each petal has a different starting position, and we're not going to set left, but translate because we want to animate the petals falling down the screen, and animating translate is more performant than animating left:.petal { position: absolute; top: -100px; --initial-position: random(element-scoped, -40vw, 100vw); translate: var(--initial-position) 0; }We'd show a demo, but they all start off-screen and don't animate, so you wouldn't see anything. That's our starting position sorted, lets move on to size and shape.
Size and petal styleFor the size, lets use aspect-ratio instead of an explicit width this time so we can keep things simple:.petal { width: random(30px, 50px); aspect-ratio: 1/1; }For the petals themselves I found four different petals by Pram Samnak that I liked and wanted to randomly pick one from.Theoretically you would be able to use random-item() to randomly pick one of the four petals, but that function is not yet implemented in any browser. It would look like this, if it worked:.petal { background-image: random-item( url(petals/1.png), url(petals/2.png), url(petals/3.png), url(petals/4.png) ); }I had to think a while on how to get around this, and I ended up realising that if each petal starts at a random place I could just use nth-child,The repeating pattern of the nth-child() selector wouldn't be noticeable since each petal starts at a random position.All of this still happens off-screen so there's no demo. Let's quickly add the falling animation and see something!Falling animationWhen petals fall down they also get pushed around by the wind, so they don't fall straight down. To achieve this, we can animate translate and move the petals down and to the right.Because each petal catches the wind differently, we want them to fall at different speeds and at different angles. For the speed, we can vary the duration of the animation. For the angle we can set an end value for the translate that takes the --initial-position that we already had, and add a random amount.Just like with the bokeh example, Each petal has a different timing and we set a negative delay so that some petals start in the middle of their animation, which makes it look more natural as you load the page.We only have to set the to keyframe to the end position at the bottom of the screen. When the petal leaves the screen, it jumps back to the top and starts falling again, creating a continuous effect.