The progress element

by .

When building web sites and web applications, we often need to provide essential feedback to a user informing them of the progress of their request or task, be it uploading a file, playing a video, or importing data.

HTML5 makes life easier for us by defining an element whose sole purpose is just that: the <progress> element.

The HTML5 specification describes it best:

The progress element represents the completion progress of a task.

The task itself is irrelevant, but displaying its progress is not.

Attributes

There are four attributes that are specified for the <progress> element: max, value, position, and labels. Before taking a look at each of theses attributes in turn, here are a few important notes on them:

  • If the value attribute exists, then the progress bar is considered to be determinate (i.e., it has exact limits). Otherwise it is considered to be indeterminate.
  • If the max attribute is not included, the default acceptable range for the progress bar is between 0.0 and 1.0 inclusive.
  • Authors are encouraged always to include the current value and the maximum value (if used) as inline text to the <progress> element so that the information is still visible to users of legacy browsers.

And now let’s take a closer look at the attributes themselves:

Max
The max attribute is a floating point number that indicates how much work the relevant task requires in total before it can be considered complete. The default value is 1.0.
Value
This is a floating point number that represents the current progress of the relevant task. Its value must be greater than or equal to 0.0 and less than or equal to 1.0 or the value of the max attribute if present.
Position
This is a read-only attribute that returns the current position of the <progress> element. This value is equal to value / max for a determinate progress bar and -1 for an indeterminate progress bar (as the position can’t accurately be determined).
Labels
This is also a read-only attribute that returns a list of the <progress> element’s labels (if there are any).

Examples

Let’s now take a look at some examples of how the <progress> element might be used, including how it might be updated via JavaScript.

Simple Indeterminate Progress Bar

<progress id='p'></progress>

Since we have no idea how long the task in hand will take, the browser will simply display the progress bar until the task is complete and we either hide it or replace it with a ‘task complete’ message.

Simple Determinate Progress Bar

<progress id='p' max='70'><span>0</span>%</progress>

And the JavaScript for updating it:

var pBar = document.getElementById('p');
var updateProgress = function(value) {
  pBar.value = value;
  pBar.getElementsByTagName('span')[0].innerHTML = Math.floor((100 / 70) * value);
}

Note that here the progress bar can have a maximum value of 70, so calls to updateProgress will have values between 0 and 70 and that the value is also displayed within the <progress> element so that it is visible as a simple percentage string for users of legacy browsers.

Using <progress> with HTML5 Video

A good example of using the <progress> element is with an HTML5 video, informing the user how much of the video has been played. This won’t be a full example but will just show the necessary HTML and JavaScript.

Given a <video> element with an id of ‘v’:

<progress id='p' max='100' value='0'><span>0</span>% played</progress>

Use this JavaScript:

var video = document.getElementById('v');
var pBar = document.getElementById('p');
video.addEventListener('timeupdate', function() {
  var percent = Math.floor((100 / video.duration) * video.currentTime);
  pBar.value = percent;
  pBar.getElementsByTagName('span')[0].innerHTML = percent;
}, false);

The JavaScript uses the timeupdate event, which is constantly triggered as the video is being played. The value is converted into a percentage value using the video’s duration (full length) and currentTime (where in the video it currently is).

Using <progress> with the File API

Another useful example is how the <progress> element might be used with the File API. Again, this is not a complete example, assuming the existence of a file input and upload button and <progress> element, and code for reading the file. The specification itself has some good code examples of this.

var p = document.getElementById('p');
// 'reader' is of type FileReader
reader.addEventListener('loadstart', function(evt) {
  if (evt.lengthComputable) p.max = evt.total;
}, false);
reader.addEventListener('progress', function(evt) {
  if (evt.lengthComputable) p.value = evt.loaded;
}, false);

Here the loadstart event is used to set the max attribute of the <progress> element, and then the progress event is used to update the <progress> element’s value attribute.

Browser Support

The <progress> element is fairly well-supported in today’s major browsers, although only in version 6+ of Safari (so not on Windows, as the last version there was 5.1) and only in version 10+ of Internet Explorer.

Styling

As is usual with such elements, browsers have their own unique styling for the <progress> element. You can, however, override this to a certain extent using simple CSS.

The default styling tends to consist of an element with rounded corners, a grey background colour, and a green gradient for the actual progress marker.

A screenshot of the progress element in Firefox
The default styling for the progress element in Firefox 18.0.2.

Let’s say we want to style our progress bar for the HTML5 Doctor website, so that it fits in with the design. We’ll remove the bevel and the gradients using only solid colours. The code below will almost do that:

progress {
  color: #0063a6;
  font-size: .6em;
  line-height: 1.5em;
  text-indent: .5em;
  width: 15em;
  height: 1.8em;
  border: 1px solid #0063a6;
  background: #fff;
}

This, however, won’t change the colour of the progress bar itself, which will remain a green colour. We can change this in Firefox, Internet Explorer 10, Chrome, and Safari using a variety of methods which are outlined below.

Firefox

All we need to use here is:

progress::-moz-progress-bar { background: #0063a6; }

and Firefox will display the colour correctly.

A screenshot of the progress bar after custom styling
The progress bar as it appears in Firefox 18.0.2 after being styled.

Chrome and Safari

For Chrome and Safari, we need to use progress::-webkit-progress-value to specify the progress bar colour and progress::-webkit-progress-bar to specify the background colour of the <progress> element itself:

progress::-webkit-progress-bar { background: #fff; }
progress::-webkit-progress-value { background: #0063a6; }

Internet Explorer 10

Actually the CSS above will be fine to style the <progress> element in IE10, but it’s worth noting that this browser interprets the <progress> element’s color value as the colour of the progress bar.

I’ve uploaded some working examples of determinate and indeterminate progress bars for you to see.

Summary

The <progress> element may seem very similar to the <meter> element — which was also introduced in HTML5 — but it can be seen as a more specific kind of <meter> element that’s only used to measure progress of a task. It’s worth bearing this in mind when deciding which one to use.

Since browser support is pretty good, it’s definitely worth using the <progress> element where appropriate, but you should also ensure that you provide textual fallback for legacy browsers as has been outlined above.

21 Responses on the article “The progress element”

  • Santosh says:

    Hi Ian, I like you article, its really useful for me.

  • NatalieMac says:

    Fantastic tutorial, Ian. Thank you very much. I’m so excited about the new HTML5 elements.

  • Ian Devlin says:

    Thanks to you both for your kind comments, glad you found it useful.

  • Peter Jaros says:

    Perhaps I misunderstand, but it appears that the “indeterminate” progress bar above is in fact determinate, but percentage-based—that is, it’s “max” value is the default, 1.0.

    An indeterminate progress bar is not one without a “max”, but without a “value”. In Mac OS X’s native GUI, for instance, and indeterminate progress bar is shown as a candy-striped “barber pole”, showing that work is happening, but we can’t say how much. It can also be shown as a spinning indicator, which is a familiar use case to most web developers.

  • Ian Devlin says:

    Peter, I think that it is indeed I who misunderstood and you are correct!

    Thanks for pointing it out, I will update the article and get the example altered.

  • Adam says:

    how to make big its in small i need width:500 how to do plz help me

    0% played

  • Simon Davies says:

    Just tried to use the example link and the buttons do not work on an ipad, so cannot view till I get to computer, unless you can look at this, otherwise good work on this article

  • Ahmad Alfy says:

    I was always wondering about that default progress indicator! I have seen it being used by many WebGL demos and I was wondering is that a design produced using CSS? Thanks for clearing this up; I never knew about that element before this post. Definitely gonna use it in the future.

    By the way it renders the same in FF and Chrome on Windows

    Thanks HTML5Doctor!

  • Query – why do you use math to determine the percentage instead of just using the readonly “position” property and multiplying by 100? Granted it isn’t going to save you a lot of work, but it seems … more appropriate?

  • Ian Devlin says:

    Raymond, if the browser doesn’t support the progress element then there won’t be any “position” property to use.

  • 555 says:

    Do you think it would be appropriate to use the element to indicate a user’s progression through a particularly wieldy form. eg. step 2 of 5

  • Adrian says:

    I tried to use the progress element with audio elements, so I could style it a bit more than the
    default audio progress bar.
    I found that updating every second made it quite jerky.
    I wrote my own, using a div inside a div and increasing the width and the effect was much smoother.

  • Ollie New says:

    Hi Ian – great article, thanks. One thing (and please correct me if I’m wrong)…

    in the example ‘Using with HTML5 Video’ you are referencing the ‘v’ variable when you .addEventListener and do .currentTime. Shouldn’t those reference the variable ‘video’ instead?

  • Ian Devlin says:

    You are indeed correct Ollie, thanks for pointing that out. I have updated the article.

  • George Aziz says:

    very Fantastic tutorial, Ian. Thank you very very much. I’m so excited about the new HTML5 elements.

  • Nijraj Gelani says:

    Hey,
    Anyone can help me please
    How can I use this HTML progress bar to show Progress of my website or Image loading

    Please Say in easy words
    If its already in article please point me there

  • Federica says:

    Hello,

    I used this code to create a video progress bar. It worked really well. Thank you very much!

    Although I would like to make the progress bar draggable, so that people can skip the video by dragging the edge of the bar.

    Do you know how I can make that?

    Thanks in advance,
    Federica

  • Peter Jaros says:

    Federica: You could do that by tracking mousedown, mousemove, and mouseup events, just like any other drag-and-drop in JavaScript. You’d have to do a bit of math based on the position and size of the progress bar to figure out how much to change the bar’s value.

    For video scrubbing, you’d probably also want to adjust the value on mousedown to immediately jump to wherever the user is clicking. Again, it’s a little bit of math, but it should be pretty straightforward.

  • Martijn says:

    What would be a good example to use instead of ? I really don’t see the difference between the two. And if they’re so similar, why do they need a unique tag name for both?

    Also, the bit about Opera is wrong. They haven’t moved to webkit, they’ve moved to being a shameless Chromium-clone, so Opera’s rendering should be exactly identical to Chromium’s. Or you could see it as a “new” browser, dubbed by the community as Chropera.

  • Jason says:

    Unfortunately, neither the Progress bar nor the Meter bar, are compatible with the Output tag rendering them useless!

    If you have to update the result with a complex javascript function then you might as well write a custom meter/progress bar that looks good and doesn’t have to deal with pre-formatted junk elements!

    Here’s what I’m talking about:

    0%

    0%

    0%

  • Leave a Reply to Ian Devlin

    Some HTML is ok

    You can use these tags:
    <a href="" title="">
    <abbr title="">
    <b>
    <blockquote cite="">
    <cite>
    <del datetime="">
    <em>
    <i>
    <q cite="">
    <strong>

    You can also use <code>, and remember to use &lt; and &gt; for brackets.