Animated Clouds - Part 1
If you want to know how to animate clouds, similar to the drifting clouds in the title bar, then you are reading the right post!
In Part 1 we will cover how to set up animated clouds using CSS animations and variables.
In Part 2 we will cover how you can use JavaScript to programmatically spawn clouds at random intervals with randomised positions, speeds, sizes and depths.
Part 1: CSS Animations & CSS Variables permalink#
- Setting up clouds in HTML & CSS
- Moving clouds across the screen
- Changing the speed of clouds
- Changing the size of clouds
- Adding a perception of depth to the clouds
- Bringing it all together
- Next steps
All examples from the steps below are available on CodePen.
1. Setting up the cloud in HTML & CSS permalink#
Before you get started you will need to find yourself an image of a cloud with a transparent background.
The following HTML and CSS will position a single, stationary, cloud at the left hand side of the sky.
HTML
<div class="sky">
<div class="cloud" style="top: 50%"></div>
</div>
CSS
.sky {
background: #95d2ec;
overflow: hidden;
position: relative;
width: 100%;
height: 50px;
}
.cloud {
background-image: url(/cloud.png);
background-size: contain;
background-repeat: no-repeat;
background-position: center;
position: absolute;
transform: translateY(-50%);
width: 50px;
height: 50px;
}
2. Moving the clouds permalink#
We need to use CSS animations to move the clouds across the sky.
The following CSS will define the move
animation and add it to the cloud. The animation will move the cloud across the sky, from left to right, over a period of 60 seconds. The cloud will then reappear at the left and repeat the cycle indefinitely.
CSS
.cloud {
...
animation-name: move;
animation-duration: 60s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@keyframes move {
0% {
margin-left: -50px;
}
100% {
margin-left: 100%;
}
}
3. Changing the speed of the clouds permalink#
To adjust the speed of the clouds we can change the animation-duration
property within the cloud
class. This applies the same speed to every cloud which you may not want. Instead we are going to make use of CSS variables so we can change the speed of individual clouds.
The following HTML sets up three clouds of varying speeds using a new --speed
variable.
HTML
<div class="sky" style="height: 150px">
<div class="cloud" style="top: 20%"></div>
<div class="cloud" style="top: 50%; --speed: 0.5"></div>
<div class="cloud" style="top: 80%; --speed: 2"></div>
</div>
The following CSS uses the --speed
variable when calculating the animation-duration
of the cloud and sets --speed
to a default value of 1
.
CSS
.cloud {
...
--speed: 1;
animation-duration: calc(60s / var(--speed));
}
4. Changing the size of the clouds permalink#
It looks a bit odd that all clouds are the same size so let's add another CSS variable --scale
which we will use to change the size of a cloud.
The following HTML sets up three clouds of varying sizes using a new --scale
variable.
HTML
<div class="sky" style="height: 200px">
<div class="cloud" style="top: 15%"></div>
<div class="cloud" style="top: 45%; --scale: 2"></div>
<div class="cloud" style="top: 75%; --scale: 1.5"></div>
</div>
The following CSS uses the --scale
variable when calculating the width
and height
properties of the cloud and sets --scale
to a default value of 1
.
To ensure larger clouds start their animation out of view we also update the first frame of the move
animation by multiplying the margin-left
by the --scale
.
CSS
.cloud {
...
--scale: 1;
width: calc(50px * var(--scale));
height: calc(50px * var(--scale));
}
@keyframes move {
0% {
margin-left: calc(-50px * var(--scale));
}
100% {
margin-left: 100%;
}
}
5. Adding a perception of depth to the clouds permalink#
Next we will add a perception of depth between the clouds with the addition of a third CSS variable --depth
. Similar to the other variables, --depth
will also be used as a scalar. Where 1
has no visual effect on the cloud and the closer the depth gets to zero the further away the cloud disappears into the distance.
When a cloud appears further back it will be smaller, slower and appear darker (really just a lower opacity).
The following HTML sets up three clouds of varying depths using a new --depth
variable.
HTML
<div class="sky" style="height: 150px">
<div class="cloud" style="top: 20%; --depth: 0.7"></div>
<div class="cloud" style="top: 50%; --depth: 0.85"></div>
<div class="cloud" style="top: 80%; --depth: 1"></div>
</div>
The following CSS uses the --depth
variable when calculating the width
, height
, z-index
, animation-duration
and opacity
properties of the cloud and sets --depth
to a default value of 1
.
Again, we also ensure clouds start their animation just out of view by updating the first frame of the move
animation by multiplying the margin-left
by the --scale
and the --depth
.
CSS
.cloud {
...
--depth: 1;
animation-duration: calc(60s / (var(--speed) * var(--depth)));
opacity: var(--depth);
width: calc(50px * var(--scale) * var(--depth));
height: calc(50px * var(--scale) * var(--depth));
z-index: var(--depth);
}
@keyframes move {
0% {
margin-left: calc(-50px * var(--scale) * var(--depth));
}
100% {
margin-left: 100%;
}
}
6. Bringing it all together permalink#
Finally, we can combine the usage of our three CSS variables --speed
, --scale
and --depth
to create a simulation of drifting clouds which hopefully looks awesome!
The following HTML sets up three clouds of varying speeds, sizes and depths using the three CSS variables --speed
, --scale
and --depth
respectively.
HTML
<div class="sky">
<div class="cloud" style="top: 15%; --scale: 1.5; --depth: 0.85"></div>
<div class="cloud" style="top: 45%; --speed: 0.75; --depth: 0.85"></div>
<div class="cloud" style="top: 75%; --scale: 2"></div>
</div>
The following CSS is a complete example of everything covered in this post.
- The
animation-duration
is affected by both the--speed
and the--depth
- The
opacity
is affected by only the--depth
- The
width
andheight
are affected by both the--scale
and the--depth
CSS
.sky {
background: #95d2ec;
overflow: hidden;
position: relative;
width: 100%;
height: 150px;
}
.cloud {
--depth: 1;
--scale: 1;
--speed: 1;
animation-name: move;
animation-duration: calc(60s / (var(--speed) * var(--depth)));
animation-timing-function: linear;
animation-iteration-count: infinite;
background-image: url(/cloud.png);
background-size: contain;
background-repeat: no-repeat;
background-position: center;
position: absolute;
transform: translateY(-50%);
opacity: var(--depth);
width: calc(50px * var(--scale) * var(--depth));
height: calc(50px * var(--scale) * var(--depth));
z-index: var(--depth);
}
@keyframes move {
0% {
margin-left: calc(-50px * var(--scale) * var(--depth));
}
100% {
margin-left: 100%;
}
}
7. Next steps permalink#
Part 2 will show you how you can use JavaScript to programmatically spawn clouds at random intervals with randomised positions, speeds, sizes and depths.
All examples from this article are available on CodePen.
Back to top