Unlimited Wordpress themes, plugins, graphics & courses! Unlimited asset downloads! From $16.50/m
  1. Web Design
  2. CSS

How to Build an Animated CSS Thermometer Chart

Read Time:8 minsLanguages:

So far in our series of CSS chart tutorials I’ve shown you how to build a column chart, a bar chart, and a semi-circle donut chart

In this tutorial I’ll cover the process of creating a pure CSS animated “thermometer” chart; the perfect way to track achievement of a single target.

What We’re Building

Here’s the chart we’ll be creating (hit reload to see it animate):

1. Begin With The Data

For the purposes of this demo, we’ll need some data. Let’s work with some fictional figures that describe the funding of a charitable organization over the years:

Year Funding
2018 €95,000
2016 €72,000
2015 €50,000
2012 €35,000
2010 €15,000

As you might’ve guessed, our challenge is to visualize this data in a thermometer chart. We’ll be taking our visual inspiration from those troublesome do-gooders Extinction Rebellion (if you haven’t heard of them, check out what they’re up to!). 

2. Specify the Page Markup

We’ll specify a wrapper element which contains three lists:

  • The first list sets the y-axis range. If you take a closer look at the table data above, you’ll see that the second column includes values up to 95,000. Keeping this in mind, we’ll define six values from 0 to 100,000 with a step size of 20,000. The values of the y-axis will therefore be 0, 20,000, 40,000, 60,000, 80,000, and 100,000.
  • The second list sets the x-axis data. These are extracted from the first column of our table, from lowest to highest. But their order doesn’t matter because we’ll absolutely position them. Notice in the markup below though, that a list item contains the same year twice. We could’ve omitted setting the year as the item’s text node. But it’s important to store this value in the data-year attribute. As we’ll see later, we’ll pass the value of this attribute to the related ::before pseudo-element. 
  • The third list groups the aforementioned table data, from the highest funding value to the lowest one. Again here the order isn’t important. You can show them from lowest to highest as well. This is completely up to you.

Here’s the required markup:

3. Define Some Basic Styles

Coming up next, we’ll set up a few CSS variables and some common reset styles:

Nothing really spectacular happens here, but perhaps one thing to note is that apart from the well-known “Georgia” system serif font, I’ve also used the premium “Cheddar Gothic” font taken from Envato Elements

Cheddar Gothic Font FamilyCheddar Gothic Font FamilyCheddar Gothic Font Family
Cheddar Gothic Font Family on Envato Elements

Note: For simplicity I won’t walk through all the CSS rules in the tutorial. You can check the rest of them by clicking the CSS tab of the demo project.

4. Style the Chart

The chart wrapper will be a grid container with horizontally centered content. Each column (list) will have its default width, with a 4rem gap between them.

The grid container layoutThe grid container layoutThe grid container layout

Here’s the related CSS:

The y-axis

The first list which contains the y-axis data will also behave as a grid container. There’ll be a 3rem gap between the items:

The layout of the y-axis

Here’s the associated CSS:

The x-axis

The second list which includes the x-axis data will have a fixed width of 50px. Furthermore, we’ll give it some additional styles so it’ll have the appearance of a real thermometer:

The layout of the x-axis

The corresponding styles are as follows:

The list items will be absolutely positioned with an initial height of 0–hence by default, they’ll be invisible. Another thing we do is set their foreground color as transparent. In such a case, their text which contains the year won’t be visible:

For the next step we’ll specify some styles for their ::before pseudo-element. Remember its content will include the value of the associated data-year attribute (see markup above). Plus, it’ll be initially hidden:

The layout of the before pseudo-element

The required styles:

Animate the Items

As soon as the page loads, the height of the list items will be animated and receive a value that’ll be determined by the associated funding value (see table above). For example, a value of 15,000 corresponds to height: 15%. Besides the list items, their ::before pseudo-element will be animated as well, though the animations won’t run simultaneously. The item will become visible first, then its pseudo-element.

Let’s now turn all the requirements above into code.

When the page loads, we’ll first add the loaded class to the body:

At that point the items can be animated sequentially. To achieve this, we’ll take advantage of a technique used in my previous chart demos. We’ll define two CSS variables that determine the transition speed (feel free to change them if needed) and we’ll combine them with the calc() function.

Here are the CSS styles responsible for revealing the x-axis items:

As already mentioned in previous chart demos, Microsoft Edge doesn’t support these math operations, so if you need to support it, you’ll have to pass some static values instead, like this:

Note: I could have defined the transition-delay property outside the loaded class like this:

In either case, the result will be the same; the animation won’t run until the page loads. I only chose to include that property within the loaded class because I wanted to limit the CSS code and group the properties that share the same selector, for example those two:

As already discussed in previous steps, the ::before pseudo-element should also appear on page load:

But with an even bigger delay:

The labels

The third list which includes the table data will be hidden by default.

The layout of the third list

But at the moment the chart animations finish, it will appear:

Notice the value of the transition-delay property which is set to 3.8s. We’ll use this value because the transition-delay property of the last ::before element of the x-axis is set to 3.6s:

The transition-delay property of the last before element of the x-axisThe transition-delay property of the last before element of the x-axisThe transition-delay property of the last before element of the x-axis

Finally, we’ll use the ::before pseudo-element of its list items to create the colorful rectangle which appears in the left corner of each item:

The colorful rectangle

 Here are the styles needed for that:

Our final project looks like this!


That’s it folks! In this tutorial, we built a pure CSS animated thermometer chart. I hope you found this exercise interesting and that it will challenge you to create your own CSS charts.

As always, thanks for reading!

More Tutorials About Charts and Animation

Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.