How to create a kick-ass CSS3 progress bar

As I've shown you in some of my recent posts, the new features introduced in CSS3 allows developers to create stunning visual effects. Today, let's create a fancy progress bar using CSS3 and jQuery, but no Flash or even images.

Please note: The original CSS3 progress bar shown in this tutorial has been created by Ivan Vanderbyl, which hereby gave me the right to reproduce and document his work.
The following tutorial and the demo works best on Chrome and Safari, correctly on Firefox and very badly in Internet Explorer (eh…I’m sure you hadn’t guessed that).

The Demo

Click on the image to view a live demo. You can also get the source on Github.

Getting ready

Let’s start by organizing our work. To achieve the effect of this tutorial, we’ll need to create 3 files:

  • progress.html, which will contain our markup.
  • ui.css which will contain our CSS styles.
  • progress.js which will contain some additional jQuery animations.

Create a directory on your webserver (or hard drive) and create the files.

The HTML markup

Here we go. Open your progress.html file and paste the following markup in it:

<!DOCTYPE html>
	<meta charset="utf-8">
	<title>Pure CSS Progress Bar</title>

	<link rel="stylesheet" href="stylesheets/ui.css">
	<link rel="stylesheet" href="stylesheets/ui.progress-bar.css">
	<div id="container">
		<div id="progress_bar" class="ui-progress-bar ui-container">
        	<div class="ui-progress" style="width: 79%;">
				<span class="ui-label" style="display:none;">Processing <b class="value">79%</b></span>
      		</div><!-- .ui-progress -->
    	</div><!-- #progress_bar -->  

		<div class="content" id="main_content" style="display: none;">
	    	<p>Hello, World!</p>
	  	</div><!-- #main_content -->
	</div><!-- #container -->

Let me explain the code a bit: On line 1, I’ve declared a HTML5 doctype. Then, lines 12 to 16 contains the markup for the progress bar itself. If you save the file and view it in your browser right now, you’ll see that nothing appears. Don’t worry, we’re going to apply so CSS3 magic in a minute.

Diving into CSS3

Open your ui.css file and paste the following code in it. There’s nothing fancy there, just some basic styles (that I’ve simplified from the original source) for the layout.

body {
  padding: 30px;
  font-size: 62.5%;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  position: relative;
  margin: 0;

#container {
  margin: 0 auto;
  width: 460px;
  padding: 2em;
  background: #DCDDDF;


.ui-progress-bar {
  margin-top: 3em;
  margin-bottom: 3em;

.ui-progress span.ui-label {
  font-size: 1.2em;
  position: absolute;
  right: 0;
  line-height: 33px;
  padding-right: 12px;
  color: rgba(0,0,0,0.6);
  text-shadow: rgba(255,255,255, 0.45) 0 1px 0px;
  white-space: nowrap;

Once you are done, we can finally get into more serious things. The code below will make your progress bar come to life. I’ll explain it in details in a minute. For now, copy it and paste it in your ui.css file.

@-webkit-keyframes animate-stripes {
  from {
    background-position: 0 0;

  to {
   background-position: 44px 0;

.ui-progress-bar {
  position: relative;
  height: 35px;
  padding-right: 2px;
  background-color: #abb2bc;
  border-radius: 35px;
  -moz-border-radius: 35px;
  -webkit-border-radius: 35px;
  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #b6bcc6), color-stop(1, #9da5b0));
  background: -moz-linear-gradient(#9da5b0 0%, #b6bcc6 100%);
  -webkit-box-shadow: inset 0px 1px 2px 0px rgba(0, 0, 0, 0.5), 0px 1px 0px 0px #FFF;
  -moz-box-shadow: inset 0px 1px 2px 0px rgba(0, 0, 0, 0.5), 0px 1px 0px 0px #FFF;
  box-shadow: inset 0px 1px 2px 0px rgba(0, 0, 0, 0.5), 0px 1px 0px 0px #FFF;

.ui-progress {
  position: relative;
  display: block;
  overflow: hidden;
  height: 33px;
  -moz-border-radius: 35px;
  -webkit-border-radius: 35px;
  border-radius: 35px;
  -webkit-background-size: 44px 44px;
  background-color: #74d04c;
  background: -webkit-gradient(linear, 0 0, 44 44,
    color-stop(0.00, rgba(255,255,255,0.17)),
    color-stop(0.25, rgba(255,255,255,0.17)),
    color-stop(0.26, rgba(255,255,255,0)),
    color-stop(0.50, rgba(255,255,255,0)),
    color-stop(0.51, rgba(255,255,255,0.17)),
    color-stop(0.75, rgba(255,255,255,0.17)),
    color-stop(0.76, rgba(255,255,255,0)),
    color-stop(1.00, rgba(255,255,255,0))
  ), -webkit-gradient(linear, left bottom, left top, color-stop(0, #74d04c), color-stop(1, #9bdd62));
  background: -moz-repeating-linear-gradient(top left -30deg,
    rgba(255,255,255,0.17) 15px,
    rgba(255,255,255,0) 15px,
    rgba(255,255,255,0) 30px
  ), -moz-linear-gradient(#9bdd62 0%, #74d04c 100%);
  -webkit-box-shadow: inset 0px 1px 0px 0px #dbf383, inset 0px -1px 1px #58c43a;
  -moz-box-shadow: inset 0px 1px 0px 0px #dbf383, inset 0px -1px 1px #58c43a;
  box-shadow: inset 0px 1px 0px 0px #dbf383, inset 0px -1px 1px #58c43a;
  border: 1px solid #4c8932;
  -webkit-animation: animate-stripes 2s linear infinite;

Save your ui.css file and view progress.html in your web browser, and you’ll see your gorgeous progress bar, done without using any image.
So, what’s inside? Let me explain the code a bit.

First, we have two CSS classes: .ui-progress-bar and .ui-progress. The first is the container, and the second is the green progress bar.

  • Lines 1 to 9: These lines define a webkit-specific animation, which allows us to move an element from a pint to another.
    For more details about webkit animations, see
  • Line 16: The border-radius CSS3 property allows you to define a radius and get rounded corners.
  • Line 17: Mozilla specific property for border-radius.
  • Line 18: Webkit specific property for border-radius.
  • Line 19: The -webkit-gradient property allows you to add a gradient to an element. It works only on Webkit, other browsers will ignore this property.
  • Line 20: Mozilla specific property, similar to -webkit-gradient with a different syntax.
  • Lines 21 to 23: box-shadow (and its browser specific alternatives) allows you to add a shadow to an element.
  • Line 34: Webkit specific property, based on the standard background-size property, which allows you to specify the size of a background image.
  • Line 56: Triggers webkit animation defined on line 1.

Final touch: Using jQuery to animate the progress bar

A pure CSS3 progress bar is a very cool thing, but progress bars are here to show progress, so we have to animate it. We’re going to use jQuery to do so.

Open your progress.html file and paste the two line below just above the closing</body> tag.

<script src="" type="text/javascript" charset="utf-8"></script>
<script src="progress.js" type="text/javascript" charset="utf-8"></script>

This code will load jQuery from Google (Which I recommend to do instead of loading your own copy) as well as your progress.js file, which will contain the required code to animate the progress bar.

Now, paste the code below in your progress.js file:

(function( $ ){
  $.fn.animateProgress = function(progress, callback) {
    return this.each(function() {
        width: progress+'%'
      }, {
        duration: 2000, 

        easing: 'swing',

        step: function( progress ){
          var labelEl = $('.ui-label', this),
              valueEl = $('.value', labelEl);

          if (Math.ceil(progress) < 20 && $('.ui-label', this).is(":visible")) {
            if (":hidden")) {

          if (Math.ceil(progress) == 100) {
            setTimeout(function() {
            }, 1000);
            valueEl.text(Math.ceil(progress) + '%');
        complete: function(scope, i, elem) {
          if (callback) {
  , i, elem );
})( jQuery );

$(function() {
  $('#progress_bar .ui-progress .ui-label').hide();
  $('#progress_bar .ui-progress').css('width', '7%');

  $('#progress_bar .ui-progress').animateProgress(43, function() {
    $(this).animateProgress(79, function() {
      setTimeout(function() {
        $('#progress_bar .ui-progress').animateProgress(100, function() {
      }, 2000);


Save the file, and view progress.html in your web brower: Wow, the progress bar is now animated. How cool is that?

This Javascript code makes the progress bar go from 0 to 100, and then, it displays a message, which is simply “Hello World” in our tutorial.

I hope you enjoyed reading this tutorial as much as I enjoyed writing it. Have fun with CSS3!

  • Your demo seems to have some issues around the rounded edges in Chrome 6.0.472.63 It looks fine in Firefox though.

    • I just saw the footnote in the demo where the author describes the issue in Chrome and calls it a non-issue. He then goes on to say “Because I use a Mac this is not regarded as an issue.” Which I thought particularly funny as he seems to believe that the web is only viewed through his mac.

      • Its a know chrome issue ( and since it’s a tech demo and only used on internal software he can assume the ‘the web is only viewed through his mac’.

        Go fix chrome or buy a mac 😀

        • Touché

          But it seems that fixing Chrome will likely be more economic.

      • I love when developers feel that if it works for them that they should not be required to make it work for anyone else. If only I could do that at my job..”Hey Boss, it looks fine on my OS & browser combo that only 5-10% of our visitors use, however it does not really work for 90% of our visitors.”

        For demo purposes though, very cool and very clean looking. Now if only I could find a reason for needing it lol.

  • Jürgen Dressel

    Thank you for this articel.

  • Pingback: Around the Web: Node.JS Goodness, Amit on Humble Pied, & Riak 0.13 | Think Vitamin()

  • Wow!
    Very smoooothly move. nice : )

  • Red

    Too bad Chrome has that inset box-shadow problem, otherwise I like it, very nice! Thanks for sharing

  • Great tutorial, nice work!

  • Pingback: 50 New Useful CSS Techniques, Tutorials and Tools - Smashing Magazine()

  • Helpful tutorial, thanks ever so much! 🙂

  • Excellent tutorial, the best is that progress bar is not using flash. I am going to use it for one of my new projects home page presentation.

  • This is nice! Really very nice, congratulations to Ivan (for the work) and Jean-Baptiste (for sharing with this nice tutorial)

  • It’s not looking super hot in Chrome 7.0.517.36 but still cool tutorial nonetheless. Here is a screenshot of what I’m talking about:

  • Can you use this to preload a whole page? That would be awesome. I really need a great preloader and the only one I can ever find is Gaya’s jquery preloader.


  • nice work with css

  • Waw ! That’s really beautiful. Nice work !

  • Mick

    I really do like this example, but I must say I am disturbed by your comments regarding IE 8 and below. Rather than embracing the challenge of finding ways for this to work in those browsers you rather fall back to name-calling which I find rather unprofessional. It is quite a shame.

  • ryan Wijaya

    very interesting and awesome script!

  • Does this progress bar show a real time status of the amount of data loaded or is the animation predefined?

  • Feeeeeb

    Pretty cool, I guess, but ultimately useless as it doesn’t work in IE. However much IE sucks, there is no point developing just for Firefox or other browsers. Your average Joe uses IE and doesn’t even know what a browser is.

    A lot of people I know think Internet Explorer IS the Internet.

  • Cool stuff, and really pretty simple too. Can’t wait till this fully supported!

  • hey really nice work with CSS

  • That’s cool! Now I’ll find something to use it on!!!

  • That’s really cool. I’ve been meaning to try out some CSS3 but I’m a little intimidated. Oh and by the way, I love the illustration at the top of your blog…totally cute!

  • Great looking progress bar. I can think of a few good uses for it.

  • Wow, I’m surprised at the all criticism.

    First, it’s a great plugin.

    Second, it’s free.

    Third, he doesn’t work for you.

    Fourth, IE8’s support of CSS3 is ‘minimal’, thus most dev code does not work with ALL browsers OUT OF THE BOX. Nor would I expect him to spend hours/days troubleshooting this issue.

    Thanks for the code.

  • Great css3 bar Is very nice, thank you for share the bad side of css3 is IE but this bar and so much css3 effects are very very nice. I hpe IE will update and support all css3 functions.

  • Wow, looks very nice. But could you give me a hint on where we can use this in our sites? I mean is it made to show the progress of the loading of the page?

  • A very thorough tutorial. Found this searching through google and it’s exactly what I needed. Thanks!

  • Jay

    Grate tutorial, thanks for sharing Jean.

  • Pingback: CSS3 Tutorials to Brighten Up Your Day - Noupe Design Blog()

  • Thanks for the great article. I will be back here often for more ideas!

  • For quite some time there’s been a surprisingly neat fix for the legendary Chrome issue, that made some of you say a lot of stuff, you wouldn’t probably say otherwise. 🙂 Here:

    Thanks for the plugin!

  • Beautiful. Exactly the kind of bar I was looking for (+bonus animations). I’ve added you to my ‘Morning’ folder; it’s about time I started seriously looking at the bleeding-edge of css3.

  • Really cool and simple tutorial….

  • Great work , i really like this Css progress bar, but really hard to create the same without copying the code from this tutorial. Someday i will be that much expert so i can create such a great piece of design. Thanks for sharing.

  • I really love the HTML5 and CSS3. Now we can do some rich UI element with this technology. This progress bar is such an example. Thank you very much for the awesome post

  • jason

    This works great if it is single process bar in a page.
    However, when running multiple process bar then all of them start and finish at same time.

    Note: Each div shows about 6 seconds delay

  • Paul Mountney

    This doesn’t work in Google Chrome version 23, which is the latest version. I’m using NetBeans 7.3 Beta 2 for my coding experience, and it has a ‘connector’ with Chrome, which gives me instant updates as i save my progress with HTML files. I get an animated ‘bar’ with this code, but it’s just text. After the progress gets to 100%, it says, ‘Done’, then disappears, and the words ‘Hello World’ show up after, but not graphical bar is displayed.

  • Marcus

    Awesome tutorial! Everything works .. EXCEPT that the progress bar fails to disappear after it’s done. No idea how to do this. Am on Mac, OS 10.5.8, Safari 5.0.6. Thanks!

  • Davide

    hi, beautiful work!
    please, how to stop the bar at different points ? (20%, 40%, 60% …. 99%?)

    i would use it for a work-in-progress page

  • Is there a way change the template of the loading bar? I have a redish theme and I would like to make something to resemble it…

  • I’m facing the same problem as Marcus. I’m on Mac, and the bar seems to act strange when the progress is at 100%. Any idea how to fix this? Is there a special code for Safari?

  • Maine Lee

    Hi! Thanx for your creation!
    Could you tell me how to stop the progression at 80% for example?