How to create Bar Charts with CSS flexbox property
Table of contents
Introduction
A chart is a piece of information in the form of a table, graph or diagram. They are used to display series of numeric data in a graphical format to make it easier to understand large quantities of data and the relationship between different series of data.
CSS Flex
CSS flexbox is a layout model that allows you to align and distribute space among items in a container. It is a one-dimensional layout concept that allows for fine-tuning specific sections of a web page either as a row or column. In this article, I will show you a step-by-step guide on how to create a bar chart using CSS Flex. Below is a scenario whose data we will visualise using CSS Flexbox.
Scenario
A small business was surveyed to determine the gender of its customer base over one month. The survey collected data over the following parameters: Gender: (male/female)
Result: The survey found that out of 500 total customers, 300 were female, and 200 were male. The percentage breakdown of customers by gender was 60% female, 40% male.
To solve this,
I created a basic Html document, and add give it a title. In this case I will title it "CSS Flex Charts"
<!DOCTYPE html>
<html>
<head>
<title>CSS Flex Charts</title>
</head>
<body>
</body>
</html>
I also created a CSS file and named it "styles.css". Then I linked it to my HTML document.
<head>
<title>CSS Flex Charts</title>
<link rel ="stylesheet" href="styles.css">
</head>
In my HTML document, I created five div elements, to represent the information provided by the scenario.
<body>
<div class ="horizontal">
<div class="label">Gender</div>
<div class="container">
<div class="female">60%</div>
<div class="male">40%</div>
</div>
</div>
</body>
I added an internal CSS to class male and female to set the flex-basis property to their respective percentage values.
<body>
<div class="horizontal">
<div class="label">Gender</div>
<div class="container">
<div class="female" style="flex-basis: 60%;">60%</div>
<div class="male" style="flex-basis: 40%;">40%</div>
</div>
</div>
</body>
flex-basis
property sets the initial size of the female and male elements to 60% and 40% respectively of the available space. As you notice there is no noticeable effect yet.
I then defined the styling in the CSS file.
I set the horizontal div display to flex and its items alignment to stretch
.horizontal{
display: flex;
align-items: stretch;
}
display: flex
: sets the property of the horizontal element to flex
which enables flexbox layouts for its child elements.
align-items: stretch
: sets the alignment of the horizontal's elements along the cross-axis (perpendicular to the main axis) to stretch
, which will cause them to fill the available space in that direction.
Next, I defined the styling for the div with the class label
.horizontal .label{
flex: 0 0 auto;
font-family: Arial;
font-weight: 900;
}
flex: 0 0 auto
: sets three flex properties for the label element the values are flex-grow
, flex-shrink
and flex-basis
. Here, flex-grow
is set to 0 which means the label will not grow to fill available space. flex-shrink
is also set to 0, which means the label element will not shrink when there is no available space. flex-basis
is set to auto this will set the initial size of the container to be based on it content.
font-family
: is set to Arial and the font-weight
to bold in order to increase the contrast of the label element.
Then, I defined the styling for the container elements.
.horizontal .container{
flex: 1;
display: flex;
justify-content: flex-start;
}
flex: 1
: This sets, the flex properties of the container.flex-grow
is set to 1, which means the container will grow to fill the available space. flex-shrink
and flex-basis
are not set, so they'll use their default values.
display: flex
: sets the property of the container element to flex which enables flexbox layouts for its child elements.
justify-content: flex-start
: this will align the container child elements towards the left side of the container.
Next, I set the styling for the female and male elements. In the female and male div elements, I added a general class of "gender". this will allow for ease of styling and reduced codes. you can also use another method of your choice.
.horizontal .gender{
display: flex;
justify-content: center;
align-items: center;
}
display: flex
: sets the property of the container element to flex which enables flexbox layouts for its child elements.
justify-content: center
: this will align the gender element content towards the center.
align-items
: sets the alignment of the horizontal's elements along the cross-axis (perpendicular to the main axis) to center, which will align the contents of the gender element towards the center.
Finally I added a background color to each of the male and female elements.
.male{background-color: #0000ff;}
.female{background-color: #ffc0cb;}
The chart is ready and it is responsive.
Assuming the survey in the scenario above was carried out for 4 months and the percentage breakdown of customers by gender for the first month was 30% female, 40% male, in the second month, 45% were female and 40% were male, in the third month 15% were females, and 50% were males, while in the fourth month, 15% were females, and 60% were males.
Instead of creating a horizontal bar chart, CSS flex properties allow the creation of a vertical or column bar chart.
First, I created a basic HTML document structure and give it a title.
<!DOCTYPE html>
<html>
<head>
<title>CSS flex Charts</title>
</head>
<body>
<body>
</html>
Next, I created a CSS file and link it to my HTML document below the `title` element inside the `head` tag.
<!DOCTYPE html>
<html>
<head>
<title>CSS flex Charts</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<body>
</html>
I then created a div and give it a class name, inside the div, I nest four other divs and give them the same class name.
<body>
<div class="vertical">
<div class="container"></div>
<div class="container"></div>
<div class="container"></div>
<div class="container"></div>
</div>
</body>
Inside each of the container div, I nested two other div and gave them two classes each.
<body>
<div class="vertical">
<div class="container">
<div class="bar female"></div>
<div class="bar male"></div>
</div>
<div class="container">
<div class="bar female"></div>
<div class="bar male"></div>
</div>
<div class="container">
<div class="bar female"></div>
<div class="bar male"></div>
</div>
<div class="container">
<div class="bar female"></div>
<div class="bar male"></div>
</div>
</div>
</body>
Then I added a CSS style with the flex-basis property and use the values of the results from each month as values.
<body>
<div class="vertical">
<div class="container">
<div class="bar female" style="flex-basis:30%;"></div>
<div class="bar male" style="flex-basis: 40%;"></div>
</div>
<div class="container">
<div class="bar female" style="flex-basis:45%;"></div>
<div class="bar male" style="flex-basis: 40%;"></div>
</div>
<div class="container">
<div class="bar female" style="flex-basis: 15%;"></div>
<div class="bar male" style="flex-basis: 50%;"></div>
</div>
<div class="container">
<div class="bar female" style="flex-basis: 15%;"></div>
<div class="bar male" style="flex-basis: 60%;"></div>
</div>
</div>
</body>
To visualise my data, I added CSS first to our vertical div element, to set the display property as well as the amount of space I want it to occupy. See the result after the code.
.vertical{
display: flex;
height: 450px;
max-width: 300px;
align-items: stretch;
border: 1px solid black;
}
display: flex
: sets the property of the horizontal element to flex which enables flexbox layouts for its child elements.
max-width
: sets the maximum width of the vertical elements to 300 pixels, this implies that the width will not exceed 300 pixels.
align-items: stretch
: sets the alignment of the vertical's elements along the cross-axis (perpendicular to the main axis) to stretch, which will cause them to fill the available space in that direction
border
: sets the border-width
to 1 pixel, border-style
to solid and the border-color
to black. Add styling to the container elements
Then I added styling to my container element. This does not produce any noticeable visual effect or changes yet,
.vertical .container{
flex: 1;
display: flex;
flex-direction: column;
align-items: stretch;
justify-content: flex-end;
}
flex: 1
: This sets, the flex properties of the container. flex-grow
is set to 1, which means the container will grow to fill the available space. flex-shrink
and flex-basis
are not set, so they'll use their default values.
display: flex
: sets the property of the container element to flex which enables flexbox layouts for its child elements. flex-direction: column
: sets the orientation of the child element to column.
justify-content: flex-end
: aligns the child elements towards the base of the flexbox.
Finally, I added a border to the bar element. and a background color to each of the male and female elements and my column chart is ready.
.vertical .bar{border-right: 1px solid white;}
.male{background-color: #0000ff;}
.female{background-color: #ffc0cb;}
border-right
: sets the right side border of each of the bar elements. The width is 1 pixel, the border type to solid and the color to white.
background-color
: sets the background color of male and female elements.
Note that you can have both a horizontal and a column bar chart inside the same web page. This is demonstrated below
HTML
<!DOCTYPE html>
<html>
<head>
<title>CSS Flex Charts</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="horizontal">
<div class="label">Gender</div>
<div class="container">
<div class="gender female" style="flex-basis: 60%">60%</div>
<div class=" gender male" style="flex-basis: 40%;">40%</div>
</div>
</div>
<div class="vertical">
<div class="container">
<div class="bar female" style="flex-basis:30%;"></div>
<div class="bar male" style="flex-basis: 40%;"></div>
</div>
<div class="container">
<div class="bar female" style="flex-basis:45%;"></div>
<div class="bar male" style="flex-basis: 40%;"></div>
</div>
<div class="container">
<div class="bar female" style="flex-basis: 15%;"></div>
<div class="bar male" style="flex-basis: 50%;"></div>
</div>
<div class="container">
<div class="bar female" style="flex-basis: 15%;"></div>
<div class="bar male" style="flex-basis: 60%;"></div>
</div>
</div>
</body>
</html
CSS
.horizontal{
display: flex;
align-items: stretch;
margin-bottom: 20px;
}
.horizontal .label{
flex: 0 0 auto;
font-family: Arial, Helvetica, sans-serif;
font-weight: bold;
}
.horizontal .container{
flex: 1;
display: flex;
justify-content: flex-start;
}
.horizontal .gender{
display: flex;
justify-content: center;
align-items: center;
}
.male{background-color: #0000ff;}
.female{background-color: #ffc0cb;}
.vertical {
display: flex;
height: 450px;
max-width: 300px;
align-items: stretch;
border: 1px solid black;
}
.vertical .container {
flex: 1;
display: flex;
flex-direction: column;
align-items: stretch;
justify-content: flex-end;
}
.vertical .bar {border-right: 1px solid white;}
The result is indicated below
The Chart is responsive. Let me know in the comment section if you find this impactful.
Thanks for reading.
Subscribe to my newsletter
Read articles from Timileyin Olayuwa directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Timileyin Olayuwa
Timileyin Olayuwa
I'm a frontend developer passionate about building beautiful UIs. Learning JS & technical writing. Great code needs great docs. Follow my journey!