CSS Progress Bar Tutorial: Part I | Styling a Simple Progress Bar in 3 Easy Steps

Step 1:  Reset All CSS Properties to a Default Style

For any CSS project, we have to start with our reset.  Elements can be rendered differently from browser to browser.  Since Internet Explorer still sucks, resetting all of the CSS properties to a default style solves a lot of issues before you even have to think about it.

Normally, I use a modified version of the Yahoo! UI Reset.  Since it is a non-factor here, I can just include the file directly from Yahoo!

<link rel=“stylesheet” type=“text/css” href=“http://yui.yahooapis.com/2.7.0/build/reset/reset-min.css”>

Step 2:  Create the Progress Bar

Creating a progress bar is actually very simple, and can be done with just two div elements.  We will have an outer one, which will be the container.  I will call it “progressbar”.  Then, we will have a child div, which I will call “progress“.  The child div will represent how much progress is done.

The HTML markup is simple:

<div id=“progressbar”><div id=“progress”>50%</div></div>

[shiny’s edit for the noobs:  God help you if you actually need this in order to understand parent and child divs, but….


When rendered in a browser, it will look like this:

Step 3:  Styling the Heights, Width and Border

[shiny noob note:  When going in to production, always remember the best practice is to move the CSS into an external file.]

Both div elements are going to need set heights.  The height does not matter, whatever works for you.  For the sake of our example, I will go with 50px tall.

The progress bar is also going to need a width.  The width of the progress bar, again, does not matter — whatever the application demands.  500px should work for our example.

Finally, I will add a border just so we can see what is going on.  For those of you keeping score at home, this is what we have so far:

<div id=”progressbar” style=”height:50px;width:500px;border:dashed 1px #000″>

    <div id=”progress” style=”height:50px;“>50%</div>


When rendered in a browser, it will look like this:

Step 4:  Styling the Background
Okay, so you can see we have something happening.  The next step is to set the background up so we can really see some progress (haha, see what I did there).

First, I am going to remove the 50% text from the child div.  Since this text would always be displayed in the child div, it would cause overflow at really low percentages.

Next, I am going to define two more CSS properties of the child div: width and background-color.

  • Since the parent div already has a defined width, we can just use a percentage for the child div.  In this case, our 50% returns, just not in text form.
  • I also defined the background-color of the child div as green in order to set it off from its colorless parent.

These changes will bring our code up to this point:

<div id=”progressbar” style=”height:50px;width:500px;border:dashed 1px #000″>


<div id=”progress” style=”height:50px;width:50%;background-color:Green”></div>



And, the browser will render this code to look like this:

Congratulations, you have styled a progress bar in CSS.  However, that is pretty damn ugly.  Let’s look at some other approaches with the graphics to make this a little prettier.

Optional Step 4.1:  Making the Progress Bar Pretty

I do not have photoshop at home, so we’ll be tackling this in MS Paint, bear with me here.

I’m going to start by changing the CSS properties of the parent div.  I’ll bust down the height to a slimmer 24 pixels and give the left side a solid 1 pixel grey border.

For the child div, or actual progress, I’m going to use an image.  This image:

This image is 500px wide, so simply setting it as the background would indicate 100% progress, but we are going to go a little fancier still.

  • We are going to toss the “%” text back in so people have a number to correspond to their progress.
  • We going to add some padding to the top and to the left so the text isn’t scrunched into the upper left hand corner like it was in the earlier example.
  • We are also going to specify the font family, font size and font weight.
  • The image is set at background position “0  0” so all 500 pixels are displayed for our full 100% representation.
  • Finally, please note the image is set to “no-repeat”.  Obviously, this doesn’t matter when progress is at 100%, but it would certainly come into play for anything less.

These improvements will make our code look like this:

<div id=”progressbar” style=”height:24px;width:500px;border-left:solid 1px #b6b6b6″>


<div id=”progress” style=”height:24px;padding-left:5px;background:#fff url(progress-bar.png) no-repeat;background-position:0 0;font-family:Georgia;font-size:12px;padding-top:3px;font-weight:700″>100%</div>



And, the browser will render our code to look like this:

Now, how do you represent progress less than 100%?  Simple, just change the coordinates of the background position and the “%” text.  For example, if you want to represent 50% progress, shift the background position to the following:
background-position:-250px 0;
Resulting in:

<div id=”progressbar” style=”height:24px;width:500px;border-left:solid 1px #b6b6b6″>


<div id=”progress” style=”height:24px;padding-left:5px;background:#fff url(progress-bar.png) no-repeat;background-position:-250px 0;font-family:Georgia;font-size:12px;padding-top:3px;font-weight:700″>50%</div>



Which renders as:
Think of the background position as aligning your progress image on a X,Y axis.  The first number corresponds with the horizontal location and the second is vertical.  If your progress image is 500 pixels and you want to represent 50%, then you have to hide 250 pixels in negative territory where they won’t display.  This is how we arrived at -250px  0;

Achieving any other percentage is just simple math.  If you want to represent 77% then determin 77% of 500 pixels (385 pixels), and hide the remainder in negative territory (-115px  0;)

It really is that simple.

Coming Soon:  CSS Progress Bar Tutorial: Part II | Styling Javascript Animated Progress Bars

1 comment » Write a comment

Leave a Reply

Required fields are marked *.