CSS is Awesome Happy-CSS

Dealing with the daily frontend trouble with Martin Muzatko

Interaction Design with Riot - Making of Rain Animation

10. Lesson of RiotJS series

We are going to see how together with Riot, we can do awesome animations without bending our minds around the DOM.

Lately, I've created a little animation I featured in Stay determined Human. Surprisingly, it took me just a few minutes to figure out the animation itself.

The original Artwork by Makameowart, inspired me to create that little animation.

#What do we need?

It is as simple as creating a few divs. We just iterate over an array of 16 items so we can attach values to the elements later.

this.droplets = 'x'.repeat(16).split('')

Riot doesn't loop through undefined arrays, as it looks like. So new Array(16) won't work.

#Designing the Droplet

The droplets are just simple div elements with a subtle styling.

.rain .droplet {
    background: linear-gradient(to bottom, transparent, #2e20aa);
    width: 1%;
    height: 5%;
    border-radius: 100%;
    position: absolute;
    animation: rain 1.5s linear;
    animation-iteration-count: infinite;
    z-index: 1;

The animation doesn't contain anything than a simple top: 100%; We are going to randomize the base offset and animation speed, so we can have that simplicity in our animation.

@keyframes rain {
    100% {
        top: 100%;

To spread them apart from left to right, we add an inline style.

<div each={droplet in droplets} style="left: {Math.random()*100}%" class="droplet"></div>

This doesn't look that great. We need to randomize the offset of the drops.

#Randomizing to make it feel more natural

As you can see, the drops all land at the bottom at the same time. We do that by adding another inline style to set their top value:

<div each={droplet in droplets} 
    style="top: -{Math.random()*20}%; left: {Math.random()*100}%"

A bit better, but they just repeat all over at the same time. We can prevent that by adding yet another attribute to control the animation-speed.

<div each={droplet in droplets} 
    style="animation-duration: {(Math.random()*2)+0.5}s; top: -{Math.random()*20}%; left: {Math.random()*100}%"

We have to add an extra 0.5 seeconds, so we don't have too fast rain droplets. Due to the random animation-speed, drops are now having random starting and endpoints.

#Why not canvas?

The ultimate pro of this approach is that you can easily create simple particle effects with just a bunch of HTML and CSS. There isn't even that much javascript involved, just for making it more random. Depending on the amount of items, this can quickly become performance intense, but I think for games or websites that need ambience effects, this could be a great solution.


This post is just a quick followup of my recent article Stay determined Human. More lessons to continue our previous problems and solutions will follow soon.