Horizontal list menu in IE (why)

This is more of a “why” question for my edification than anything else.
Recently, I was going to the step of IE-ising my code, when I ran into a typical problem. in making a horizontal menu, I had floated all my LIs … which of course is all that you need to do in standard compliant browsers. In IE however you need to float any block or display:block element WITHIN the LI’s.
ex: <li><a><span></span></a></li>. if you have given the anchor and span a display:block, you need to float BOTH or IE will break the layout.

My question is WHY? Do floated elements in IE not contain their children ? The a fore mentioned solution seems to be well know, but yet this is not referred to as a BUG, so it made me curious.

Hi,

Perhaps I can explain :slight_smile:

The answer to the question as is always the case with IE is the “haslayout” issue.

If we take your example and expand it you will see that it actually works fine in iE6/7.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style>
ul{margin:0;padding:0;list-style:none}
li{float:left;margin:10px;}
a,span{display:block;}
span{padding:10px;background:red}
</style>
</head>
<body>
<ul>
    <li><a href="#"><span>test</span></a></li>
    <li class="test"><a href="#"><span>test</span></a></li>
    <li><a href="#"><span>test</span></a></li>
    <li><a href="#"><span>test</span></a></li>
</ul>
</body>
</html>


The anchor and span are display:block and the list is fine and works as expected (unlike what you suggested would happen).

The problem only arises when the anchor or the span gets haslayout.

e.g. If we add a height to the span.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style>
ul{margin:0;padding:0;list-style:none}
li{float:left;margin:10px;}
a,span{display:block;}
span{padding:10px;background:red}
.test span{height:100px}
</style>
</head>
<body>
<ul>
    <li><a href="#"><span>test</span></a></li>
    <li class="test"><a href="#"><span>test</span></a></li>
    <li><a href="#"><span>test</span></a></li>
    <li><a href="#"><span>test</span></a></li>
</ul>
</body>
</html>

Now the layout is completely broken because the span achieves layout and an element with layout will try and be 100% wide and as a result it makes that span the remaining 100% width of the viewport thus displacing all other floats.

If on the other hand you gave the span a width then even though it has layout the width is no longer 100% (or more correctly auto) and the layout once again starts working properly.

You may then ask that why doesn’t floating the span cause the layout to break because a float gives an element layout? The answer is again related to width and floats are shrink to fit and the floated element doesn’t try to be 100% wide.

So the answer to your question is that when element inside a float have layout but don’t have their dimensions controlled then they will expand to 100%.

That’s why the problem can be solved by simply floating the list and its children rather than using display:block. Or where possible using widths and avoid all bugs.

If you float a right floated element inside a left floated element in iE6/7 then once again you trigger the 100% effect and things are broken.

The float ends up on the right side of the screen in IE6/7.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style>
ul {
    margin:0;
    padding:0;
    list-style:none;
}
li {
    float:left;
}
a {
    float:right;
    background:red
}
</style>
</head>
<body>
<ul>
    <li><a href="#"><span>test</span></a></li>
</ul>
</body>
</html>


The solution is to float both to the left.

There is an opposite bug where you float all the items to the right and IE6/7 lines then vertically because this time it takes the parents floated width as a constraining factor and won’t align them horizontally.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style>
ul {
    margin:0;
    padding:0;
    list-style:none;
}
li,a,span {
    float:right;
}
li{margin:0 10px}
span {
    background:red
}
</style>
</head>
<body>
<ul>
    <li><a href="#"><span>test</span></a></li>
    <li><a href="#"><span>test</span></a></li>
    <li><a href="#"><span>test</span></a></li>
    <li><a href="#"><span>test</span></a></li>
</ul>
</body>
</html>


In IE6/7 the floats are all on the right but align vertically and not horizontally.

The solution perversely enough is to float the inner elements to the left instead which doesn’t trigger the effect that we saw earlier when you floated left and then right.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style>
ul {
    margin:0;
    padding:0;
    list-style:none;
}
a,span {
    float:left;
}
li{float:right;margin:0 10px}
span {
    background:red
}
</style>
</head>
<body>
<ul>
    <li><a href="#"><span>test</span></a></li>
    <li><a href="#"><span>test</span></a></li>
    <li><a href="#"><span>test</span></a></li>
    <li><a href="#"><span>test</span></a></li>
</ul>
</body>
</html>


That’s all there is to it - I’m surprised that everyone doesn’t know this :slight_smile:

(Have a look at one of the recent CSS quizzes where we discuss alternate solutions.)

Paul,
as wise as always.
In fact, I was testing in IE5x, and the problem that I thought occurred because I had had to float the anchor ( and then also the span) beacuse I had given each tag a display: block. I had not mentioned the fact that the LI, A, and SPAN were all given height and width as well. ( I was working an IR technique).

I also did solve it before I posted by floating all elements. I was a bit confused because I thought triggering HasLayout SOLVED layout issues rather than caused them. In fact, the first thing i tried since I couldnt change the height/width was to add zoom:1 to trigger HasLayout. Thanks so much for your explanation, Paul.

BTW,

If you float a right floated element inside a left floated element in iE6/7 then once again you trigger the 100% effect and things are broken.

The float ends up on the right side of the screen in IE6/7.

There is an opposite bug where you float all the items to the right and IE6/7 lines then vertically because this time it takes the parents floated width as a constraining factor and won’t align them horizontally.

does this mean it’s impossible to have a horizontal menu floated so that it’s on the right side of the page?

I miss read the post the first time, but I get it now. Thanks Paul.

Works the same in all browsers.
Perhaps another css rule is causing the problem.
Can you give example code?

The code at the end of my last post is the solution to that :slight_smile: