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

Dan Rubin's SuperfluousBanter

Design, random musings, and the Web. Since 1977


Navigation Matrix

This method has been updated! See Navigation Matrix Reloaded.

navigationIt’s been a while since I shared my last navigation experiment. This new experiment is, as the first one, based exclusively on graphics — therefore the same usability and accessiblity cautions apply. Unsurprisingly, once CSS is disabled, a nice unordered list should remain. I probably don’t need to explicitely mention that this example is constructed using well-formed and semantic XHTML instead of tables. All the tabs work and are linked to 4 individual html pages (welcome.html, products.html, support.html and contact.html) that each load the same stylesheet.

How it works

At first this example might not seem very different from other navigation experiments. But the most interesting part is hidden in the code and the methodology. My example is called navigation matrix because it actually loads a matrix to display the correct graphics for the menu items. Below I included the image that is downloaded — just once.


As you can see it contains all the different states required for the navigation to function properly. In essence it’s based on the method to shift background positions, which of course works faster than shifting individual images. By assigning a specific id to each body tag in individual pages I can target the list elements and set their respective backgrounds. The only thing I need to do is make sure that the background is in the right position for each element. I use the above matrix to see what position 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 basically just an unordered list with ids — nothing fancy. As mentioned earlier I assign a specific id to the body tag to make sure I can set different backgrounds on different pages. The CSS contains nothing really new either. For each list link, and respective state, I determine the correct position of the background image. Download the complete CSS file to have a closer look.


I showed this method to Dan and he told me he thought of a similar method when Dan Cederholm was working on the navigation tabs for Fast Company. To me the method mainly has advantages because it’s simple and keeps the number of graphics needed to a minimum — all I really need to do is set the correct position, top and left. But in the comments section of SimpleBits, Dan explains that there are more advantages than simplicity.

Having one graphic for navigation also makes future changes easier. Changing colors will only require to edit one file. All in all this example is not revolutionary and does not show you anything new per se. However it combines a few tricks that make this a fun and useful 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 working on the exact same technique 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 yesterday that Zeldman uses this technique for his nav bar (sans tabs). It’s great that you only need one image for the whole setup–much easier to manage.

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

    Very nice indeed, Didier!

    In Firefox 0.8/Win, if you click on one of the tabs and then you drag your mouse down, the original 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.

    Beautifully done. Interestingly I was playing around with overlapping tabs like this recently — using one image for all the possible combinations is the best approach. Otherwise, you’ll have to chop up each end where the tabs overlap, and another set for when tab is selected to appear “in front”. Keeping all the possibilities in one single file, like Didier has done is so much easier. Nice work.

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

    Why do you need the bottom two rows of tabs, the -66px and -88px?

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

    So is this basically using tabs w/ body id’s in combination with Dave Shea’s CSS Sprites navigation?

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

    Very nice example and good work on the explanation, it’s very easy to follow. Thanks for sharing 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 programs as Jaws (Freedom Scientific) to navigate the site will not be able to do so. I think the ALT= field might be read instead so it might be possible but I don’t have convenient access to JAWS to test the theory out. Granted this is a very tiny populace of the world wide web I don’t think your technique would be good if those people were potential visitors/users.

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

    Great explanantion Didier, maybe we will even see it used in site sometime soon ;-)

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

    Nick, Didier is replacing his links with background images, when read by something like JAWS it should render as an ordered list, as he said. There’s nothing in his code that he can apply an alt=”” field to.

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

    Amazing (^_^)//

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

    I’ve been using this technique for ages, in mock-ups at least. To me it seems the best technique for image based navigation menus since it eliminates the delay between loading the mouseover image without any complicated JS pre-loading. It can take some fiddling to get right, depending on context but it’s pretty easy once you get your head round. It’s nice to see it showcased in such a clear manner.

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

    Um yeah, this is killer.

    We worked a similar technique while building an interface for a mobile device application. Only it involved a single “matrix” image (we called it the same thing) that also included the background image as well.

    All the graphics for the entire application were placed in the single PNG file, then layered on top of each other in realtime by the Java app.

    That said, what you have done is awesome… especially using the BODY ID to reposition the inactive tabs as well. So cool.

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

    Did I mention this was killer?

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

    I’ve been using a similar method recently (not with all images in one file – I wish I’d thought of that!), but have a problem with flicker in IE 6. Its only a second or so, but its bad enough to look unacceptable.

    To get round it, I had to apply the rollover state to the background 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 problem 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 creative use of the CSS. Fine method to maintain accessability while treating with eyecandy at the same time! I’ll be sure to “steal” this technique for my own use >8P


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

    If I’d known that I was going to be viewing such beauty, I would have put on a diaper. Simply lickable!

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

    the first time I looked at the example in Opera 7.5beta1 the tabs didn’t show up in the normal 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 everyone for the very kind and encouraging words. This method certainly has some flaws and there’s definitively room for improvement. I’ll address some of the individual remarks and commments below. Michele — Thanks for pointing that out. It’s a bit of an odd thing really, but I tested it and it happens indeed. Isn’t code a wonderful thing? I’ll update the stylesheet soon.Brian — I need the bottom two rows (-66px and -88px) because on the active state the tabs overlap other sections, i.e. the gray colored active tabs are actually wider than the width of the list element (visually). To make sure it looks good, and correct, the remaining parts of the image are included in adjecent elements. Download all the files and play with the background positions in the CSS file and you will see why they are needed.Andrew — That’s an interesting view on the matter. I think you are right to make the analogy and link the various methods, although I did not specifically look at these two articles at the time I created this example. Of course I based my work on knowledge posted by others, including Dave, Dan and Douglas.Nick — This example inherits the problems inherent to the FIR (and similar) methods: when stylesheets are enabled and images disabled the navigation will not work, i.e. users will not see anything. However, none of the content is actually hidden or not displayed , so to my knowledge blind users working with JAWS should be able to use the navigation. However it would be nice to have a confirmation on that, if possible.Jon — The damn flickering is something the IE team should fix, honest, too many designers are suffering from this obvious flaw. That said the flickering in IE6 will only occur in one instance. IE6 has an assortment of options to check for newer versions of stored pages, that are located under Tools » Internet Options… » Temporary Internet Files » Settings. In that list you can choose between:Every visit to the pageEvery time you start Internet ExplorerAutomaticallyNeverThe automatically option is checked by default. Most designers set this option to every visit to the page to make sure they’re not viewing a cached version (when testing). When the latter setting is used it will flicker no matter what you try, IE6 will load the image again each time you hover, and thus result in flickering, unfortunately setting a background image the the list element itself does not solve the problem. But my guess is that just a small percentage is using these settings (it just happens to be the small percentage looking at this and other examples, probably.) With all the other settings no flickering occurs, to my knowledge.Tony — That’s an odd problem. No such thing happens in my version of Opera (7.03). Normally it shouldn’t occur in Opera 7.5 Beta 1 either. The image is downloaded once. The only thing that happens in the hover state is the change in background position. I have no explenation for the problem except that the image didn’t load correctly the first time around (due to an unknown reason.)

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

    Didier, thanks for sharing your experiments wth us! Visually the result his awesome. Unfortunately, it isn’t IE 5.x Mac friend due – I think – to the browser CSS position related bugs. Have you check it out?

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

    Why is anyone using Mac IE 5 anymore? Dump it? Safari is far better and free. If you are using OS 9 with Mac IE 5… well… if one wants to live in the dark ages (in computing 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 regarding support for IE5.x for Mac. Just a small fraction of users browse the web using IE5.x for Mac and I think it’s not worth the effort and trouble to hack my way around to support that browser.

    That said if anyone has a quick fix that doesn’t require a zillion hacks I’m all ears. The more that is supported the better obviously. But at a certain point it’s not worth the effort.

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

    For more information on this technique, read the article “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 technique, Dan’s method has a major accessibility flaw and is not so much, as he states, ‘accessible’. Being able to be read by screenreaders is only part of the story. Turning image-loading off in a graphical desktop-browser is all that is needed to render the menu inaccessible.

    Until this issue is resolved, I will not use CSS-IR for critical site functionality.

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

    Didier, I recall an article on ALA, possibly written by Douglas Bowman, in which a floating bug in IE/mac is addressed; when both the element and the content of that element are floated, IE/Mac suddenly behaves properly on adjusting the width of the element.

    I don’t remember which article 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 solution to a problem I’ve been thinking about for some time. However, as with Jon, the flicker in IE makes it unacceptable (note in Moz it works BEAUTIFULLY!).

    I tried changing my settings back to automatically, reloaded the browser, but the flicker was still there, no matter 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 comment. But personally I find that the possibility of users browsing with images turned off and CSS turned on is rather an exception. However I do not have any data to back this statement up. It would be interesting to know what percentage is using these particular settings. I know it is usually done to improve download 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 possibility of it not working properly. As far as IE/Mac is concerned I think my updated version solved some issues, but I did not check that myself.

    James — Please see Navigation Matrix Reloaded for an updated version of this method, which effectively solves the flickering issue in IE6.

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

    Regarding accessibility by screen readers: both Jaws 5 and Home Page Reader 4 do just fine with this experiment. Confirmed by actual testing. They both read the text links exactly as presented in the HTML. The images are completely irrelevant as they are background images, and the screen readers don’t even know they exist.

    Unlike the image replacement techniques which often use display:none to hide the text, this technique leaves the text available to screen readers.The technique is much more accessible than some image replacement methods.

    Very nice job Didier!

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

    I picked up on this method after reading Dave Shea’s article ‘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 opportunity to create a similar flash navigation where you don’t have to worry about preloading the image rollovers. I just created an example that would be something like what I would see in a flash navigation. Anyways, let me know what you guys think. Its just an animated gif.



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

    very interesting idea ~~~!

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

    I hate to be a harebringer of bad news but overall there are still problems with this solution 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 trying this for sure. Tabstrips with overlapping tabs can be seriously confusing. But, I am building a serverside scripted app (php), so I’m not about the matrix. Should i just include all possible tabs in the matrix, even though users might not even see some of the tabs (due to the rightsmanagement). Anyway, I’ll see if I can get it to work.

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

    Oh, and I think Blogger uses it too (on the CMS part where users edit their weblog), I was really confused when I saw their matrix, but now I understand how it works!