We have coated loads of strategies for creating various kinds of charts utilizing CSS or/and JavaScript. Right now, I’ll present you how you can make a bubble chart with CSS.
What’s a Bubble Chart?
A bubble chart is a chart kind, thought-about to be the cousin of the scatter plot, and its main objective is to visualise relationships between three totally different dimensions/variables: one is represented by the X axis, one by the Y axis, and one by the bubble measurement.
This sort of chart can present helpful info for developments over the 12 months, historic knowledge comparability, gross sales comparability, and many others.
You may construct complicated dynamic bubble charts through the use of totally different JavaScript libraries like Highcharts.js and ApexCharts.js.
1. Start With The Knowledge
For this demo, we’ll borrow some knowledge from a earlier chart tutorial and elaborate on them a bit. So, let’s assume that we wish to visualize in a bubble chart the next knowledge that describes the funding of a charitable group over time:
Yr | Funding | Variety of Staff |
---|---|---|
2018 | €95,000 | 12 |
2016 | €72,000 | 10 |
2015 | €50,000 | 8 |
2012 | €35,000 | 6 |
2010 | €15,000 | 4 |
Every desk row will correspond to some extent (bubble). The primary two columns will describe the bubble place alongside the X and Y axes, whereas the third one will point out its measurement.
2. Specify the Web page Markup
We’ll specify a wrapper aspect that incorporates two lists:
- The primary record units the y-axis vary. Should you take a more in-depth take a look at the desk knowledge above, you’ll see that the second column consists of values as much as 95,000. Retaining this in thoughts, we’ll outline six values from 0 to 100,000 with a step measurement of 20,000. The values of the y-axis will subsequently be 0, 20,000, 40,000, 60,000, 80,000, and 100,000.
- The second record units the x-axis knowledge. These figures are extracted from the primary column of our desk, from lowest to highest. Discover within the markup beneath although, {that a} record merchandise incorporates the identical 12 months twice. We might have omitted to set the 12 months because the merchandise’s textual content node. But it surely’s vital to retailer this worth within the
data-year
attribute. As we’ll see later, we’ll go the worth of this attribute to the associated::earlier than
pseudo-element. Take into account additionally thedata-details
attribute. Its worth will function the tooltip of the corresponding bubble. Inside this worth exist a number of appearances of the

that’s the HTML illustration in hex format of a line feed character. We’ll put it after each little bit of textual content the place we wish to power a brand new line. Extra on that later.
Right here’s the required markup:
1 |
<div class="chart-wrapper"> |
2 |
<ul class="chart-y"> |
3 |
<li>€100,000</li> |
4 |
... |
5 |
</ul>
|
6 |
<ul class="chart-x"> |
7 |
<li data-year="2010"> |
8 |
<span data-details="UK:72%
USA:24%
Sweden:3%">2010</span> |
9 |
</li>
|
10 |
... |
11 |
</ul>
|
12 |
</div>
|
3. Fashion the Chart
For simplicity, I’ll skip some reset/fundamental kinds. You may examine the remainder of them by clicking the CSS tab of the demo venture.
I haven’t optimised the kinds, making it simpler so that you can see what’s occurring
Lastly, I’ve embedded the premium Cheddar Gothic font taken from Envato Components for the heading.
The chart wrapper might be a flex container with a most width of 700px and horizontally centered content material. The y-axis might be thrice greater than the x-axis.
The associated CSS:
1 |
.chart-wrapper { |
2 |
show: flex; |
3 |
max-width: 700px; |
4 |
padding-right: 15px; |
5 |
margin: 30px auto 0; |
6 |
}
|
7 |
|
8 |
.chart-wrapper .chart-y { |
9 |
flex: 1; |
10 |
}
|
11 |
|
12 |
.chart-wrapper .chart-x { |
13 |
flex: 3; |
14 |
}
|
The x-axis
The second record which incorporates the x-axis knowledge may even be a flex container. Its gadgets could have a width of 12%, be evenly distributed throughout the principle axis, and sit on the backside of the container. We’ll make the record seem like a neumorphic aspect with the assistance of this device.
Plus, every record merchandise could have a top that may rely on the related funding worth (see desk above). For instance, a worth of 15,000 corresponds to top: 15%
.
Listed below are the associated kinds:
1 |
.chart-wrapper .chart-x { |
2 |
show: flex; |
3 |
justify-content: space-around; |
4 |
align-items: flex-end; |
5 |
border-radius: 48px; |
6 |
background: #f0f0f0; |
7 |
box-shadow: -8px 8px 20px #b4b4b4, 8px -8px 20px #ffffff; |
8 |
}
|
9 |
|
10 |
.chart-wrapper .chart-x li { |
11 |
place: relative; |
12 |
width: 12%; |
13 |
}
|
14 |
|
15 |
.chart-wrapper .chart-x li:nth-child(1) { |
16 |
top: 15%; /*represents €15,000*/ |
17 |
}
|
18 |
|
19 |
.chart-wrapper .chart-x li:nth-child(2) { |
20 |
top: 35%; /*represents €35,000*/ |
21 |
}
|
22 |
|
23 |
.chart-wrapper .chart-x li:nth-child(3) { |
24 |
top: 50%; /*represents €50,000*/ |
25 |
}
|
26 |
|
27 |
.chart-wrapper .chart-x li:nth-child(4) { |
28 |
top: 72%; /*represents €72,000*/ |
29 |
}
|
30 |
|
31 |
.chart-wrapper .chart-x li:nth-child(5) { |
32 |
top: 95%; /*represents €95,000*/ |
33 |
}
|
Subsequent, we’ll use the ::earlier than
pseudo-element of every merchandise to output the labels of the x-axis.
The related CSS:
1 |
.chart-wrapper .chart-x li::earlier than { |
2 |
content material: attr(data-year); |
3 |
place: absolute; |
4 |
left: 50%; |
5 |
backside: 0; |
6 |
width: 100%; |
7 |
text-align: middle; |
8 |
remodel: translate(-50%, 40px) rotate(45deg); |
9 |
}
|
Bubbles
Every span
aspect will correspond to a bubble (level). Every bubble could have a distinct shade and measurement.
The bubble measurement will rely on the worth of the associated third desk column (see desk). Assuming that the width and top for the smallest (first) bubble might be 15px, we’ll calculate accordingly the dimensions of the remaining ones.
One other factor we’ll do is to forestall exhibiting the bubbles by default and as an alternative present them with a fade and scale animation. In your personal pages the place the DOM will most likely include extra parts, for extra correct outcomes you’ll be able to wait till the web page hundreds earlier than exhibiting the bubbles as we did within the thermometer chart.
Listed below are the related kinds:
1 |
/*CUSTOM VARIABLES HERE*/
|
2 |
|
3 |
.chart-wrapper .chart-x li:nth-child(1) span { |
4 |
width: 15px; /*represents 4 workers*/ |
5 |
top: 15px; /*represents 4 workers*/ |
6 |
background-color: var(--bubble-color1); |
7 |
}
|
8 |
|
9 |
.chart-wrapper .chart-x li:nth-child(2) span { |
10 |
width: 22.5px; /*represents 6 workers*/ |
11 |
top: 22.5px; /*represents 6 workers*/ |
12 |
background-color: var(--bubble-color2); |
13 |
}
|
14 |
|
15 |
.chart-wrapper .chart-x li:nth-child(3) span { |
16 |
width: 30px; /*represents 8 workers*/ |
17 |
top: 30px; /*represents 8 workers*/ |
18 |
background-color: var(--bubble-color3); |
19 |
}
|
20 |
|
21 |
.chart-wrapper .chart-x li:nth-child(4) span { |
22 |
width: 37.5px; /*represents 10 workers*/ |
23 |
top: 37.5px; /*represents 10 workers*/ |
24 |
background-color: var(--bubble-color4); |
25 |
}
|
26 |
|
27 |
.chart-wrapper .chart-x li:nth-child(5) span { |
28 |
width: 45px; /*represents 12 workers*/ |
29 |
top: 45px; /*represents 12 workers*/ |
30 |
background-color: var(--bubble-color5); |
31 |
}
|
32 |
|
33 |
.chart-wrapper .chart-x span { |
34 |
content material: ""; |
35 |
place: absolute; |
36 |
prime: 0; |
37 |
left: 50%; |
38 |
border-radius: 50%; |
39 |
font-size: 0; |
40 |
cursor: pointer; |
41 |
opacity: 0; |
42 |
remodel: scale(0.001); |
43 |
animation: fade-in 0.8s linear forwards; |
44 |
}
|
45 |
|
46 |
@keyframes fade-in { |
47 |
100% { |
48 |
opacity: 1; |
49 |
remodel: scale(1) translateX(-50%); |
50 |
}
|
51 |
}
|
Tooltips
As we’ve mentioned, every bubble could have a tooltip to indicate extra info. This might be seen when the viewport width is bigger than 700px and once we hover over a bubble.
To create it, we’ll use the ::earlier than
and ::after
pseudo-elements of every span (bubble). The ::after
pseudo-element will function the precise tooltip whereas the ::earlier than
one could have a extra ornamental place and function the tooltip’s triangle.
As we’ve talked about above, the tooltip information we’ll come from the data-details
attribute. Right here we’ve used the 

hex illustration to separate the attribute worth into multi-lines. However this isn’t sufficient; we even have to make use of the white-space
property. Right here’s an in depth Stack Overflow thread about it.
The associated kinds:
1 |
.chart-wrapper .chart-x span::earlier than { |
2 |
content material: ""; |
3 |
place: absolute; |
4 |
left: 50%; |
5 |
backside: calc(100% + 3px); |
6 |
remodel: translateX(-50%); |
7 |
width: 0; |
8 |
top: 0; |
9 |
border-style: stable; |
10 |
border-width: 6px 6px 0 6px; |
11 |
border-color: rgba(0, 0, 0, 0.7) clear clear clear; |
12 |
opacity: 0; |
13 |
transition: opacity 0.15s linear; |
14 |
pointer-events: none; |
15 |
}
|
16 |
|
17 |
.chart-wrapper .chart-x span::after { |
18 |
content material: attr(data-details); |
19 |
place: absolute; |
20 |
left: 50%; |
21 |
backside: calc(100% + 9px); |
22 |
min-width: 90px; |
23 |
line-height: 1.35; |
24 |
remodel: translateX(-50%); |
25 |
shade: var(--white); |
26 |
background: rgba(0, 0, 0, 0.7); |
27 |
font-size: 1rem; |
28 |
white-space: pre; |
29 |
border-radius: 3px; |
30 |
padding: 6px; |
31 |
opacity: 0; |
32 |
z-index: 1; |
33 |
transition: opacity 0.15s linear; |
34 |
pointer-events: none; |
35 |
}
|
36 |
|
37 |
.chart-wrapper .chart-x span:hover::earlier than, |
38 |
.chart-wrapper .chart-x span:hover::after { |
39 |
opacity: 1; |
40 |
}
|
41 |
|
42 |
@media display screen and (max-width: 700px) { |
43 |
.chart-wrapper .chart-x span::earlier than, |
44 |
.chart-wrapper .chart-x span::after { |
45 |
show: none; |
46 |
}
|
47 |
}
|
Conclusion
Finished, of us! Right now, we practiced our CSS information by constructing a totally purposeful bubble chart. Whereas it isn’t the preferred methodology to visualise knowledge, hopefully, it’ll have a spot in one among your future knowledge visualization initiatives.
Let’s remind ourselves of what we constructed:
As all the time, thanks for studying!