tags:

views:

160

answers:

4

Suppose I have this HTML structure:

<div class="a">
 <div class="floated-left">...</div>
 <div class="floated-left">...</div>
</div>

I have noticed that if I don't set overflow:hidden to .a, then the <div class="a"> does not occupy any vertical size. For example, if I set its background to red, it is not visible at all. Inspecting it with FireBug shows that it's there but of almost no vertical size.

To fix this, I found that I have to set overflow:hidden to .a. Then the first <div> goes over all its content.

Here is a real example:

<html>
<head>
  <style>
    .a { background-color: red; }
    .b { background-color: red; overflow: hidden }
    .floated-left { float: left; width: 100px; height: 100px; background-color: blue; }
  </style>
</head>

<body>
  <p>div with class a, that doesn't overflow:hidden:</p>
  <div class="a">
    <div class="floated-left">Hi,</div>
    <div class="floated-left">Mom!</div>
  </div>

  <div style="clear:both"></div>

  <p>div with class b, that does overflow:hidden:</p>
  <div class="b">
    <div class="floated-left">Hi,</div>
    <div class="floated-left">Dad!</div>
  </div>
</body>
</html>

Notice how Hi, Mom! does not get red background (no overflow:hidden), while Hi, Dad! does get red background (has overflow:hidden).

Can anyone explain this behaviour?

Here is screenshot of the example:

http://imgur.com/O8qvP

Thanks, Boda Cydo.

+1  A: 

Hi, Mom does not get any background because the background comes from the a div, which is height 0 (or near 0). The inner divs are actually overflowing its bounds (which is what floats do by default).

The thing to remember with floats is that they don't have inherent height (when it comes to layout and determining the parent's height). Inline content simply flows around them. So without overflow: hidden the parent div has no height. No height means no background. The floats are still rendered but they go beyond the bounds of the parent div ie the content in the floats is outside the parent div.

cletus
A: 

Floated elements don't occupy any vertical space for clearing, there are a few ways to fix this, something like:

<div class="a">
  <div class="floated-left">Hi,</div>
  <div class="floated-left">Mom!</div>
  <br style="clear: left;" />
</div>

Would clear after, and make the outer div have a vertical height. Set a border: solid 1px red; on .a to see this in action.

Alternative CSS only solution:

.a:after {
  content: ".";
  display: block;
  height: 0;
  clear: both;
  visibility: hidden;
}
Nick Craver
I honestly don't know why anyone would ever use that clearfix solution (last). It's less supported than `overflow: hidden` and is far more obscure.
cletus
@cletus: It's supported in every current browser, and less markup...just a matter of what your audience is and which (html/css) you're more comfortable with.
Nick Craver
@cletus: Actually some version of it is used in both blueprint and 960gs. Although i think they are moving to the solution he stumbled upon.
prodigitalson
@Nick: how is it less markup than `overflow: hidden` on the parent?
cletus
@cletus: I meant less markup than any html...but `overflow:hidden` doesn't always work, in some scenarios you'll get scrollbars if the children are large enough...depends on the situation of course but `overlow:hidden` isn't a valid solution 100% of the time (most commonly, if the width overflows).
Nick Craver
@nick: However in current browsers you can set overflow independently for each axis with overflow-x and overflow-y.
prodigitalson
+3  A: 

When you float elements they are taken out of the document flow. Among other things, this means that they have no impact on the dimensions of the parent element (although its width will determine where the floats are positioned on the horizontal axis). They do however impact positioning of siblings within the container depending on whether those sibling are inline or block level elements and whether they have width or not.

In order to make the height of the floats impact the height of the container you must have an element after them that clears them. However, what you are seeing here is actually a part of the CSS standard that you can use to clear floats without additional, non-semantic markup. The only issue is this behavior can vary slightly in older browsers and their css implementations. This effect is present with both overflow auto and overflow hidden but does not present with overflow visible. In IE < 6 you must have a width set on the containing element for it to work.

prodigitalson
A: 

Per the spec for CSS basic box model:

Margins of a floated box do not collapse with any other margins. Margins of a box with ‘overflow’ other than ‘visible’ do not collapse with its children's margins.

By providing it the "overflow" property explicitly you have allowed the children to fit into this model, thus the b div no longer has bounds attached to its children. If you apply visible or inherit (which the parent of b is visible by default), the bounds return and the children divs define the margins.

http://www.w3.org/TR/css3-box/ (RE: Example X)

Joel Etherton