Reputation: 9347
This question is similar to this one (with an excellent answer), although mine doesn't pertain to float issues.
I recently ran into some trouble when trying to apply a margin to an only-child of a block-level element:
#parent {
background: rgba(255, 0, 0, 0.1);
}
#child {
margin: 30px 0;
padding: 20px;
background: rgba(0, 255, 0, 0.1);
}
<div id="parent">
<div id="child">Foo</div>
</div>
Although the margin is applied, the parent's background is not. This remains true unless siblings are added before and after the #child
, or (more interestingly in my opinion), an overflow
of any value other than visible
is set. Here is the same example but with an overflow value:
#parent {
background: rgba(255, 0, 0, 0.1);
overflow: auto;
}
#child {
margin: 30px 0;
padding: 20px;
background: rgba(0, 255, 0, 0.1);
}
<div id="parent">
<div id="child">Foo</div>
</div>
From CSS2.1 Section 9.4.1 - Block Formatting Contexts, I found the following:
Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.
I'm really struggling to understand the rationale behind the "overflow other than visible" logic in this instance. The margins are seemingly not being clipped in this situation, as the only thing to change is the background. Could someone demonstrate why a value of overflow: visible
creates such a situation?
Upvotes: 8
Views: 365
Reputation: 272136
In your first examples the top and bottom margins of parent and child are collapsed. Roughly speaking, the 30px margin of child is combined with the zero margin of parent, the greater margin of the two is applied on the parent. Quote:
In CSS, the adjoining margins of two or more boxes (which might or might not be siblings) can combine to form a single margin. Margins that combine this way are said to collapse, and the resulting combined margin is called a collapsed margin.
In the same document, the effect of overflow (as in your second example) is explained:
Margins of elements that establish new block formatting contexts (such as floats and elements with 'overflow' other than 'visible') do not collapse with their in-flow children.
Upvotes: 1
Reputation: 723729
As I have covered in my answer to the question that you link to, the main reason overflow
values other than visible
result in a new block formatting context is due to implementation limitations relating to floats, even though the concept of overflow does not immediately appear to have a relationship with floats.
While the relationship between floats and collapsing margins is pretty simple (it never occurs), the fact that margins cannot collapse through the boundaries of an element with such a value for overflow
either is little more than a side effect of this change, because margins are defined not to collapse through any box that establishes a block formatting context, as described in section 8.3.1. I quote:
- Margins of elements that establish new block formatting contexts (such as floats and elements with 'overflow' other than 'visible') do not collapse with their in-flow children.
This includes both floats and elements with such a value for overflow
. The overflow itself does not actually have any direct effect on the margins.
When both the parent and the child are block-level elements that participate in the same block formatting context, they will collapse by default unless there is something in the way:
The top margin of an in-flow block element collapses with its first in-flow block-level child's top margin if the element has no top border, no top padding, and the child has no clearance.
The bottom margin of an in-flow block box with a 'height' of 'auto' and a 'min-height' of zero collapses with its last in-flow block-level child's bottom margin if the box has no bottom padding and no bottom border and the child's bottom margin does not collapse with a top margin that has clearance.
This explains why the parent's background does not extend until you try and block the margin collapse.
Upvotes: 2
Reputation: 1733
This clarifies an issue I've occasionally had with heights. It looks like the height of the parent element is not being calculated from the margins of the child.
Adjusting your fiddle: http://jsfiddle.net/u6tQj/2/
#parent { background: #555;}
#child { margin:200px; background: #ccc; }
The margins are being applied to the child, but the height of the parent was unaffected. Adding overflow or border causes the height to adjust. I do sometimes struggle with why parent elements don't always expand to contain the children.
It seems very odd, but...
It could be complicated to have conflicting rules on parent height. It would affect many of the browser layouts, such as parent position relative with children set to absolute, or overflow auto/hidden, and probably a host of other layout algorithms. I imagine it would unnecessarily complicate the browser's layout engine, in the same way that css selector specificity can sometimes be a major pain for us.
You would add padding to the parent to adjust its height, which is more intuitive (isn't it?).
Upvotes: 0