fluid CSS steps – this is how it’s done :)

I have had Cody Lindley’s technique for CSS steps in the back of my head for soooo long and finally got around making my own version of it. My aim was to create a flexible fluid version of Lindley’s wizard menu. And I’ve succeeded. Here’s how:

Approach

Whether you decide to use <ul> or <ol> is entirely up to you. Do consider <dl> as well. In my example I have used <ol>. I was hoping to achieve semantically correct markup (read: not use tables – because that’s too easy and in a way cheating a bit) and create a solution that naturally stretches over the whole screen – so a block element.

Consider how many steps you are going to use in your CSS steps (wizard menu): 2, 3, 4, 5… more? Is more really necessary? Two, four and five steps are easy. You are going to end up with

  • two steps both 50% wide (class “two_steps”)
  • four steps each 25% wide (class “four_steps”)
  • five steps each 20% wide (class “five_steps”)

But what about 3? Since a floating point (decimals) is not 100% supported by all browsers and 33.3 × 3 ≠ 100, we have to cheat a little. I have decided to give the current element a width of 34%, leaving the other two at 33% (+ class “three_steps”). To users’ eye hardly noticeable, to me achieving what I set out to do in the first place. You could use similar technique when working with 6 step menu: 5×16% + 1×20% OR 5×17% + 1×15%.

/*	STEPS WIDTH	*/
#progress-bar.two_steps li { width: 50%; }
#progress-bar.three_steps li { width: 33%; }
#progress-bar.three_steps .current { width: 34%; }
#progress-bar.four_steps li { width: 25%; }
#progress-bar.five_steps li { width: 20%; }

Yes, one could argue I could simplify by omitting the #progress-bar, the choice is yours.

No matter how many steps you are using there are 5 (essentially 4) classes utilised: “current”, “previous”, “done”, “last” and empty.

  • current – for the active element
  • previous – for the element just completed – preceding immediately the “current” class
  • done – for the element dealt with two (or more) steps back – for the element preceding immediately the “previous” class
  • last – for the very last element – used in conjunction with current

Here is the CSS for the whole progress bar, I’ll go through each line separately:

/*	PROGRESS BAR	*/
#progress-bar { text-transform: capitalize; margin-bottom: .25em; height: 3.5em; }
#progress-bar li { float: left; height: 3.5em; color: #ccc; background-color: #efefef; background-image: url(../img/steps/default.png); background-position: right center; background-repeat: no-repeat; }
#progress-bar a { display: block; padding: .25em; height: 3.5em; line-height: 150%; text-decoration: none; }
#progress-bar em { display: block; font-style: normal; font-weight: bold; }
#progress-bar span { display: block; }

#progress-bar .current { color: white; background-color: #369; background-image: url(../img/steps/current.png);  }
#progress-bar .current a { color: white; }
#progress-bar .last { background-image: none; }
#progress-bar .done { color: white; background-color: #c8e9ed; background-image: url(../img/steps/done.png); }
#progress-bar .previous { color: white; background-color: #c8e9ed; background-image: url(../img/steps/previous.png); }

I have sat down earlier and thought of the colours my progress bar is going to be. I wanted grey for bits that have not happened yet, the teasing (used #efefef as it is very light yet recognised as grey with #ccc for the colour of the text). Something stronger, bolder for the current element: #369, text white. And the previous and dealt-with parts: lighter blue perhaps, text white too? I used #c8e9ed as the background colour.

At this point I should maybe mention the four different background images we will be using to create the illusion of one step leading to another. According to the classes mentioned before I created four images that I will use as backgrounds of the li – list items. Here they are:

defaultpreviousdonecurrent

The first one: default – as in the first step all steps but the first are yet to happen, the two transitions we will be witnessing is between the elements with grey background and the current element with the dark-blue background into the grey again. Every step after the current one – unless the current is the last step – is a little unknown (blue into grey) – the blend is obvious and easy. In the case where current IS the last step we combine it with the “last” class – which disables the background image yet preserves the background colour. The “previous” class transitions from lighter blue (has happened) immediately into “current” element – light-blue into dark-blue transition. And the last: “done”: both done and previous steps have happened, hence only a transition between light-blue AND light-blue. Easy, right? :)

Since there is always going to be only one instance of the progress bar and since an id has more gravity as a selector than a class I named my little experiment “progress-bar”. I suppose the only important rule in the first line is the height of the whole thing. If you are trying to fit in more: change it.

Rather than using “li { display: inline; }” I floated the list items, the height matches the parent element and the important bit: the background. Since we are assigning the aforementioned background arrows to <li>s themselves, rather than explicitly writing the rule every time it occurs I defined the background-position and background-repeat for all the elements here. It doesn’t change throughout the steps and saves couple of bytes :) No really..

Used <em> (emphasis) and <span> to describe the steps, rather than floating and clearing each other I used display: block on both. The rest deals with each step by changing the default background and the colour of the text to allow users to easily distinguish between what has happened and what is still ahead. The .current a { color: white; } rule is there to overwrite an existing one higher in the stylesheet, you might choose to leave it out.

As mentioned before: striving for semantically correct markup I have used <ol> – ordered list – they are steps in the end that happen in a particular order – so it only makes sense to use that. There is a link within each li, note that NOT ALL OF THE LINKS have a “href” attribute. The code for the first step is fairly simple – I have used an example from our day-to-day programming:

<ol id="progress-bar" class="four_step">
<li class="current"><a href="#nogo" title="description"><em>step one &raquo;</em><span>description</span></a></li>
<li><a title="members"><em>step two &raquo;</em><span>members</span></a></li>
<li><a title="folder access"><em>step three &raquo;</em><span>folder access</span></a></li>
<li class="last"><a title="confirmation"><em>step four &raquo;</em><span>confirmation</span></a></li>
</ol>

This is what it the first step looks like formatted in real life:

form-steps

Second step:

form-steps2

Third step:

form-steps3

Fourth step:

form-steps4

Voila!

Believe it or not I have been searching for a similar solution all over the internet on and off for over a year. As I mentioned earlier the main credit goes to Cody, his awesome solution inspired me in the first place. I was excited implementing the solution in the latest DocuView and testing: successfully in IE6+ (hell) – Win, FF 2+ Win & Mac, Safari 3+ Win & Mac, Chrome 1+ Win and lets not forget Opera 9.5+ both Win & Mac.

If you have any suggestions, if you think I could have done it easier or differently or if this too is what you have been looking for leave me a comment below.

Now I’m onto turning this (the MAC-like dock that is) into a semantically correct solution, one that works in IE6. And when I do, you will hear about it here. Make sure you subscribe to our feed to get the all the updates!

At both W this point I should maybe mention the four different background images we will be using to create the illusion of one step leading to another.
Bookmark and Share

One Response to “fluid CSS steps – this is how it’s done :)”

  1. femi says:

    Hi, I really like this, here is my way :

    http://www.vision.to/step-by-step-menu-a-wizard-lke-single-image.php

    Your solution is inspiring too, will try to make it with single image …

Leave a Reply