Dark & Stormy Night with CSS Animations

Photo by Johannes Plenio on Unsplash

This beginner-friendly tutorial will introduce you to HTML and CSS as you create a simple stormy night scene with CSS animations. You will also learn about CSS positioning, transparency, and opacity.

“It was a dark and stormy night; the rain fell in torrents — except at occasional intervals, when it was checked by a violent gust of wind which swept up the streets.”

Sounds exciting! Although this line from Bulwer-Lytton’s 1830 novel is traditionally mocked as an example of melodrama, it is the perfect setting for us to paint with HTML and CSS.

HTML and CSS are the building blocks of the web. While HTML allows us to put content on our webpage — such as headers, paragraphs, and images — CSS allows us to make that webpage a work of art. With CSS, we can add colors, fonts, and even animations.

If at any point you get lost during this tutorial, check your code against the solution code!

Getting started with HTML

Go to https://glitch.com/~dark-stormy-starter and click “Remix your own.” Keep following along with tutorial as you work on your Glitch project in the next tab!

Click on index.html and check out the HTML code. HTML is made up of tags, which are surrounded by angle brackets: < >. Can you identify the two tags within the body tags of index.html?

If you identified h1 and p as the tags, you’re correct!

To see what these tags do, click the “Show Live” button in the top left-hand area of your screen on Glitch. You can also keep this tab open to see how your code renders on a webpage. Right now, you should see something like this:

As you can see, the h1 tag creates big header text, and the p tag creates a simple paragraph.

But why is the h1 fuschia? The answer lies in… the CSS!

Getting started with CSS

Now on Glitch, if you go to the styles.css file, you should see:

h1 {
color: fuschia;

The three lines on the page comprise a CSS rule-set, which is how we modify the style of HTML elements.

To write a rule-set, you simply:

  • Say which HTML tag you want to modify, e.g. h1 (called the selector)
  • Say what you want to modify about it, e.g. the color of the text (called the property)
  • Say how you want to modify the previous property, e.g. making the color red (called the value)

Incorporating the pesky syntax of the curly braces and semicolons, the basic outline of a CSS rule-set looks like this:

selector {
property: value;

You can have multiple property-value pairs inside your curly braces that modify fonts, position, etc.

Let’s try writing our own rule-set!

For the paragraph, I’d prefer a different font, so I’m going to make a rule-set using the p selector that makes the font-family (or, as we would say colloquially, the font) arial.

Try writing the selector yourself before looking at mine!

Here’s what I added:

p {
font-family: arial;

If Arial doesn’t do it for you, you can check out some more font options here.

OK, now that we’ve been introduced to the very basics of HTML and CSS, let’s make this scene look a bit more like a dark and stormy night.

Adding a background

The easiest way to make our webpage look more dark and stormy will be to add a dark and stormy background image. I’ve added one to the starter project assets, though you’re free to search for your own on Google as well! Click on the assets button in your file list in the left-hand menu:

Click on “assets” in the left-hand file menu.

You should see the four pictures we’ll be using, which includes the purple stormy image in the bottom row. Click on it and copy the URL:

Click on the “Copy Url” button.

Now hop back to your styles.css file. We’re going to make this image the background for the entire body of our webpage, which means that we need to use the body tag as a selector.

Add this rule-set to your CSS file, but paste in your image URL where mine is:

body {
background: url(https://cdn.glitch.com/4f83b17b-3d9a-4782-bfb9-3298fce7ff84%2Fstormynight.jpg?1516228334292);
background-size: cover;

Check out how your page looks now!

The fuschia text looks awesome, but I can’t really read the black text in the p tag. Can you figure out how to fix this?

(Solution: you’ll want to add the property-value pair color: white; to your p rule-set. Of course, you can have the color be fuschia or some other bright color, too!)

Also, I think I want to make ALL the text on my webpage Arial, and also to have it centered on the page. I’m going to add two property-value pairs into my body rule-set:

body {
background: url(https://cdn.glitch.com/4f83b17b-3d9a-4782-bfb9-3298fce7ff84%2Fstormynight.jpg?1516228334292);
background-size: cover;
font-family: arial;
text-align: center;

Since the body rule-set covers everything on the page, I can delete font-family: arial; from my p rule-set. Go ahead and do that.

So far, I think our page looks awesome!

Now let’s add some animations!

Adding an animated storm cloud

I think a storm cloud would really enhance the “dark and stormy” vibe we’re trying give off. I’ve added a storm cloud image to your assets for you to use. Copy its URL:

Now we’re going to put the image on your webpage using an img tag. But first, I’m going to put the img tag inside a div tag so I have a little bit more control over it.

I’m also going to give a specific name to the div and the img so that I can refer to it in my CSS. This specific name is referred to as a CSS class.

Paste this code into your HTML, below the p tags, except substitute your own storm cloud image URL for mine:

<div class="storm">
<img src="https://cdn.glitch.com/4f83b17b-3d9a-4782-bfb9-3298fce7ff84%2Fstormcloud.png?1516228447161" class="cloud">

You can see by the class attributes that I’m calling the div by the name storm and I’m calling the img by the name cloud. Again, these names (or classes) will help us target these elements in the CSS.

The img tag puts the image on the HTML page, and the div is nothing to stress about either. It’s just a new division on the page that allows us to organize our code better.

Check out how your app looks. Woah! The storm cloud is huge!

Let’s use the cloud image’s specific name, cloud, to target it with CSS and modify its size. Add these lines to your CSS:

img.cloud {
width: 200px;

Looks a bit better:

But do we really want our cloud smack in the middle of the scene? Kind of unrealistic, right?

In the CSS, I’m going to target the cloud’s div by its name, storm, with the selector div.storm. Then I’m going to make the content inside the div align to the left. But since I don’t want the cloud shoved up against the left-hand side of the screen, I’m also going to add a 100-pixel margin on the left. Add this code to your CSS:

div.storm {
text-align: left;
margin-left: 100px;

Looks a bit more natural:

Now let’s animate the cloud! I think it would be great if the cloud pulsed ominously, threatening a downpour of rain.

First, we have to write the code for our animation by defining its keyframes. I’m going to name this animation pulse and make the animation loop seamlessly by changing its width from 200px to 250px and back to 200px again. Add this code to your CSS:

@keyframes pulse {
0% { width: 200px; }
50% { width: 250px; }
100% { width: 200px; }

OK, now we can use the animation called pulse to modify our rule-set for img.cloud. Return to that rule-set and add in these property-value pairs:

animation-name: pulse;
animation-duration: 4s;
animation-iteration-count: infinite;

These pairs will make the animation called pulse repeat infinitely for four seconds at a time. Go back to your webpage and check it out! Is your cloud pulsing ominously?

Congratulations on making your first CSS animation!

Adding animated rain

Okay, so according to the quote that inspired this dark and stormy scene, “the rain fell in torrents.” Let’s add some rain!

I’ve added a picture of some raindrops that can be falling from our storm cloud in the assets folder. Copy the URL of this picture:

We’re going to add the raindrops image right under the storm cloud image. Inside the HTML div with the class of storm, and right underneath the img with the class of cloud, add in this code:

<br />
<img src="https://cdn.glitch.com/4f83b17b-3d9a-4782-bfb9-3298fce7ff84%2Fraindrops.png?1516215095327" class="rain">

Don’t forget to replace my URL with yours.

The br tag creates a line break so that we can put the raindrops right under the cloud. You’ll also notice that I’m calling the rain image rain by assigning it the rain class. We’ll use this class, or name, to target the raindrops specifically in our CSS.

Your raindrops should appear right underneath your ominously pulsing cloud. And they’re huge!

Let’s make the raindrops a little bit smaller and center them in the middle of the storm cloud. Add this code to your CSS which targets the raindrops image:

img.rain {
width: 100px;
margin-left: 50px;

That’s better:

Let’s animate the raindrops as well! I want them to simulate falling from the cloud, so I’m going to have them move up and down.

The raindrops are inside a div, so I’m going to be moving them up and down by changing the number of pixels they are from their topmost position in the div. The drops will start out 0px from the top, move to 100px from the top, and return to 0px.

Add this keyframes animation called fall to your CSS:

@keyframes fall {
0% { top: 0px; }
50% { top: 100px; }
100% { top: 0px; }

This animation called fall will make the raindrops go up and down, as though falling from the storm cloud. Now we need to assign the animation to our rain image.

But first, since I’m telling the rain image to move x number of pixels from the top, I need to say from the top of where. Is it from the top of the browser window? No, it’s from the top of its default position in the div.

Because the rain image’s position is relative to the div, I need to specify this in its CSS. Add this property-value pair to the rule-set for img.rain:

position: relative;

Now we can add in the animation. Last time, we added the animation in three separate lines, but this time we’re going to do it with a short-cut. Add this property-value pair to the rule-set for img.rain:

animation: fall 2s infinite;

This will animate the rain image using the fall keyframes infinitely for 2 seconds at a time.

Now your img.rain rule-set should look like this:

img.rain {
width: 100px;
margin-left: 50px;
position: relative;
animation: fall 2s infinite;

Check out your webpage in the next tab. The rain should be going up and down!

It’s raining!

Adding a flash of lightning

OK, we have a pretty good stormy scene going. What’s missing? A flash of lightning!

When lightning flashes, it lights up the entire sky. So when I make a bolt of lightning appear with CSS, I’m going to make sure the flash takes up the whole screen.

First, we want to eliminate any margin space from the body element. Add this property-value pair to the body rule-set:

margin: 0;

Now I want to define a div takes up the entire screen. First I’ll put the div in my HTML and then customize it with CSS. Add this code between the body tags of your HTML, at the bottom:

<div class="lightning">

You can see that I gave the div a class, or a custom name, of lightning. I’ll use this class to target the div in the CSS.

In the CSS, we need to make the div take up the whole screen. To do this, I’ll set its height and width to 100%, declare its position absolute (so that it overlays the rest of your HTML content), and make it 0px away from the top of the page.

These specifications translate into this rule-set targeting the div called lightning, which you should add to your CSS:

div.lightning {
position: absolute;
top: 0;
width: 100%;
height: 100%;

But we can’t see this div at all yet. Let’s add the background, the burst of light that will come when we animate this div into a flash of lightning. Add this property-value pair to your div.lightning rule-set:

background: rgba(255,255,255,.5);

Check out how that looks on your webpage. You should see a transparent layer of whiteness over the whole page:

What we’ve done is use the rgba method of adding color to our page. Computers create colors by adding amounts of red, green, and blue (rgb) light together in different increments from 0–255. Here, we’ve maxed out the red, green, and blue at 255 each to create white (0 of everything would create black).

We’ve also added an alpha value (that’s what the a stands for in rgba) to control how transparent the color is. 0 means totally transparent; 1 means totally opaque. We’ve gone with .5 to make it half-transparent.

OK, now we want to add an actual lightning bolt to our div. In the assets file, I’ve added a lightning bolt picture for you. Copy its URL:

And then return to your HTML. Using an img tag and giving the image a class name of lightning-bolt, put the image inside your lightning div so that it looks like this:

<div class="lightning">
<img src="https://cdn.glitch.com/4f83b17b-3d9a-4782-bfb9-3298fce7ff84%2Flightning.gif?1516229402265" class="lightning-bolt">

Don’t forget to change my image URL to yours. Your lightning bolt should appear on the page:

Now let’s position it inside the div. We want to make its position relative to the lightning div so that we can make it about 100px from the top. Add this code to your CSS:

img.lightning-bolt {
position: relative;
top: 100px;

Now our lightning bolt doesn’t cover up the important text!

But we don’t want it to be permanently flashing on the page. We can just have it flash once to impress the user soon after the page loads. To do that, we want to make the lightning div invisible at first.

We can make whole HTML elements invisible by changing their opacity to 0. Add this property-value pair to your div.lightning rule-set:

opacity: 0;

Now, in our animation, we can make the div change from no opacity to full opacity. Here are the keyframes that will accomplish this:

@keyframes bolt {
from { opacity: 0; }
to { opacity: 1; }

Add those keyframes to your CSS. Now go back up to the div.lightning rule-set and implement the animation. This code will assign it the bolt animation that changes the div's opacity:

animation: bolt .5s;
animation-delay: 2s;
animation-iteration-count: 1;

The code above will also make the animation happen 2 seconds after the user’s page loads. Finally, it will ensure that the animation only happens once.

Refresh your webpage, wait 2 seconds, and watch for the lightning flash!

Congratulations! You’ve made a fully functional webpage with a variety of CSS animations!


  1. Change the background image.
  2. Play with the preexisting animations: make them faster, slower, or more pronounced, and alter different CSS properties.
  3. Animate other aspects of the page, like the text!
  4. Add more storm-related animations (ideas: people walking around with umbrellas, sheets of rain, etc).
  5. Use your knowledge of CSS positioning and animation to start from scratch and create your own work of art.