Forum Moderators: not2easy
I have a fluid width container div with a bunch of floated children. One of the children is float:left and the rest are float: right. The right children have fixed widths. The last child is wider than the previous ones and has clear: right.
It's a bit difficult to describe what's wrong, but here goes: when the distance between the left element and the right edge of the container are larger than the width of the big (last) right element, the big element aligns correctly against the right edge of the container. When the container is smaller, the big element will overlap the right edge of the container even if it has room to slide below the left element.
FF and Opera do not have the problem. IE7 does it correctly except when the container is too small for the big element AND is too big to force one of the other right elements below the left element. Once one of the small right elements goes below the left element, the big right element again correctly aligns with the right border.
Maybe just try the code below. I see the problem when the browser window is 1047px wide, not including window decorations.
Has anyone seen this? Is there a fix? Do I get a prize if there isn't? (at least then I'll have something to show for banging my head against a wall for 3 hours)
<!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" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Test 2</title>
<style type="text/css">
.container {
background-color: #AAA;
width: 50%;
}
.left {
float: left;
height: 3em;
border: 1px dashed green;
}
.right {
float: right;
width: 5em;
border: 1px dashed red;
}
.big {
width: 20em;
clear: right;
}
</style>
</head>
<body>
<div class="container">
<div class="left">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
</div>
<div class="right">Foo</div>
<div class="right">Foo</div>
<div class="right">Foo</div>
<div class="right">Foo</div>
<div class="right">Foo</div>
<div class="right">Foo</div>
<div class="right big">Foo</div>
<div style="clear:both;"></div>
</div>
</body>
</html>
Although the bug seems vaguely familiar, I really can't remember seeing this exact thing before. And, you know what -- there appears to be no fix for it either. At least not one I could find.
You can, however, circumvent the problem by inserting a clearing element before your
.big element. ...
<div class="right">Foo</div>
<div style="clear:whatever;"></div>
<div class="right big">Foo</div>
...
As you will notice, it does not matter what the clear property is set to (to demonstrate, I set it to the invalid value
whatever). Its mere presence is enough to fix the bug in IE. You'd think that
.big:before { clear: right; } would fix it too then ...
it appears this particular IE Bug is not squishable without an extra element of sorts, there are various documentations of this bug on Bruno Fassino's site - search phrase [google.co.uk]
The bug is present in various guises whenever float + clear are used together (on the same element) in IE. (there are 3 pages of test cases via that search!)
the main problem being for IE:
A float having the clear property (value both) only clears preceding floats of its same direction (left/right.) This fact is responsible for the wrong behaviour in the following cases:
I take it from that, though not wholly tested, that a float which also has a value of
clear:right will only clear previous right floated elements and vice versa.. -----
I changed your sample slightly to give it widths on everything to make sure it wasn't the combination of ems (widths) and px (borders) - changed method of clearing floats to remove clearing div (optional), removed borders and used backgrounds to remove all traces of 'IE having to do calculations' - but it made no difference and in fact it also appears if you reverse the float directions
my code for ref..
CSS:
.container {
background-color: #000;
width: 480px;
float: left; /* to contain floats */
}.left {
float: left; /* swap to show reverse effect */
width: 250px;
height: 100px;
background: #dad;
}
.right {
float: left; /* swap to show reverse effect */
width: 80px;
background: #cfc;
}.big {
width: 320px;
/* clear: both; */ /* if you need this then any empty element before the last/big float seems to help */
}/* extras for visual */
div {margin: 2px 5px;}
.left, .right {display: inline;} /* double margin bug workaround <IE7 */HTML:
<div class="container">
<div class="left">Left floated container..</div>
<div class="right">Foo 1</div>
<div class="right">Foo 2</div>
<div class="right">Foo 3</div>
<div class="right">Foo 4</div>
<div class="right">Foo 5</div>
<div class="right">Foo 6</div>
<!--<br />-->
<div class="right big">Foo last</div>
</div>
apparently any empty element inserted before the cleared element will do it,
HOWEVER bugs aside and with ref your particular usage, do you need the clear at all?
if you don't use clear and the big element fits the space all is well, but then IF the big element is bigger than the space between the main float and the right edge it automatically clears the space and the main float as far as I can see - perhaps there is another reason for this that I can't see or it's because of the changes I made, if so I apologise for going off tack ;)
Well spotted on the bug though!
Suzy
added to clarify
where I have clear:both in my code it makes no difference if you use
clear:right; or clear:left; - depending on which float directions you're testing, I did test this but forgot to swap it back to right for this sample [edited by: SuzyUK at 1:09 pm (utc) on July 18, 2007]
Thanks again!