Grow your CSS skills. Land your dream job.

Display Form <progress>

Published by Chris Coyier

Imagine you have a form with 10 required fields on it. That's a bit larger than your average form on the internet and a good bit of work for a user. You might lose some users along the way, which is never a good thing. Perhaps to encourage finishing the form, you let them know how close to completion they are, and display motivational messages along the way.

progressform
View Demo

1. HTML for Required Inputs

Inputs wouldn't necessarily need to be required for this demo, but it makes for a clean demo. Filling out an optional field doesn't bring you any closer to the minimum requirements for submitting a form. So for this demo, we'll have 5 required fields down a typical form that collects information for payment.

<form id="payment-form" action="#">
  
   <label for="name">Full Name</label>
   <input required id="name" name="name">

   <!-- etc -->

</form>

2. HTML for Progress

There is an HTML element specifically for visually displaying progress. Literally, <progress>. Let's have one of these available (with an ID so it's easy to target with JavaScript). Place it where you will.

<progress max="100" value="0" id="progress"></progress>

Making the max attribute 100 means for easy math. The progress bar is as full as the value in percentage is. E.g. value="20" == bar is 20% full.

progress
No styling needed, you get this look by default (platform specific).

3. Watch for Changes

We'll use jQuery here to make event binding and element selection easy. All our inputs here will be text-y, making keyboard events relevant. So...

$("#payment-form input").keyup(function() {
  
  // calculate progress

});

4. Count Number of Valid Inputs

Whether or not any particular input is valid or not in its current state is part of the DOM now. Once we have a pointer to it, we just check this.validity.valid for true or false.

var numValid = 0;
$("#payment-form input[required]").each(function() {
    if (this.validity.valid) {
        numValid++;
    }
});

5. Adjust the Progress Bar / Display Messages

Now that we have an integer of how many inputs are valid, we just set up some basic logic to adjust the progress bar's current value.

This is where we could also display our motivational messages. Perhaps there is a <p> element somewhere on the page which we have a pointer to (progressMessage) and we simply adjust the text inside it to match the progress.

// "Cached" somewhere once
var progress = $("#progress"),
    progressMessage = $("#progressMessage");

// Logic that runs after counting every time
if (numValid == 0) {
    progress.attr("value", "0");
    progressMessage.text("The form, it wants you.");
}
if (numValid == 1) {
    progress.attr("value", "20");
    progressMessage.text("There you go, great start!");
}

Browser Support

If browser support is a concern, you'll probably want to run a little Modernizr test first. If it passes, then load scripts, inject elements, however you want to handle it.

if (Modernizr.input.required) {

  // Modernizr.load, inject elements, whatever.

}

If you need more help on that, read this article.

Demo on CodePen

Do whatever you'd like with it.

Comments

  1. Permalink to comment#

    That’s a great idea! Love that concept especially the dynamic progress bar! We’ll use that. Thanks!!

  2. Permalink to comment#

    I wasn’t aware of this.validity.valid, very handy. Good article as well!

  3. Hallo
    Permalink to comment#

    Pressing key isn’t the only way to change input field. You can also do it for example with drag & drop or pasting using middle mouse button in some linux distributions.

    • John
      Permalink to comment#

      Very good point, Hallo.

      I would change the trigger event to focus/blur or something.

      Otherwise love the idea!

    • Autofill also confuses it. But I great concept once the kinks are worked out.

  4. Permalink to comment#

    This is a great example of progressive enhancement. It does bring up the question that will be asked: How stylable is that progress bar.

  5. mwhyte.ca
    Permalink to comment#

    Brilliant use of progress bar….I have been thinking of a way to demonstrate the HTML progress bar in a way that was easy to explain and show……This fits the bill perfectly…Thank you for sharing…

  6. You should probably use the “input” event via .on("input"). Note it’s not supported in IE lower than 9 (I think), so you could use both (.on("input keyup")). Also on windows (7 at least) the progress bar is constantly animated, so maybe a custom progress bar or the <meter> element , which has “custom” styling in the browsers as far as I know, would be better…

  7. I think this goes without saying but IE9 hates this.

  8. Permalink to comment#

    Nice. Would be cool to animate the progress bar too. Something like this:

    http://jsfiddle.net/526hM/

    Not my code, though; comes from this SO thread, from someone named “Thomas”.

  9. I did not know there was a <progress> element in HTML. I’m surprised you don’t see this element much for ‘loading’ pages.

  10. Diana Cee
    Permalink to comment#

    If someone can please explain to me where the validation of this form is being handled on the demo i would appreciate it thank you.

    • Permalink to comment#

      It’s in the HTML, using the “pattern” attribute. I believe the JS also checks for empty/filled inputs, to make the progress bar and messages proceed.

      The “pattern” attribute is new in HTML5 and lets things get validated client side without extra JavaScript.

    • Diana Cee
      Permalink to comment#

      Got it. Thank you. Will have to read up on all the new HTML5 form elements.

  11. Just be careful about Safari 5 (and Mobile Safari 5). It aggressively deletes progress elements instead of just ignoring them. You might have to test to see whether the progress element exists at all first.

  12. Chris
    Permalink to comment#

    Nice, thank you!

  13. Nico
    Permalink to comment#

    Setting the percentages manual is a mess.

    How about to add classes like “valid” if valid and change the width of the progressbar to (amount of inputs)/(valid inputs)?

  14. Permalink to comment#

    As many forms are accompanied by JS client validations I would consider updating the progress only after the required value is already validated (and valid). Also using an animator function as Louis mentioned would be a nice addon.

    The autofill could be workarounded by another event handler after the page is loaded that will walk through the fields and validate them (and as we would have our progress update hooked on validations the progress would immediately update to corresponding value).

Leave a Comment

Current day month ye@r *

*May or may not contain any actual "CSS" or "Tricks".