I absolutely love coding up the more semantic aspects of a build. Usually forms and tables, it’s these massively semantic (read; lots of elements with very specific jobs) that I really love coming up against. They’re not all that challenging, but they’re very fun (to me at least—is that sad?!)
After Séan shared the Financial Times’ timeline I got to wondering how I’d code my own (albeit massively more simple) timeline.
This is what I came up with: HTML/CSS timeline.
The markup
The markup is amazingly simple. Semantically I used an <ol>. This was quite an obvious choice as this is an ordered list of events. I used one id="" and some supporting datetime attributes where known (some exact dates are unknown, therefore not included (hopefully you’ll know your exact dates!)), and then that’s it:
<ol id="timeline">
<li>
<time datetime="1990-07-04">July 1990</time>
<p>Born</p>
</li>
<li>
<time>September 1994</time>
<p>Started first school</p>
</li>
<li>
<time>September 1999</time>
<p>Started middle school</p>
</li>
<li>
<time>September 2003</time>
<p>Started high school</p>
</li>
<li>
<time>September 2006</time>
<p>Started 6th Form</p>
</li>
<li>
<time datetime="2007-11-19">November 2007</time>
<p>Registered csswizardry.com</p>
</li>
<li>
<time datetime="2008-07-14">July 2008</time>
<p>Joined Sense Internet as Web Developer</p>
</li>
<li>
<time datetime="2009-03-16">March 2009</time>
<p>Joined Twitter</p>
</li>
<li>
<time datetime="2010-01-11">January 2010</time>
<p>Joined Venturelab as Web Developer</p>
</li>
<li>
<time>January 2011</time>
<p>Became a member of the Smashing Magazine Experts Panel</p>
</li>
<li>
<time datetime="2011-03-21">March 2011</time>
<p>Joined Sky as Senior UI Developer</p>
</li>
</ol>
I was initially marking the dates up as <b>s but as Mark pointed out I could use the new HTML5 <time> element.
The CSS
As far as basic styling goes, I won’t insult your intelligence; I merely set some type styles and background colours on the list items.
The really interesting bits are the odd/even styling, the ’spine’, the dot and arrow ‘images’ and the branches off the centre of the timeline. I put images in quotes because they’re not actually images at all, they’re :before and :after pseudo-elements.
The spine
The spine running down the timeline is actually an image and is applied as a background using the fantastic Dummy Image:
#timeline{
background:url(http://dummyimage.com/1x1/f43059/f43059.gif) top center repeat-y;
width:820px;
padding:50px 0;
margin:0 auto 50px auto;
overflow:hidden;
list-style:none;
position:relative;
}
The arrow and dot
The arrow and dot, as mentioned above, are actually pseudo-elements. Their CSS is:
#timeline:before, /* The dot */
#timeline:after{ /* The arrow */
content:" ";
width:10px;
height:10px;
display:block;
background:#f43059;
position:absolute;
top:0;
left:50%;
margin-left:-5px;
-moz-border-radius:20px;
-webkit-border-radius:20px;
border-radius:20px;
}
#timeline:after{
margin-left:-7px;
background:none;
border:7px solid #f43059;
border-color:#f43059 transparent transparent transparent;
width:0;
height:0;
top:auto;
bottom:-7px;
-moz-border-radius:0;
-webkit-border-radius:0;
border-radius:0;
}
Here we’ve created two empty pseudo-elements that are shaped like an arrow and a dot and then absolutely position them at the top and bottom of the ordered list. They sit over the top of the spine, giving the illusion of all being connected.
It’s worth saying that I’m not actually a fan of the border-arrow behaviour, but this is an experimental piece.
The branches
The branches that span between the list items and the spine are, again, pseudo elements. They are 70px wide and 1px high and have a gradient background which transitions from the colour of the spine to the colour of the list items. The CSS powering those is:
#timeline li:before,
#timeline li:after{
content:" ";
width:70px;
height:1px;
background:#f43059;
position:absolute;
left:100%;
top:50%;
background:-moz-linear-gradient(0,#d8d566,#f43059);
background:-webkit-gradient(linear,left top,right top,from(#d8d566),to(#f43059));
}
So by now we’ve added start and end points, a spine and branches to our timeline with no extra markup whatsoever. Lean!
Odd/even styling
The odd/even styling of each list item is achieved, as you might expect, using nth-of-type() selectors. What we do is move every even list item over the right of the <ol> and move its branch to attach to the spine accordingly:
#timeline li:nth-of-type(even){
float:right;
text-align:left;
}
#timeline li:nth-of-type(even):after{ /* Move branches */
background:-moz-linear-gradient(0,#f43059,#d8d566);
background:-webkit-gradient(linear,left top,right top,from(#f43059),to(#d8d566));
left:auto;
right:100%;
}
CSS feature detection?
This next bit I found quite cool, though a little unorthodox. I set the <li>s to have a negative margin-top so that they had a slightly overlapped effect on the timeline, so either side is not below the previous one, rather next to and slightly along-side it.
The problem I had here is that, in browsers that don’t support nth-of-type() selectors, the list items bunched up, each one slightly covering the previous one.
What I did was use this:
#timeline li:nth-of-type(odd),
#timeline li:nth-of-type(even){
margin:-10px 0 0 0;
}
Which basically says if the browser supports nth-of-type() selectors then give the list items a negative margin-top.
Any browsers that don’t support nth-of-type() selectors get the previously defined margin value for the list items, set here:
#timeline li{
position:relative;
clear:both;
float:left;
width:318px;
padding:10px;
background:#fef8c4;
border:1px solid #d8d566;
text-align:right;
margin:0 0 10px 0;
-moz-border-radius:2px;
-webkit-border-radius:2px;
border-radius:2px;
-moz-box-shadow:0 1px #fff inset;
-webkit-box-shadow:0 1px #fff inset;
box-shadow:0 1px #fff inset;
}
I guess you could call that a small kind of feature detection…?
However, whatever you call it, it means that IE8 users still get a pretty good experience, a linear, one column timeline with no nth-of-type() styling:

IE7 however doesn’t support pseudo-elements or nth-of-type() selectors, so they just get a single column list with no branches or dots/arrows but they do get a lonely spine…
Final word
So there we have it, a super lean, semantic and progressively styled timeline in HTML and CSS and one image. No doubt you could make a completely imageless solution, but I’m personally not one for this ‘never use images’ phase that the industry seems to be going through…
By Harry Roberts on Monday, March 14th, 2011 in Web Development. Tags: CSS, HTML, Semantics | 13 Comments »
+
Russell Heimlich said on 15 March, 2011 at 3:13 am
Dummyimage.com is a fan of the fantastic CSS Wizardry!
Ben said on 15 March, 2011 at 8:27 am
Hi Harry.
Brilliant article love the timeline project.
Would’nt it be more semantic as a definition list though?
Ben
Harry Roberts said on 15 March, 2011 at 9:03 am
Ben,
I see where you’re coming from, but I feel the order is the most important part about a timeline, so an
<ol>wins the most-appropriate-element Top Trumps for me!H
Ben said on 15 March, 2011 at 9:08 am
on second thoughts i do think your right ….. semantics are so cool.
Great work man :)
Greg Johnson said on 15 March, 2011 at 3:21 pm
You lost me when you were considering using
<b>sKimmo Linkama said on 15 March, 2011 at 8:09 pm
Hi Harry,
I just landed on your site from Twitter through someone’s link.
Your design looks great! I especially like the way you’re using position:fixed for your left-column menu, a much underutilised feature. I’m wondering about one thing, though: scrolling down the comments, the left-hand “marginalia” run over the menu. With JS enabled, the marginalia push the menu up out of sight. Am I just seeing this wrong in Windows/Firefox or is it intentional/accidental?
Harry Roberts said on 15 March, 2011 at 10:06 pm
Greg,
A
<b>would have been semantically correct… I’m not sure what you’re getting at…Kimmo,
This is intended behaviour. It allows me to utilise the space to the left for comments, but prevents them from being obtrusive through some JavaScript that @dan_bentley wrote.
bob marteal said on 16 March, 2011 at 1:59 pm
Harry,
This is really slick. I’m curious about the datetime attributes on some of the elements. Basically, why do some of the entries have the attribute while others don’t. The content all seems consistent, so would it be advisable to either include it on all items or not?
Thanks.
Klaus said on 16 March, 2011 at 4:24 pm
@Bob: it depends ;-)
Have a look at http://html5doctor.com/the-time-element/
Ben said on 17 March, 2011 at 12:01 pm
Hey Harry, Nice to see you going to DIBI Conf :) … hope to see you there!
Rene said on 19 March, 2011 at 1:34 am
Hey Harry,
Thanks for writing this up. I realize this is kind of newbie to ask, but I hope you could answer my question:
In the #timeline li:nth-of-type(even):after {} rules, why does “left: auto” need to be explicit if “right: 100%” was declared? I played with it in Firebug, but I don’t understand why that works.
Ben Palmer said on 22 August, 2011 at 11:18 am
Great idea, I was thinking of doing it as a definition list but an ordered list is probably the best thing to do.
Nice use of the time tag too, thanks!
Jimmy Pautz said on 25 January, 2012 at 2:21 pm
Very nice looking and functioning timeline! My only problem is that it doesn’t degrade well into older browsers (which you already know). I came up with my own solution, because I was making the timeline for my company’s history and we still have some people using IE7 (sadly). I wanted to give a relatively equal experience across browsers.
http://jamespautz.com/web/2011/12/pure-css-timeline/
It doesn’t do great in IE6, but I’ve given up on IE6 (Microsoft is even encouraging its death). It doesn’t work in IE7 and higher and is pretty semantic and easily stylable.