Make progress bar with CSS3

Make progress bar with CSS3

Not always easy to make progress bars with HTML and CSS. The horizontal bars are relatively simple to make but the vertical bar and circle it is a different story and it usually ends in a headlock with canvas.

There are other simpler and faster solutions with CSS3. I know that in 60% of cases customers want compatibility with browsers of yesteryear, this is a point that I would not treat this tutorial.

In this tutorial we will use LESS in order to simplify our task. If you do not know LESS I recommend you start by reading this article. We'll see how to create an horizontal,  vertical and finally circular progress bar, using only CSS3. The tutorial does not use any prefixes, you're free to add them according to your needs.

Knowledge to be able to follow this tutorial are:

  • Basic HTML and CSS
  • Some knowledge of the LESS syntax

An horizontal progress bar

The easiest way to proceed would be to put a block in another block and define a length on the inner block to get a progress bar. This method is compatible with all types of browsers but it is not that I will use in this tutorial.

We will use the functions available in CSS3 gradient. We'll start by creating a template HorizontalProgressBar in our style.less file which will take teh following parametters, the percentage, the height of the progress bar, the colors of active and passive parts thereof. The template of this set as follows:

.HorizontalProgressBar(@percent, @height:25px, @color:#61c419, @color2:#FFF)
	when (ispercentage(@percent)) and (ispixel(@height)) and (iscolor(@color)) and (iscolor(@color2)) {
	height : @height;
}
We will now put the colors in the bar in the form of a two-color gradient as follows:
.HorizontalProgressBar(@percent, @height:25px, @color:#61c419, @color2:#FFF)
	when (ispercentage(@percent)) and (ispixel(@height)) and (iscolor(@color)) and (iscolor(@color2)) {
	height : @height;
background-image: linear-gradient(90deg, @color @percent, @color2 @percent, @color2);
}

Now we will call this template in a class to be able to test it in an HTML file.

.horizontal-progress-50{
	.HorizontalProgressBar(50%);
}
<html>
	<head>
		<link rel="stylesheet/less" type="text/css" href="style.less" />
		<script src="less.js" type="text/javascript"></script>
	</head>
	<body>
		<div class="horizontal-progress-50"></div>
	</body>
</html>

Here, we performed and displayed a horizontal progress bar.

Vertical progress bar

For vertical progress bar, the principle is essentially the same except that the 90 degree rotation is removed and we have an additional parameter to specify the width of the bar.

.VerticalProgressBar(@percent, @height:100px, @width:25px, @color:#61c419, @color2:#FFF)
	when (ispercentage(@percent)) and (ispixel(@height)) and (ispixel(@width)) and (iscolor(@color)) and (iscolor(@color2)) {
	height : @height;
	width: @width;
	background-image: linear-gradient(0deg, @color @percent, @color2 @percent, @color2);
}

As before, a class is created with the template VerticalProgressBar and added in our HTML to enjoy the result.

.vertical-progress-50{
	. VerticalProgressBar(50%);
}
<html>
	<head>
		<link rel="stylesheet/less" type="text/css" href="style.less" />
		<script src="less.js" type="text/javascript"></script>
	</head>
	<body>
		<div class="horizontal-progress-50"></div>
                <div class="vertical-progress-50"></div>
	</body>
</html>

Circular progress bar

We are now arrived at the most difficult point of this tutorial, the circular progress bar does not seem simple to implement, but again CSS3 is full of reserves. As we have already seen in previous sections, it is possible to apply a gradient angle.

We have three cases to deal with, less than 50% bars, those strictly equal to 50% and finally those above 50%. For this we will create three templates of the same name but with a different precondition.

To make our round square we apply a different rule named CSS3 border-radius to round the corners.

.CircularProgressBar(@percent, @size:100px, @color:#61c419, @color2:#FFF, @margin:0px) 
		when (ispercentage(@percent)) and (ispixel(@size)) and (iscolor(@color)) and (iscolor(@color2)) and (@percent < 50%) {
	height: @size;
	width: @size;
border-radius: 50%;
}
.CircularProgressBar(@percent, @size:100px, @color:#61c419, @color2:#FFF, @margin:0px) 
		when (ispercentage(@percent)) and (ispixel(@size)) and (iscolor(@color)) and (iscolor(@color2)) and (@percent = 50%) {
	height: @size;
	width: @size;
border-radius: 50%;
}
.CircularProgressBar(@percent, @size:100px, @color:#61c419, @color2:#FFF, @margin:0px) 
		when (ispercentage(@percent)) and (ispixel(@size)) and (iscolor(@color)) and (iscolor(@color2)) and (@percent > 50%) {
	height: @size;
	width: @size;
border-radius: 50%;
}

The case of 50% is easier to manage because only the right part will be colored. It therefore represents the same manner as the horizontal progress bar by inverting the colors.

.CircularProgressBar(@percent, @size:100px, @color:#61c419, @color2:#FFF, @margin:0px) 
		when (ispercentage(@percent)) and (ispixel(@size)) and (iscolor(@color)) and (iscolor(@color2)) and (@percent = 50%) {
	height: @size;
	width: @size;
background-image: linear-gradient(90deg, @color2 50%, @color 50%, @color);
border-radius: 50%;
}

CSS3 allows overlapping layers, that is to say, put several layers of background. So we'll have a layer with an angle corresponding percentage spent more parameters that define one second if 50% have summers past or not.

.CircularProgressBar(@percent, @size:100px, @color:#61c419, @color2:#FFF, @margin:0px) 
		when (ispercentage(@percent)) and (ispixel(@size)) and (iscolor(@color)) and (iscolor(@color2)) and (@percent < 50%) {
	height: @size;
	width: @size;
background-image: linear-gradient(90deg, @color2 50%, transparent 50%, transparent), linear-gradient((((unit(@percent, deg)/100)*360)+90), @color 50%, @color2 50%, @color2); 
border-radius: 50%;
}
.CircularProgressBar(@percent, @size:100px, @color:#61c419, @color2:#FFF, @margin:0px) 
		when (ispercentage(@percent)) and (ispixel(@size)) and (iscolor(@color)) and (iscolor(@color2)) and (@percent > 50%) {
	height: @size;
	width: @size;
background-image: linear-gradient( (((unit(@percent, deg)/100)*360)+90), @color 50%, transparent 50%, transparent), linear-gradient(90deg, @color2 50%, @color 50%, @color); 
border-radius: 50%;
}

Once again we implement in a class and test.

.circular-progress-50{
	.CircularProgressBar(50%);
}
.circular-progress-80{
	.CircularProgressBar(80%);
}
.circular-progress-15{
	.CircularProgressBar(15%);
}
<html>
	<head>
		<link rel="stylesheet/less" type="text/css" href="style.less" />
		<script src="less.js" type="text/javascript"></script>
	</head>
	<body>
		<div class="horizontal-progress-50"></div>
                <div class="vertical-progress-50"></div>
                <div class="circular-progress-15"></div>
                <div class="circular-progress-50"></div>
                <div class="circular-progress-80"></div>
	</body>
</html>

Les sources

I myself have made a more complete implementation of these methods, I created all the possibilities between 0 and 100 that made the file is relatively large. Book you go from 5 to 5 or 10 to 10 to reduce it. My implementation also supports the management of labels and prefixes-o,-ms, mz-and-webkit browsers to not update.