style the numbers in an ordered list!) – Web Performance and Site Speed Consultant

  • Home
  • WEBSITES
  • style the numbers in an ordered list!) – Web Performance and Site Speed Consultant
May 17, 2025


Written by on CSS Wizardry.

Table of Contents
  1. Design and build
    1. Design
    2. Build
  2. Styling
  3. Styling numbers in ordered lists
  4. Progressively enhancing
    1. Recap
  5. Mobile optimisation
  6. Demo
  7. Final words

How about that for an over-the-top title? But it’s true, that’s what we’re going to be doing. It’s been a while since my last post, unfortunately, so I thought I’d make up for it with this sizeable offering in which we will learn a lot of really great techniques in order to make something as simple as a progress bar. By which I mean a breadcrumb-esque meter of steps, such as you might find on a checkout process; we are making this:

Screenshot of the final product.

And in doing so we will cover:

  • Design and build a semantic, accessible and sensible progress bar.

  • Utilise the much underused method of styling page-specific elements based on their IDs.

  • Style the numbers in an ordered list!

  • Progressively enhance it with some CSS3.

  • Optimise it for mobile.

N.B. This article isn’t so much about a progress bar, but more an illustration that best practices and more advanced techniques can be applied to even the most insignificant aspects of a build to create something awesome!

Design and build

Let us assume the brief is this:

We require a numbered progress bar to indicate user location (past, current and future) during a checkout path on the OurService™ website. It must:

The design, let’s assume, is predefined. It looks as above, purely because it has to. The design is not the major focus of this article, the code and techniques are.

“Code what you consume, not what you see.”

Design

The progress bar shall be a linear, left to right series of linked labels. Current location shall be indicated by a change in colour, progression onto the next step shall be indicated by an arrow.

Build

For the purposes of this tutorial we shall assume the current page is the payment page.

One school of though I find invaluable when it comes to sensible and semantic builds is code what you consume, not what you see. This is a very broad generalisation but works for the most part. Code content independently of (and before you consider) coding any styles. Web development basics, but fundamental to web standards and progressive enhancement.

So, what are we consuming? It’s an ordered list of steps which indicate location in a process.

Okay so first off we know we need an

    as this list has fixed and definite order. We also require titles and supporting copy for each item. As the titles and supporting copy require separation from one another we are going to wrap the titles in a ; a generic inline container. This leaves us with:

    There are a few things in this code which I’ve not yet mentioned, one is the ID on the , another being the class on each

  1. and the last being the wrapped around the payment page’s text. I shall explain these next.

    ID and list item classes

    A combination of an ID on the and a class on a list item can allow you to know what the current page is. The CSS #payment-page .payment-step{} will target the payment section of the progress bar when it is on the payment page in the process. Similarly, #go-page .go-step{} will target the go item on the go page. I wrote a much more in-depth article on this over at Venturelab.

    The around the payment step’s text

    If you’re determining current page programatically, one could argue inserting a class="current" on the relevant item. This is doable, but avoiding such a class name is far nicer.

    As stated earlier we are assuming the current page to be the payment page. Now, we can style the current step on any page using CSS, as outlined above, however how would a user with styles disabled be able to tell what the current page is? How can we highlight this for those users?

    Well the solution would be to programatically wrap a around the text on that page, undo the bolding effects with CSS for browsers with styles enabled, and allow people viewing unstyled content to see that the bolded item is the current page. This gives us:

    Unstyled progress bar

    As you can see, users with styles disabled can clearly see the current link is the bolded one, this makes the progress bar that little bit more accessible to those who might need it.

    So there we have it, the markup that powers the whole thing.


    Styling

    Now to style this thing up. First off we’ll look at the very basic CSS, and that alone:

    
    html{
      height:101%;
    }
    body{
      font-family:Calibri, Arial, Verdana, sans-serif;
      background:#fff;
      color:#88979e;
      width:940px;
      padding:10px;
      margin:0 auto;
    }
    
    
    
    #progress{
      list-style:none; 
      float:left; 
      margin-bottom:20px;
    }
    #progress li{
      float:left; 
      font-size:0.75em; 
      font-style:italic; 
    }
    #progress a{
      display:block;
      text-decoration:none;
      padding:10px 25px 10px 10px; 
      background:#7b8d77;
      color:#fff;
    }
    #progress span{
      font-size:1.333em; 
      font-weight:bold;
      display:block;
      font-style:normal; 
    }
    #progress strong{
      font-weight:normal; 
    }
    #progress a:hover{
      text-decoration:none;
    }
    #progress a:hover span{
      text-decoration:underline; 
    }
    #details-page .details-step a,
    #account-page .account-step a,
    #products-page .products-step a,
    #payment-page .payment-step a{
      background:url(../img/css/splitter.gif) right center no-repeat #a49d4d; 
    }
    #go-page .go-step a{
      background:#a49d4d; 
    }
    

    All of the above is very obvious, it is essentially just like creating a normal navigational menu, and gives us this:

    Basic progress bar

    Styling numbers in ordered lists

    Next up we style the numbers in the ordered list by using the very very useful and much unknown CSS counter module. Because you have such limited control over the appearance of your bullets in (ordered) lists they can be a pain to style. This pain is alleviated somewhat when using an unordered list as you can simply use a background image. It is an altogether different story when you’re using an ordered list as the bullet needs to change with each list item.

    What we do here is use CSS to do a very prog-like job; we get it to loop through each item in a parent container and then increment a user-defined value each time it encounters a specified child. Sounds Greek? Read this.

    Once we have this number available to us we use the CSS :before pseudo-element and the content:; property to insert the number before each item. How cool is that?!

    
    #progress{
      list-style:none;
      float:left;
      margin-bottom:20px;
      counter-reset:step; 
    }
    #progress li{
      float:left;
      font-size:0.75em;
      font-style:italic;
    }
    #progress a{
      display:block;
      text-decoration:none;
      padding:10px 25px 10px 30px; 
      background:#7b8d77;
      color:#fff;
      position:relative; 
    }
    #progress span{
      font-size:1.333em;
      font-weight:bold;
      display:block;
      font-style:normal;
    }
    #progress strong{
      font-weight:normal
    }
    #progress a:hover{
      text-decoration:none;
    }
    #progress a:hover span{
      text-decoration:underline;
    }
    #progress li a:before{
      counter-increment:step; 
      content:counter(step); 
      text-align:center;
      font-weight:bold;
      position:absolute; 
      top:50%;
      left:5px;
      margin-top:-8px;
    }
    #details-page .details-step a,
    #account-page .account-step a,
    #products-page .products-step a,
    #payment-page .payment-step a{
      background:url(../img/css/splitter.gif) right center no-repeat #a49d4d;
    }
    #go-page .go-step a{
      background:#a49d4d;
    }
    

    This then gives us this:

    Non-CSS3 progress bar


    Progressively enhancing

    Now for the CSS3 progressive bits:

    
    #progress{
      background:#7b8d77; 
    }
    #progress{
      -moz-border-radius:5px;
      -webkit-border-radius:5px;
      border-radius:5px;
    }
    #progress a{
      text-shadow:1px 1px 1px rgba(0,0,0,0.25); 
      -moz-border-radius:5px 0 0 5px; 
      -webkit-border-radius:5px 0 0 5px;
      border-radius:5px 0 0 5px;
    }
    #details-page .details-step a,
    #account-page .account-step a,
    #products-page .products-step a,
    #payment-page .payment-step a{
      background:url(../img/css/splitter.gif) right center no-repeat #a49d4d;
    }
    #progress .go-step a{
      -moz-border-radius:5px; 
      -webkit-border-radius:5px;
      border-radius:5px;
    }
    

    The full, combined CSS for the progress bar so far is:

    
    html{
      height:101%;
    }
    body{
      font-family:Calibri, Arial, Verdana, sans-serif;
      background:#fff;
      color:#88979e;
      width:940px;
      padding:10px;
      margin:0 auto;
    }
    
    
    
    #progress{
      list-style:none;
      background:#7b8d77;
      float:left;
      margin-bottom:20px;
      counter-reset:step;
      -moz-border-radius:5px;
      -webkit-border-radius:5px;
      border-radius:5px;
    }
    #progress li{
      float:left;
      font-size:0.75em;
      font-style:italic;
    }
    #progress a{
      display:block;
      text-decoration:none;
      padding:10px 25px 10px 30px;
      background:#7b8d77;
      color:#fff;
      text-shadow:1px 1px 1px rgba(0,0,0,0.25);
      position:relative;
      -moz-border-radius:5px 0 0 5px;
      -webkit-border-radius:5px 0 0 5px;
      border-radius:5px 0 0 5px;
    }
    #progress span{
      font-size:1.333em;
      font-weight:bold;
      display:block;
      font-style:normal;
    }
    #progress strong{
      font-weight:normal
    }
    #progress a:hover{
      text-decoration:none;
    }
    #progress a:hover span{
      text-decoration:underline;
    }
    
    #progress li a:before{
      counter-increment:step;
      content:counter(step);
      text-align:center;
      font-weight:bold;
      position:absolute;
      top:50%;
      left:5px;
      margin-top:-8px;
      padding:2px 6px;
      background:rgba(0,0,0,0.25);
      
      -moz-border-radius:20px;
      -webkit-border-radius:20px;
      border-radius:20px;
    }
    #details-page .details-step a,
    #account-page .account-step a,
    #products-page .products-step a,
    #payment-page .payment-step a{
      background:url(../img/css/splitter.gif) right center no-repeat #a49d4d;
    }
    #go-page .go-step a{
      background:#a49d4d;
    }
    #progress .go-step a{
      -moz-border-radius:5px;
      -webkit-border-radius:5px;
      border-radius:5px;
    }
    

    Which, when coupled with the markup, gives this:

    Screenshot of the final product.


    Recap

    So, let’s cover what we’ve done so far. We’ve:

    • Coded up a semantic progress bar (using an ordered list and correct generic elements).

    • Made it accessible (addition of the strong around the content for non-CSS browsers).

    • Styled it all up.

    • Made use of the body ID trick to mark the current page.

    • Used CSS counters to style the numbers of an ordered list

    • Progressively enhanced it all to make it a little easier on the eyes.

    Mobile optimisation

    For more information on mobile/iPhone optimised sites please see my associated article.

    Next up we need to optimise this thing for mobile. This couldn’t be simpler. The key to optimising sites for mobile is linearise. Linearise everything.

    In your markup, add this line to the section, thus:

    This tells the user agent that the viewport should be the same as the device’s own screen-size, that it should be initially set to a scale of 1 (i.e. no scale), its maximum scale is set to 1, and that users can’t scale themselves.

    Now, add the following to the very end of your CSS file:

    
    @media (max-width: 480px){ 
    body{
    	width:auto; 
    	padding:5px; 
    }
    #progress{
    	width:auto; 
    	background:none; 
    	float:none; 
    }
    #progress li{
    	float:none; 
    	margin-bottom:1px; 
    }
    #progress a{
    	margin:0 10px; 
    	-moz-border-radius:5px; 
    	-webkit-border-radius:5px;
    	border-radius:5px;
    }
    #details-page .details-step a,
    #account-page .account-step a,
    #products-page .products-step a,
    #payment-page .payment-step a,
    #go-page .go-step a{
    	background:#a49d4d; 
    	margin:0 auto; 
    }
    }
    

    Now, if you want to test this and don’t have a smartphone, or haven’t got this hosted in a live environment, simply resize your browser window right down until you see the change. I tend to use the Firefox Web Developer Toolbar addon to resize the window to 480x800px.

    On the iPhone this now looks like:

    iPhone optimised progress bar


    For the full working demo head to /demos/progress-bar/. For the complete CSS (with reset) please see /demos/progress-bar/css/style.css. Also, try using Firebug to change the ’s ID to go-page.


    Final words

    As I stated previously, this article isn’t so much about the progress bar itself. What I hope this article has shown is how something as small and trivial as a progress bar has a wealth of little nooks and crannies in which to immerse yourself. Semantics, accessibility, using IDs to style current states without a class="current", how to use CSS counters to style the numbers in an ordered list, how to progressively enhance lean markup, and how to optimise things for mobile in a flash.

    All of the above skills are easily and quickly transferable. It might be a progress bar today, but what could it be tomorrow? Skills like the ones covered here give you the potential to make something great, out of something very very simple.



Source link

Leave a Reply