Cross-Browser Issue: Min-Height and Collapsing Margins

Cross-browser Issue: Min-height and collapsing margins

OK, so this seems to be a very peculiar case.

If you change min-height to height, the gap disappears in Chrome. Not only does Safari behave the same as Chrome, but so does IE. Firefox's behavior is unique to itself, and its behavior does not change when you make that adjustment to your CSS. This should come as a surprise, as you would not expect min-height and height to behave any differently in your given scenario.

However, the spec has something interesting to say about min-height with respect to margin collapsing:

The following algorithm describes how the two properties influence the used value of the 'height' property:

[...]

These steps do not affect the real computed values of the above properties. The change of used 'height' has no effect on margin collapsing except as specifically required by rules for 'min-height' or 'max-height' in "Collapsing margins" (8.3.1).

Because you have not specified a fixed value for the height property on the same element that has a min-height, the computed value for height remains the default auto, even though the used value is floored to min-height.

Therefore the following text from section 8.3.1 applies, and the margins between the block box and its child should collapse as a result, irrespective of min-height:

Two margins are adjoining if and only if:

  • both belong to vertically-adjacent box edges, i.e. form one of the following pairs:

    • ...
    • bottom margin of a last in-flow child and bottom margin of its parent if the parent has 'auto' computed height

Note that it goes on to list some scenarios in which margins may or may not collapse:

Note the above rules imply that:

  • ...
  • 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.

... but it does not state what happens when the block box has height: auto and a non-zero min-height.

Based on this, it would be safe to assume that the spec should be interpreted as I am doing. Therefore it looks like Firefox is not behaving quite correctly, and all other browsers are following the spec to the letter, despite what one might expect from the behavior of height and min-height.

You can file a bug for Firefox here, although it looks like the developers have already made themselves aware of this issue.

Why do Chrome and Firefox behave differently on margin?

Reason

That's because the p element inside #wrapper has some margin, which may collapse.

Introduction to margin collapse

The CSS 2.1 spec says

8.3.1 Collapsing margins

In CSS, the adjoining margins of two or more boxes [...] can combine
to form a single margin. Margins that combine this way are said to
collapse [...]

Adjoining vertical margins collapse [...]

Your styles

Your #wrapper element has

#wrapper {
height: auto;
min-height: 100%;
}

Old behavior (Firefox)

An old version of the spec said

The bottom margin of an in-flow block-level element with a
'height' of 'auto' and 'min-height' less than the element's
used height and 'max-height' greater than the element's used
height is adjoining to its last in-flow block-level child's bottom
margin if the element has no bottom padding or border.

#wrapper has height: auto. However, in case that the window is taller than its contents, min-height will be the used height (not less). Therefore, margins won't collapse.

This is the behavior observed on Firefox.

New behavior (Chrome)

However, the spec changed, and now the value of min-height does not matter:

Rephrased the rule for adjoining margins so that the 'min-height' and
'max-height' of an element have no influence over whether the
element's bottom margin is adjoining to its last child's bottom
margin.

The new rule is

[The] bottom margin of a last in-flow child and [the] bottom margin of
its parent [are adjoining] if the parent has 'auto' computed height

Therefore, since height is auto, margins should collapse.

This is the behavior observed on Chrome.

Note

Here the current spec seems to imply that min-height: 0 is a requirement:

The above rules imply that 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
[...]

But it is not. The sentence will be clarified in CSS 2.2.

Illustration

The following snippet animates min-height to illustrate the difference of behaviors between Chrome and Firefox:

  • When min-height is smaller than content's height,

    • The used height is content's one
    • Margins collapse both on Chrome and Firefox
  • Otherwise,

    • The used height is min-height
    • Margins collapse on Chrome but not on Firefox

Therefore, when min-height reaches content's height, on Firefox there is a sudden (dis)apparition of the space caused by margin collapse.

#wrapper {

background: orange;

margin: 0 1em;

-webkit-animation: animate 1s linear infinite alternate;

animation: animate 1s linear infinite alternate;

}

footer {

background: red;

}

p {

margin: 1em 0;

height: 1.75em;

background: green;

}

@-webkit-keyframes animate {

from { min-height: 4em; }

to { min-height: 6em; }

}

@keyframes animate {

from { min-height: 4em; }

to { min-height: 6em; }

}

/* Content is 4.5em tall */
<div id="wrapper">

<p>Line 1</p>

<p>Line 2</p>

</div>

<footer>Footer</footer>

Do vertical margins collapse reliably and consistently across all browsers?

It's hard to give a definitive answer to this question because it's very broad. "All browsers" is a lot of browsers. There could always be some fringe browsers you never heard of that handle this differently. It all depends on how the browser's CSS rendering engine was written.


That said, any browser that wants to be taken seriously will try to adhere the W3C specs, which have the following to say about margin collapsing:

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.

Adjoining vertical margins collapse, except:

  • Margins of the root element's box do not collapse.
  • If the top and bottom margins of an element with clearance are adjoining, its margins collapse with the adjoining margins of following siblings but that resulting margin does not collapse with the bottom margin of the parent block.

Horizontal margins never collapse.

Source: Box Model (w3.org)


I figured it'd be a nice addition to just put your code to the test in as many browsers as possible. I made a test page page of your html (slightly modified), with an absolutely positioned 50px high block that should fit right in between the collapsed margin, to make it easier to spot a difference:

http://files.litso.com/playground/margin.html

Then I ran this through browsershots.org to get screenshots of how browsers would display this piece of HTML:

http://browsershots.org/http://files.litso.com/playground/margin.html#
(I have no idea how long this will stay cached, but I guess you could always just run it again)

Interestingly, the positioning of the blue block is a few pixels off in a bunch of the screenshots. You can still tell the margins are collapsed correctly, but I do wonder what exactly the problem is with the positioning.

The only browsers that don't seem to collapse the margin correctly are Dillo 3.0.2 and Links 2.7 on Debian 6.0, neither of which seem to listen to padding or margin properties at all (nor to the absolute positioning for that matter). They would mess up your layout no matter what, and you shouldn't worry about it. People use browsers like these for a specific reason, and seeing your page exactly as you intended it to be seen is not one of them.


TL;DR: Yes, it's safe to say that all browsers collapse these elements reliably and consistently.

Why is the web page show a scroll bar when `body` set to `min-height: 100vh`?

margin: 10px auto;

Unlike paddings, CSS margins are not exactly a spacing measure when it is applied to an element inside. When you apply a margin to the elements like above, the top margin will tend to go outside of the parent element. It is just an example of the general margin collapsing behavior.

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing

Therefore, in your code snippet, it's not only the body with the height of 100vh that you see on the screen. It also includes 10px of space right above the body element.

To resolve this issue, remove margin from .container and consider applying padding-top: 10px; to the body element instead.

H1 appears to have zero margin-top in Chrome

You aren't using a doctype and are in quirks mode where you never want to be. Add a proper doctype on your first line, to put yourself in "standards mode" and the problem goes away.

<!DOCTYPE html>

How to Collapse Left Side Padding or Margin in Responsive Design Layout?

You want to use media queries for this. Specifically viewport-height or viewport-width from the sounds of things.

Link to documentation.

Basic idea:

@media (max-height: 600px) {
.bottom-button {
/* styles */
}
}
@media (min-height: 600px) {
.bottom-button {
/* different styles */
}
}

100% min-height wrapper breaks background

Hi you have used floating in your child elements not clear your parent wrapper div so that's why the problem is coming so clear your parent wrapper div with overflow:hidden; problem will sort out.

UPDATE YOUR CSS WITH MENTIONED BELOW CSS

CSS

.wrapper {
background-image: url("http://static.shopify.com/s/files/1/0098/1262/t/107/assets/body-bg.png?2789");
background-repeat: repeat-y;
margin: 0 auto;
min-height: 100%;
overflow: hidden;
text-align: left;
width: 940px;
}


Related Topics



Leave a reply



Submit