How to create Bar Charts with CSS flexbox property

How to create Bar Charts with CSS flexbox property

A Comprehensive Guide to Designing and Developing Both Horizontal and Column/Vertical Bar Charts Using CSS Flexbox

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.