Liquid horizontal menu with equal gap between items

Please, look at the scheme:

I want to make liquid horisontal menu like on the scheme with equal gaps between menu items. It is better if it will be unsorted list. But elegant table solution is also welcome.

Don’t hurry with answer, i already worked on this question a lot of time and have found only the following solutions — i have made it using small JS-programming and unsorted list (with recalculating gaps when resize window and text size) and (second solution) with table:


<table width="80&#37;">
	<tr>
		<td width="1%" nowrap>short</td>
		<td></td>
		<td width="1%" nowrap>much longer item</td>
		<td></td>
		<td width="1%" nowrap>middle length</td>
		<td></td>
		<td width="1%" nowrap>foobar</td>
	</tr>
</table>

But I don’t like both solutions, because it is not elegant and also using table menu long items (with several words) will not be able to wrap when it will need.

So, any ideas?
Thank you.

Maybe this example can be of use. :slight_smile:

The menu list-items can also have different share of the total width.

No, your example demonstrates menu with the same items width in percents. It is not what I need.

The total width can be divided with different amounts according to the items different content. The gap difference between different items in change of the total width will probably be one or two pixels I guess.

The alternative to a fluid solution in percent I think will most likely be a table solution. :slight_smile:

Hi -
I’ve done something similar by just using centered text for the ul - with no padding or margins, displaying the li’s inline w/ set padding in px or em - and margin:0 auto;.

Good luck,
El

Just to practice I adjusted the example to your menu conditions. :slight_smile:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<title>Flexible Site Equal Gap Horizontal Menu</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
* { margin:0; padding:0; }
body {
	text-align: center;
	background: #333;
}
#pagewrapper {
	margin: 10px auto 0;
	max-width: 1200px;
	min-width: 600px;
	padding: 10px;
	background: wheat;
}
* html #pagewrapper {
	width: 760px;
}
#header {
	margin: 0 0 4px;
	height: 80px;
	background: #333;
}
#nav {
	margin: 0 auto;
	width: 80&#37;;
	height: 3em;           /* set height to same length as the list not to vertical overflow it */
	overflow: hidden;	     /* hide the not allowed to wrap last list-item's odd pixels overflow */
	font: bold 85%/3em arial;
	text-align: center;
	background: #333;
}
#navlist {               /* (navlist is of width 100% of parent width) */
	list-style: none;
}
#navlist li#a {
	float: left;
	width: 17%;            /* set li widths value to percent-share (N.b. Opera will not read decimal) */
}
#navlist li#b {
	float: left;
	width: 37%;
}
#navlist li#c {
	float: left;
	width: 27%;
}
#navlist li#d {
	float: left;
	width: 19%;
	margin-right: -10px;   /* safely stop the list from wrapping when computed odd pixels are added */
}
#navlist li a {
	display:block;
	height: 3em;		       /* IE<7 needs a height value to fill the box*/
	color: #FFF;
	text-decoration: none;
}
#navlist li a:hover {
	background: #555;
}
#contentwrapper {
	margin-top: 5px;
	height: 600px;
	background: #CCC;
}
</style>
</head>
<body>
<div id="pagewrapper">
	<div id="header"></div>
	<div id="nav">
		<ul id="navlist">
			<li id="a"><a href="#">short</a></li>
			<li id="b"><a href="#">very much longer item</a></li>
			<li id="c"><a href="#">middle length</a></li>
			<li id="d"><a href="#">foobar</a></li>
		</ul>
	</div>
<div id="contentwrapper"></div>
</div>
</body>
</html>

Sorry, but manual adjusting width of each list item is not style of good CSS-geek ). What about text changing of or amount of items changing?

A fluid 80% wide menu with equal gaps between items, and items content is changing, not only text-size. Ok, I’ll give it a try. :slight_smile:

But the number of items isn’t changing, or is it? :rolleyes:

Text size, content, amount of items can change. Assume, that this is site menu and you don’t know, how many items menu will contain. Any solution need to be universal and work in any environment.

That’s tough, but interesting. :slight_smile:

I assume it must be centered too, but does the menu page have a minimum width? - Edit) Right, any environment. Edit2) I don’t think I can focus on this for a while. :frowning:

I think that it is impossible in fact. I have rich experience in HTML&CSS, but even after 3 projects with such menus and after about 30 hours devoted to this problem — i don’t know, how to do it by using only semantic HTML&CSS (without JavaScript).

Here is demonstrating, what I need (I use JS to achieve such effect):
http://ruban.in.ua/menu/

PS: Above I have wrote, that there is solution using table. I am sorry, that solution works not very correct.

I tryed a table solution in IE and it seems to work (in IE). Not working the same in good browsers. Don’t know yet if a table solution is good. :wink:

Here is the code for IE:

<!DOCTYPE html PUBtdC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Flexible Menubar Table Test IE</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="generator" content="PSPad editor, www.pspad.com">
<style type="text/css">
body {
	text-align: center;
}
table{
	margin: 0 auto;
	width: 80&#37;;
	border-collapse: collapse;
}
table td{
	width: 0%;           /* 0% seems to do the trick in IE5-7 */
	padding: 0 1em;
}
table td a{
	display: block;
	height:2.5em;
	font: bold medium/2.5em arial;
	text-decoration:none;
	white-space: nowrap;
	color:black;
	background: #9F9;
}
table td a:hover{
	background: #FF9;
}
</style>
</head>
<body>
	<table>
		<tr>
			<td><a href="#">short</a></td>
			<td><a href="#">very much longer item</a></td>
			<td><a href="#">middle length</a></td>
			<td><a href="#">add</a></td>
			<td><a href="#">foobar</a></td>
		</tr>
	</table>
</body>
</html>

It works neither in FF nor in Safari (I can’t test in IE now). Sorry. Please, propose only solutions, which will work stable anywhere.

:slight_smile: Please test this version on Mac and Safari in part. On my WinXP I have achieved, I think, what you requested in all my browsers, (except Safari which is instantly crashing when I try to open the browser :frowning: )

<!DOCTYPE html PUBtdC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Flexible Menubar Table Test All?</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="PSPad editor, www.pspad.com" />
<style type="text/css">
*{
	margin:0;
	padding:0;
}
body {
	width: 100&#37;;
	text-align: center;
}
table{
	margin: 0 auto;
	width: 80%;
	border-collapse: collapse;
}
table td{
	width: 1000pt;          /* I'm still investigating how this method is functioning according to how I thought it would */
	background:#F99;
	text-align: center;
	border: 1px solid #999;
}
table td a{
	display: block;
	height:2.5em;
	font: bold medium/2.5em arial;
	text-decoration:none;
	white-space: nowrap;
	color:black;
	background: #9F9;
}
table td a:hover{
	background: #FF9;
}
</style>
</head>
<body>
	<table summary="">
		<tr>
			<td><a href="#">short</a></td>
			<td><a href="#">very much longer item</a></td>
			<td><a href="#">middle length</a></td>
			<td><a href="#">add</a></td>
			<td><a href="#">foobar</a></td>
		</tr>
	</table>
</body>
</html>

I think I have a table solution. :slight_smile: Explaining the idea behind it is the hard part, but to make it simple:

Starting with some random tests to see how the browser computed table widths I used IE7. In some cases the browser ignored the setting, in other cases it went for equal widths, most times it applied the content width for each cell. But when the cell width was set to zero percent IE actually gave the columns equal pixel amount besides the content width. IE did prove it could be done!

Reading the w3.org table specs I realized that the browser can apply different algoritms for column width when total width is set. During this I got the idea to try to make the browser go an extra pass computing the width.

If the column-width is not set the browser tries to apply the fixed table layout algoritm. That means it will only give extra width to cells if the content needs it.

If the table width is not set the cell content defines the column width. First pass for the cells the minimum width for each column is computed, that gives the table width.

If the table width is set from start the browser computes both minimum and maximum cell-width. Then if total width is greater then minimum total, it must decide where to put the extra pixels.

Here was an opportunity to “negotiate” and that gave me the idea to set the cell width to a length that the browser couldn’t fit. In that case the content gives the minimum cell width and the width-setting requires an equal width, then hopefully the browser would equally spread the extra pixels over the number of cells.

Different browser engines applies the same specifications but have freedom how to get the result. Testing the major engines showed that with the table total width set:

If the column width was set with a possible length, in adding width browsers gave priority to narrow columns.

If the column width was set very extreme some browsers tried to give first cell an extrem width, and failed to set the total width. In other cases the auto layout was applied with shrinked cells.

If the column width was e.g. screen wide, the desired pass was happening. The browser distributed the extra pixels equally to each column. If the content needed more than total width, the specs was followed and total width increased.

NB. If the cell content is allowed to wrap, the browser tries to apply equal column widths.

Then followed testing in browsers using Trident, Gecko, Presto, WebKit, KHTML-engines. Based on that I have found this safe column-width settings: 2000pt or 200pc or 30in or 75cm/750mm. This are all fixed units to avoid any extreme em or ex values. Percent is not wise to use in this case, it is disturbing the calculation I think.

Finally the test code:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<title>Fluid Table Menu With Equally Distributed Extra Total Width</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="generator" content="PSPad editor, www.pspad.com">
<style type="text/css">

/* (for Trident, Gecko, Presto, WebKit, KHTML, appropriate table-cell width settings are 2000pt/200pc/30in/75cm) */

/* please help to do more extensive fluid-flexible tests, add items, play with rules, try floats and positioning */

* {margin:0;padding:0}

body {
    width:100&#37;;
    text-align: center;
}
table {
    margin: 0 auto;
    width: 80%;
    border-collapse: collapse;
}
table td {
    width: 2000pt;    /* 2000pt = oversized cell-width for equal distribution over columns of extra table-width */
    border: 1px solid #999;
    text-align: center;
    background: #F99;
}
table td a {
    display: block;
    height: 2.5em;
    font: bold medium/2.5em arial;
    text-decoration: none;
    white-space: nowrap;    /* this rule need to be to avoid item to wrap, if so, all columns being equally wide */
    color: #000;
    background: #9F9;
}
table td a:hover {
    background: #FF9;
}
</style>
</head>
<body>
    <table summary="">
        <tr>
            <td><a href="#">XXXXX</a></td>
            <td><a href="#">X</a></td>
            <td><a href="#">XXXXXXXXXXXXXXXXXXXX</a></td>
            <td><a href="#">XXXXX</a></td>
            <td><a href="#">XXXXX</a></td>
        </tr>
    </table>
</body>
</html>

Any help testing this would be appreciated :slight_smile:

If you have a broken Safari on your Windows system, installing the last developer version will fix it, download Safari 3.0.6a from Apple Developer Connection. (Membership is required to download software.)

Otherwise think back if you have added fonts to Windows, or maybe installed software that have done. If so try to reverse the font change, or at least temporarly remove added fonts. I have had indications on that a font change can be the initial cause when Windows Safari suddenly refuses to work no matter what you do.

Erik. I am wonder of your discovering this question. But gaps between cells in your variant are not equal (i have measured gaps in Photoshop). My suggested variant (in first post) provide 100% equal gaps (although my code is less clean). If you can and want, digg my variant, please, I am interesting of logic of my suggested variant. Why it works in such way.

Sorry to contradict, but crossbrowser your posted code does not. Also, using empty cells can only create equal gaps between inner items. Should you want the menu items centred with equal gaps it will not work.

If you want the outer items flushed to edges of menu, the method I used will not do. So you can’t compare the gaps between the codes with simular setups.

I know you never asked for centred items, I only assumed the equal gaps should centre items. :slight_smile: