Fluid CSS Menus and Sub-Pixel Workaround

By , 28 January 2009

Fluid CSS Menus and Sub-Pixel Workaround

A long standing CSS problem, best described by John Resig in his blog, is the different approach browsers use when rounding widths calculated from percentages. Firefox rounds alternately up and down in order to make elements fit perfectly, Opera and Safari always round down so that elements will never overflow the container, and Internet Explorer always rounds up so elements often overflow their container and developers get to practise using profanities.

My use case is a fluid css menu with no gaps between the elements or at the end. If you don't know how to build css menus you might want to start by reading my blog on css menus. CSS menus are useful because they are built with <ul> and <li> markup which is a natural representation for hierarchies. The problem is that since menu items are floated, using percentage widths does not guarantee the space will used perfectly (unlike tables).

The basic concept behind the workaround is to leave the last element of the list unfloated so it occupies the entire width of the menu bar underneath the floated elements. Essentially the last item has the following style:

.web_cssMenu li.web_last { float: none; width: auto; }
Fluid CSS Menus and Sub-Pixel Workaround

There are, as you might expect, a few issues with this idea:

  • Standards-compliant browsers stack the last item above the floated ones.
  • IE6 and IE7 have to be put in hasLayout() mode to rendered the last item as a block.
  • IE6 makes a gap between the last two items because of its three pixel gap defect.
  • As the width of the last item is essentially 100%, you have to be more careful about background styles.

Most of these problems can all be resolved with a little additional styling. The 3px gap can be fixed by adding a negative margin to the second last element, but this fix makes more code pollution and is not really worth applying. The complete set of changes are then:

.web_cssMenu li { z-index: 2; background: inherit; }
.web_cssMenu li.web_last { float: none; width: auto; z-index: 1; }

Of course you need the rest of the css menus styles to get a complete picture of what I'm talking about:

View a complete example of my Fluid CSS Menus and Sub-Pixel Workaround.

There are other problems with floated elements (e.g. heights), but hopefully this is trick will solve a problem for you until something better comes along.

About Roger Keays

Fluid CSS Menus and Sub-Pixel Workaround

I guess I'd call myself a problem solver. Either that, or I'm some sort of organic machine designed to convert oxygen into carbon dioxide. You could go either way on that. I'm into languages and stuff. I wrote a book. It's okay, I guess. What else? I like reading, swimming, eating, and playing music. Satisfied? Sheesh.

Leave a Comment

Please visit https://rogerkeays.com/blog/fluid-css-menus-and-sub-pixel-workaround to add your comments.

Comment posted by: , 8 years ago

IE6? Woah... could be anything. My approach to tackling IE defects is generally to try adding zoom: 1; or position: relative; at random to various elements until it works. Swearing also seems to help sometimes.

Comment posted by: Vasyl Mosiychuk, 8 years ago

In IE6, when I bring the cursor to the menu item (link hover) then the entire menu unit moves in the left on 1-2 px. How can I fix this?