When you ‘float’ an item, it is ‘removed from flow’ – which is to say it’s height, width, and anything else about it is NOT reported to it’s parent container or any siblings/parents of that parent container. That example page of mine shows this in action – on that first set of boxes the inner red DIV is really tall and floated, the outer DIV is not set to ‘wrap’ floats, so the red box pokes out the bottom. In the second one, the outer box expands to contain the red one because a wrapping behavior is triggered – that’s what the overflow does in modern browsers, and what the ‘zoom:1’ – aka a haslayout trigger – does in legacy versions of Internet Exploder.
There are several ways to make that parent container ‘wrap’ a floated element – basically putting that float ‘back in flow’. One way – the one people usually find first, is to put a dummy empty “sandbag” DIV in set to clear=“both”. “clear” says “this element must appear after the float instead of wrapping around it.” Seems like a good solution at first, but it means extra markup – and a good rule of thumb is that if it comes down to adding more markup, or adding more CSS - choose the CSS. You put CSS in an external file, you use the same CSS across multiple pages, it’s only loaded once for all those pages saving you bandwidth. Basically, caching is a good thing.
Since we don’t want that extra markup, the next thing people will try is called “clearfix” – this needlessly complex train wreck of a class; that basically is adding a class to the markup for no good reason, and pulling all sorts of stupid tricks to get wrapping workin. In case you couldn’t tell – not a fan.
But there are two things that will make a container wrap floats inside it easily – one is to make the container itself be floating. Floats wrap floats – but with floats playing weird games with their widths, declaring widths making using padding tricky, etc, etc… its’ not a great choice… also an entire layout where EVERYTHING is floating can also be a bit… fragile.
The other one is overflow… overflow:hidden is usually used to ‘chop off’ positioned elements or content larger than the dimensions stated on the element… for example if you had a DIV 320 px wide, and a IMG inside it 400px wide, setting the DIV to overflow:hidden would ‘chop off’ the right 80px of that image. This is a very powerful ability and can be used for all sorts of handy effects – but it does something else to that container…
So long as a fixed height isn’t set on the element overflow:hidden is applied to, said element will “wrap” any child floats… as the second pic in that little demo of mine shows. If you do set a height, be warned if the content is taller than that height, it’s getting chopped… As a rule setting fixed heights on, well… anything with variable content inside it is a bad idea.
Unfortuantely while said behavior is in the CSS 2.1 specification, IE6 and earlier were written while that specification was still in DRAFT (and of like how people are now using HTML 5 and CSS3 while it’s still in DRAFT, and using the same lame excuses to justify it)… because of that not all it’s behaviors were complete or accurate to the finalized spec – and one glaring omission is overflow wrapping floats…
But, there’s a concept they introduced to IE BEFORE there even was such a thing as CSS called “haslayout” – some HTML elements by default would ‘have layout’; extra calculations to figure out thier position and size as they might change or have changes applied that could alter the entire rest of the page – other elements would not ‘have layout’ and as such not need all those extra calculations; the laugh of this is that it made IE many times faster than Netscape, and one of the reasons that IE4 was the start of Netscapes decline. (LONG before they started bundling IE with the OS – a lame copout given the number of Mac users that use Safari as opposed to FF). When CSS was introduced haslayout was triggered by some CSS properties and not others, and tripping haslayout introduces a whole bunch of extra positioning oddities.
Amongst these oddities is that elements “with layout” will wrap floats… Of all the different things that trip haslayout, one of the easiest to use is the zoom property. zoom:1 doesn’t actually change the content, but it trips “haslayout”, fixing all sorts of strange bugs but more importantly, making the container wrap any floats.
Used to be people *****ed about zoom:1 and would use other tricks (like height:1%) to trigger haslayout… Zoom is an IE specific property that is “invalid CSS” – no arguing that, but with the SLEW of vendor specific nonsense people are using (and incorrectly calling CSS3) like -moz, -webkit, -o, -ms, etc, etc… are we really at a point of poo-pooing a simple six character vendor specific property that used well can make pages work all the way back to IE 5.5? PLEASE…
You can find a more complete explanation of haslayout and it’s triggers at these fine retailers – millions sold in Europe:
http://www.satzansatz.de/cssd/onhavinglayout.html
http://msdn.microsoft.com/en-us/library/ie/bb250481(v=vs.85).aspx
It’s good to know about haslayout – it’s not a be-all solution to IE shortcomings, but in many cases tripping it is all you need to fix ‘problems’ in IE7/earlier. Newer versions usually don’t need it, though in IE8 there are still a couple times it wigs out and haslayout “is your only hope”.
Sorry this got a bit long – but floats and the behavior of containers around them is actually a very complex topic with LOTS of different answers and approaches; figured it might help to get a nice thorough explanation in place – as I’ve rarely seen a explanation in a book or tutorial that said WHY or listed more than one approach. The answer is usually just “Do this”… and then “moving on…”
Like anything else in HTML/CSS, I suggest actually playing with it in the code – add or remove various properties, try it in three or four different browser engines, and see what happens. It’s always easier to learn by doing than by having someone just tell you about doing it.