About this site's lack of design: Yes, it's supposed to look this way — I'm helping create a new sandbox theme for WordPress (see it on GitHub).

Dan Rubin's SuperfluousBanter

Suffering from chronic idiocy since 1977


Navigation Matrix

This method has been updated! See Nav­i­ga­tion Matrix Reloaded.

navigationIt’s been a while since I shared my last nav­i­ga­tion exper­i­ment. This new exper­i­ment is, as the first one, based exclu­sively on graph­ics — there­fore the same usabil­ity and acces­si­b­lity cau­tions apply. Unsur­pris­ingly, once CSS is dis­abled, a nice unordered list should remain. I prob­a­bly don’t need to explicitely men­tion that this exam­ple is con­structed using well-formed and seman­tic XHTML instead of tables. All the tabs work and are linked to 4 indi­vid­ual html pages (welcome.html, products.html, support.html and contact.html) that each load the same stylesheet.

How it works

At first this exam­ple might not seem very dif­fer­ent from other nav­i­ga­tion exper­i­ments. But the most inter­est­ing part is hid­den in the code and the method­ol­ogy. My exam­ple is called nav­i­ga­tion matrix because it actu­ally loads a matrix to dis­play the cor­rect graph­ics for the menu items. Below I included the image that is down­loaded — just once.


As you can see it con­tains all the dif­fer­ent states required for the nav­i­ga­tion to func­tion prop­erly. In essence it’s based on the method to shift back­ground posi­tions, which of course works faster than shift­ing indi­vid­ual images. By assign­ing a spe­cific id to each body tag in indi­vid­ual pages I can tar­get the list ele­ments and set their respec­tive back­grounds. The only thing I need to do is make sure that the back­ground is in the right posi­tion for each ele­ment. I use the above matrix to see what posi­tion I need.

Markup (welcome.html):

<body id="homepage">
<ul id="nav">
<li id="wel"><a xhref="welcome.html" mce_href="welcome.html">welcome</a></li>
<li id="pro"><a xhref="products.html" mce_href="products.html">products</a></li>
<li id="sup"><a xhref="support.html" mce_href="support.html">support</a></li>
<li id="con"><a xhref="contact.html" mce_href="contact.html">contact</a></li>


ul#nav {
position: relative;
margin: 0 auto 0 auto;
width: 650px;
padding: 0;
border: 5px solid #fff;
height: 120px;
background: #666 url(header.png) no-repeat left top;
list-style-type: none;

ul#nav li a {
position: absolute;
top: 68px;
width: 84px;
text-indent: -9000px;
text-decoration: none;
padding: 22px 0 0 0;
overflow: hidden;
height: 0px !important;
height /**/:22px; /* IE5/Win */
background: #666 url(nav_f.png) no-repeat;

body#welcome li#wel a {
background-position: 0 -44px; width: 94px; left: 188px;
body#welcome li#wel a:hover { background-position: 0 -44px; }
body#welcome li#pro a { background-position: -94px 0; left: 282px; }
body#welcome li#pro a:hover { background-position: -94px -22px; }
body#welcome li#sup a { background-position: -178px 0; left: 366px; }
body#welcome li#sup a:hover { background-position: -178px -22px; }
body#welcome li#con a { background-position: -262px 0; left: 450px; }
body#welcome li#con a:hover { background-position: -262px -22px; }

The markup itself is basi­cally just an unordered list with ids — noth­ing fancy. As men­tioned ear­lier I assign a spe­cific id to the body tag to make sure I can set dif­fer­ent back­grounds on dif­fer­ent pages. The CSS con­tains noth­ing really new either. For each list link, and respec­tive state, I deter­mine the cor­rect posi­tion of the back­ground image. Down­load the com­plete CSS file to have a closer look.


I showed this method to Dan and he told me he thought of a sim­i­lar method when Dan Ceder­holm was work­ing on the nav­i­ga­tion tabs for Fast Com­pany. To me the method mainly has advan­tages because it’s sim­ple and keeps the num­ber of graph­ics needed to a min­i­mum — all I really need to do is set the cor­rect posi­tion, top and left. But in the com­ments sec­tion of Sim­pleBits, Dan explains that there are more advan­tages than simplicity.

Hav­ing one graphic for nav­i­ga­tion also makes future changes eas­ier. Chang­ing col­ors will only require to edit one file. All in all this exam­ple is not rev­o­lu­tion­ary and does not show you any­thing new per se. How­ever it com­bines a few tricks that make this a fun and use­ful method.

This item was posted by Dan Rubin on Tuesday, May 4th, 2004.


You can follow comments on this item via the RSS 2.0 feed.

Comments are closed.

36 comments on “Navigation Matrix”

  1. Posted by James on Tuesday, May 4th, 2004.


    Another great post! I’ve been work­ing on the exact same tech­nique for my site for about the past week. Great to see that I’m on the right track with my design.


  2. Posted by JP on Tuesday, May 4th, 2004.

    I noticed yes­ter­day that Zeld­man uses this tech­nique for his nav bar (sans tabs). It’s great that you only need one image for the whole setup–much eas­ier to manage.

  3. Posted by Michele on Tuesday, May 4th, 2004.

    Very nice indeed, Didier!

    In Fire­fox 0.8/Win, if you click on one of the tabs and then you drag your mouse down, the orig­i­nal text of the link appears. A quick fix could be:

    ul#nav li a {

    text-indent: –1000em;

    text-decoration: none;


    That should push the text well out of the way.

  4. Posted by Dan Cederholm on Tuesday, May 4th, 2004.

    Beau­ti­fully done. Inter­est­ingly I was play­ing around with over­lap­ping tabs like this recently — using one image for all the pos­si­ble com­bi­na­tions is the best approach. Oth­er­wise, you’ll have to chop up each end where the tabs over­lap, and another set for when tab is selected to appear “in front”. Keep­ing all the pos­si­bil­i­ties in one sin­gle file, like Didier has done is so much eas­ier. Nice work.

  5. Posted by Brian on Tuesday, May 4th, 2004.

    Why do you need the bot­tom two rows of tabs, the –66px and –88px?

  6. Posted by andrew on Tuesday, May 4th, 2004.

    So is this basi­cally using tabs w/ body id’s in com­bi­na­tion with Dave Shea’s CSS Sprites navigation?

  7. Posted by Keith on Tuesday, May 4th, 2004.

    Very nice exam­ple and good work on the expla­na­tion, it’s very easy to fol­low. Thanks for shar­ing Didier.

  8. Posted by Nick on Tuesday, May 4th, 2004.

    That’s all and good but has one major flaw in that blind users who rely on such pro­grams as Jaws (Free­dom Sci­en­tific) to nav­i­gate the site will not be able to do so. I think the ALT= field might be read instead so it might be pos­si­ble but I don’t have con­ve­nient access to JAWS to test the the­ory out. Granted this is a very tiny pop­u­lace of the world wide web I don’t think your tech­nique would be good if those peo­ple were poten­tial visitors/users.

  9. Posted by Craig on Tuesday, May 4th, 2004.

    Great explanan­tion Didier, maybe we will even see it used in site some­time soon ;-)

  10. Posted by eric on Tuesday, May 4th, 2004.

    Nick, Didier is replac­ing his links with back­ground images, when read by some­thing like JAWS it should ren­der as an ordered list, as he said. There’s noth­ing in his code that he can apply an alt=”” field to.

  11. Posted by Zelnox on Tuesday, May 4th, 2004.

    Amaz­ing (^_^)//

  12. Posted by Bruce Boughton on Tuesday, May 4th, 2004.

    I’ve been using this tech­nique for ages, in mock-ups at least. To me it seems the best tech­nique for image based nav­i­ga­tion menus since it elim­i­nates the delay between load­ing the mouseover image with­out any com­pli­cated JS pre-loading. It can take some fid­dling to get right, depend­ing on con­text but it’s pretty easy once you get your head round. It’s nice to see it show­cased in such a clear manner.

  13. Posted by Josh Williams on Tuesday, May 4th, 2004.

    Um yeah, this is killer.

    We worked a sim­i­lar tech­nique while build­ing an inter­face for a mobile device appli­ca­tion. Only it involved a sin­gle “matrix” image (we called it the same thing) that also included the back­ground image as well.

    All the graph­ics for the entire appli­ca­tion were placed in the sin­gle PNG file, then lay­ered on top of each other in real­time by the Java app.

    That said, what you have done is awe­some… espe­cially using the BODY ID to repo­si­tion the inac­tive tabs as well. So cool.

  14. Posted by Josh Williams on Tuesday, May 4th, 2004.

    Did I men­tion this was killer?

  15. Posted by Jon Hicks on Tuesday, May 4th, 2004.

    I’ve been using a sim­i­lar method recently (not with all images in one file — I wish I’d thought of that!), but have a prob­lem with flicker in IE 6. Its only a sec­ond or so, but its bad enough to look unacceptable.

    To get round it, I had to apply the rollover state to the back­ground of the <li> and set the background-image in the <a> tag to none. It still uses the same image file. Have you come across this prob­lem with this method?

  16. Posted by Alex Weber on Tuesday, May 4th, 2004.

    not really new, but very nice and very cool

    bye alex

  17. Posted by Ireney Berezniak on Tuesday, May 4th, 2004.

    Great post indeed! I love the cre­ative use of the CSS. Fine method to main­tain access­abil­ity while treat­ing with eye­candy at the same time! I’ll be sure to “steal” this tech­nique for my own use >8P


  18. Posted by justin on Tuesday, May 4th, 2004.

    If I’d known that I was going to be view­ing such beauty, I would have put on a dia­per. Sim­ply lickable!

  19. Posted by Tony Crockford on Tuesday, May 4th, 2004.

    the first time I looked at the exam­ple in Opera 7.5beta1 the tabs didn’t show up in the nor­mal state and only appeared on rollover.

    a ctrl refresh sent them away again…

    thought you’d like to know.


  20. Posted by Didier Hilhorst on Tuesday, May 4th, 2004.

    First of all I’d like to thank every­one for the very kind and encour­ag­ing words. This method cer­tainly has some flaws and there’s defin­i­tively room for improve­ment. I’ll address some of the indi­vid­ual remarks and com­m­ments below. Michele — Thanks for point­ing that out. It’s a bit of an odd thing really, but I tested it and it hap­pens indeed. Isn’t code a won­der­ful thing? I’ll update the stylesheet soon.Brian — I need the bot­tom two rows (-66px and –88px) because on the active state the tabs over­lap other sec­tions, i.e. the gray col­ored active tabs are actu­ally wider than the width of the list ele­ment (visu­ally). To make sure it looks good, and cor­rect, the remain­ing parts of the image are included in adje­cent ele­ments. Down­load all the files and play with the back­ground posi­tions in the CSS file and you will see why they are needed.Andrew — That’s an inter­est­ing view on the mat­ter. I think you are right to make the anal­ogy and link the var­i­ous meth­ods, although I did not specif­i­cally look at these two arti­cles at the time I cre­ated this exam­ple. Of course I based my work on knowl­edge posted by oth­ers, includ­ing Dave, Dan and Dou­glas.Nick — This exam­ple inher­its the prob­lems inher­ent to the FIR (and sim­i­lar) meth­ods: when stylesheets are enabled and images dis­abled the nav­i­ga­tion will not work, i.e. users will not see any­thing. How­ever, none of the con­tent is actu­ally hid­den or not dis­played , so to my knowl­edge blind users work­ing with JAWS should be able to use the nav­i­ga­tion. How­ever it would be nice to have a con­fir­ma­tion on that, if pos­si­ble.Jon — The damn flick­er­ing is some­thing the IE team should fix, hon­est, too many design­ers are suf­fer­ing from this obvi­ous flaw. That said the flick­er­ing in IE6 will only occur in one instance. IE6 has an assort­ment of options to check for newer ver­sions of stored pages, that are located under Tools » Inter­net Options… » Tem­po­rary Inter­net Files » Set­tings. In that list you can choose between:Every visit to the pageEv­ery time you start Inter­net Explor­erAuto­mat­i­cal­lyN­ev­er­The auto­mat­i­cally option is checked by default. Most design­ers set this option to every visit to the page to make sure they’re not view­ing a cached ver­sion (when test­ing). When the lat­ter set­ting is used it will flicker no mat­ter what you try, IE6 will load the image again each time you hover, and thus result in flick­er­ing, unfor­tu­nately set­ting a back­ground image the the list ele­ment itself does not solve the prob­lem. But my guess is that just a small per­cent­age is using these set­tings (it just hap­pens to be the small per­cent­age look­ing at this and other exam­ples, prob­a­bly.) With all the other set­tings no flick­er­ing occurs, to my knowl­edge.Tony — That’s an odd prob­lem. No such thing hap­pens in my ver­sion of Opera (7.03). Nor­mally it shouldn’t occur in Opera 7.5 Beta 1 either. The image is down­loaded once. The only thing that hap­pens in the hover state is the change in back­ground posi­tion. I have no exple­na­tion for the prob­lem except that the image didn’t load cor­rectly the first time around (due to an unknown reason.)

  21. Posted by Bruno on Tuesday, May 4th, 2004.

    Didier, thanks for shar­ing your exper­i­ments wth us! Visu­ally the result his awe­some. Unfor­tu­nately, it isn’t IE 5.x Mac friend due — I think — to the browser CSS posi­tion related bugs. Have you check it out?

  22. Posted by Andrei Herasimchuk on Tuesday, May 4th, 2004.

    Why is any­one using Mac IE 5 any­more? Dump it? Safari is far bet­ter and free. If you are using OS 9 with Mac IE 5… well… if one wants to live in the dark ages (in com­put­ing time), then I think designer’s should just let them stay there. 8^)

    Nice job D.

  23. Posted by Bart N. on Wednesday, May 5th, 2004.

    That’s some sweet navigation !

  24. Posted by Didier Hilhorst on Wednesday, May 5th, 2004.

    Bruno — I’m afraid I will have to agree with Andrei regard­ing sup­port for IE5.x for Mac. Just a small frac­tion of users browse the web using IE5.x for Mac and I think it’s not worth the effort and trou­ble to hack my way around to sup­port that browser.

    That said if any­one has a quick fix that doesn’t require a zil­lion hacks I’m all ears. The more that is sup­ported the bet­ter obvi­ously. But at a cer­tain point it’s not worth the effort.

  25. Posted by Susanna on Wednesday, May 5th, 2004.

    For more infor­ma­tion on this tech­nique, read the arti­cle “CSS Sprites: Image Slicing’s Kiss of Death” in A List Apart: http://www.alistapart.com/articles/sprites/

  26. Posted by Kris on Thursday, May 6th, 2004.

    Though it is a great tech­nique, Dan’s method has a major acces­si­bil­ity flaw and is not so much, as he states, ‘acces­si­ble’. Being able to be read by screen­read­ers is only part of the story. Turn­ing image-loading off in a graph­i­cal desktop-browser is all that is needed to ren­der the menu inaccessible.

    Until this issue is resolved, I will not use CSS-IR for crit­i­cal site functionality.

  27. Posted by Kris on Thursday, May 6th, 2004.

    Didier, I recall an arti­cle on ALA, pos­si­bly writ­ten by Dou­glas Bow­man, in which a float­ing bug in IE/mac is addressed; when both the ele­ment and the con­tent of that ele­ment are floated, IE/Mac sud­denly behaves prop­erly on adjust­ing the width of the element.

    I don’t remem­ber which arti­cle it was, but I am sure it is easy enough to find.

  28. Posted by James Holbeach on Saturday, May 8th, 2004.

    Hi DH, firstly a very clever solu­tion to a prob­lem I’ve been think­ing about for some time. How­ever, as with Jon, the flicker in IE makes it unac­cept­able (note in Moz it works BEAUTIFULLY!).

    I tried chang­ing my set­tings back to auto­mat­i­cally, reloaded the browser, but the flicker was still there, no mat­ter what I did?

  29. Posted by Didier Hilhorst on Saturday, May 8th, 2004.

    Kris — You are absolutely right, and I noted exactly this in my reply to Nicks\‘s com­ment. But per­son­ally I find that the pos­si­bil­ity of users brows­ing with images turned off and CSS turned on is rather an excep­tion. How­ever I do not have any data to back this state­ment up. It would be inter­est­ing to know what per­cent­age is using these par­tic­u­lar set­tings. I know it is usu­ally done to improve down­load speeds etc. I think CSS-IR has its place in real world web design, and I don\‘t think we should avoid this method just because there\‘s a pos­si­bil­ity of it not work­ing prop­erly. As far as IE/Mac is con­cerned I think my updated ver­sion solved some issues, but I did not check that myself.

    James — Please see Nav­i­ga­tion Matrix Reloaded for an updated ver­sion of this method, which effec­tively solves the flick­er­ing issue in IE6.

  30. Posted by Bob Easton on Saturday, May 8th, 2004.

    Regard­ing acces­si­bil­ity by screen read­ers: both Jaws 5 and Home Page Reader 4 do just fine with this exper­i­ment. Con­firmed by actual test­ing. They both read the text links exactly as pre­sented in the HTML. The images are com­pletely irrel­e­vant as they are back­ground images, and the screen read­ers don’t even know they exist.

    Unlike the image replace­ment tech­niques which often use display:none to hide the text, this tech­nique leaves the text avail­able to screen readers.The tech­nique is much more acces­si­ble than some image replace­ment methods.

    Very nice job Didier!

  31. Posted by Jim on Sunday, May 9th, 2004.

    I picked up on this method after read­ing Dave Shea’s arti­cle ‘CSS Sprites’ over at ALA.

  32. Posted by Bryan on Sunday, May 9th, 2004.

    This is a great idea and method. It allows for the oppor­tu­nity to cre­ate a sim­i­lar flash nav­i­ga­tion where you don’t have to worry about pre­load­ing the image rollovers. I just cre­ated an exam­ple that would be some­thing like what I would see in a flash nav­i­ga­tion. Any­ways, let me know what you guys think. Its just an ani­mated gif.



  33. Posted by esz on Monday, May 10th, 2004.

    very inter­est­ing idea ~~~!

  34. Posted by stan on Friday, May 21st, 2004.

    I hate to be a hare­bringer of bad news but over­all there are still prob­lems with this solu­tion in ie 5.x for mac. The nav does not line up.

    ie does funny things when you try to line things up lots of times.


  35. Posted by Mike on Monday, July 26th, 2004.

    I’ll be try­ing this for sure. Tab­strips with over­lap­ping tabs can be seri­ously con­fus­ing. But, I am build­ing a server­side scripted app (php), so I’m not about the matrix. Should i just include all pos­si­ble tabs in the matrix, even though users might not even see some of the tabs (due to the rights­man­age­ment). Any­way, I’ll see if I can get it to work.

  36. Posted by Mike on Monday, July 26th, 2004.

    Oh, and I think Blog­ger uses it too (on the CMS part where users edit their weblog), I was really con­fused when I saw their matrix, but now I under­stand how it works!