What is margin folding?

W3C definition for margin overlay:

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 CSS, the vertical margins of two or more adjacent boxes in a normal stream (which may be parent or sibling elements) are superimposed. The resulting margins are called margin superimposed.

Horizontal margins never collapse.

Margin stacking occurs only for vertical margins. Horizontal margins do not add up.

Here is the code:

html

<div class="container">
    <div class="item"></div>
    <div class="item"></div>
</div>
Copy the code

css

.container {
    border: 1px solid red;
    width: 500px;
    margin: 0 auto;
}

.item {
    height: 60px;
    background: blue;
    width: 300px;
    margin: 50px auto;
}
Copy the code

The effect is shown below:

It can be seen that the interval between two items is 50px, that is, the vertical margin overlaps, which is the so-called margin folding.

Why margin folding?

The CSS1.0 and 2.0 specifications describe:

CSS1.0

Minecraft 2.0 is about Collapsing

The specification in CSS1.0 is very clear and is designed to do this on purpose, because it will meet the requirements of graphic designers in most cases.

The relationship among Margin collapse, BFC and Containing blocks is analyzed with reference to depth:

On StackOverflow Why the CSS Specification… The big guy replied

There’s a historic reason. Mostly about how P(Paragraph) elements were rendered in the days before CSS. CSS needed to replicate the existing behaviour. But the behaviour still makes sense today for the reasons given in the question

It was originally intended to be compatible with the P tags used before the invention of CSS1.0

The P tag before CSS (with the same margins above and below) looks like this:

The P tag looks like this by nature, and there’s no CSS that lets you change its default style. Now look at the P tag (which is just a display:block; Element) looks like:

 p {
    display: block;
    margin-block-start: 1em;
    margin-block-end: 1em;
    margin-inline-start: 0px;
    margin-inline-end: 0px;
}
Copy the code

Among them:

margin-block-start == margin-top

margin-block-end == margin-bottom

margin-inline-start == margin-left

margin-inline-end == margin-right

If there is no margin folding, it is shown as:

The spacing in the middle is larger than the spacing in the beginning and the end, which is obviously not pretty (this is what the CSS specification says is more designer design)

When will margin overlay happen

Two margins are adjoining if and only if:

  • both belong to in-flow block-level boxes that participate in the same block formatting context
  • no line boxes, no clearance, no padding and no border separate them (Note that certain zero-height line boxes (see 9.4.2) are ignored for this purpose.)
  • both belong to vertically-adjacent box edges, i.e. form one of the following pairs:
    • top margin of a box and top margin of its first in-flow child
    • bottom margin of box and top margin of its next in-flow following sibling
    • bottom margin of a last in-flow child and bottom margin of its parent if the parent has ‘auto’ computed height
    • top and bottom margins of a box that does not establish a new block formatting context and that has zero computed ‘min-height’, zero or ‘auto’ computed ‘height’, and no in-flow children
  • Are block-level boxes belonging to normal flows and in the same BFC

  • Not separated by padding, border, clear, and line box

  • Perpendicular to each other, including:

    • The top margin of the box and the top margin of its first normal stream child

    • The bottom margin of the box and the top margin of its next normal stream sibling

    • The bottom margin of the box and its parent element

    • Top and bottom margins of the box, without creating a new block-level format context, with min-height computed to 0, height computed to 0 or auto, and no normal stream child elements

    Here’s an example:

    html:

<div class="container1"></div>
<div class="container2">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
</div>
<div class="container3"></div>
Copy the code

css:

.container1 {
    height: 20px;
    background: yellow;
    margin-bottom: 20px;
}

.container2 {
    margin: 10px 0 30px;
}

.container3 {
    height: 20px;
    background: green;
    margin-top: 100px;
}

.item {
    background: red;
    height: 20px;
    margin: 50px 0 -20px;
}
Copy the code

The effect is as follows:

Description:

According to the rule, the top margin of the box is folded with the top margin of its first normal stream child, so.container2 is stacked with the top margin of the first.item, resulting in a margin of 50px between.container1 and.container2.

According to the rule: the bottom margin of the box is folded with the top margin of its next normal stream sibling, so the top margin and bottom margin of the.item in.container2 are stacked with margins of 30px between them.

According to the rules: The bottom margin of the box is folded with the bottom margin of its parent element, so the last.item in.container2 has a bottom margin overlay, and the margin between.container2 and.container3 is 80px.

To sum up: the vertical margin of elements nested by father and son should be the maximum.

Adjacent boxes vertically do not fold

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.

Vertically adjacent boxes do not collapse:

  • The margin of the root element does not participate in folding
  • The top and bottom margins of a clearance box are adjacent and it will fold with the next box, but the folded margins will no longer fold with the bottom margin of their parent box

How to calculate the fold margin

In the case of negative margins, the absolute maximum of the negative adjoining margins is deducted from the maximum of the positive adjoining margins. If there are no positive margins, the absolute maximum of the negative adjoining margins is deducted from zero.

To sum up:

  • When the margins of two adjacent boxes are both positive, the fold margin is the larger value of the two
  • When the margins of two adjacent boxes are both negative, the fold margins are the larger absolute values of the two
  • When the margins of two adjacent boxes are positive and negative, the folded margins are the sum of the two

How to avoid margin overlay

  • Margins between a floated box and any other box do not collapse (not even between a float and its in-flow children).
  • 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.
  • Margins of absolutely positioned boxes do not collapse (not even with their in-flow children).
  • Margins of inline-block boxes do not collapse (not even with their in-flow children).
  • The bottom margin of an in-flow block-level element always collapses with the top margin of its next in-flow block-level sibling, unless that sibling has clearance.
  • 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.
  • A box’s own margins collapse if the ‘min-height’ property is zero, and it has neither top or bottom borders nor top or bottom padding, and it has a ‘height’ of either 0 or ‘auto’, and it does not contain a line box, and all of its in-flow children’s margins (if any) collapse.
  • The floating element does not superimpose with any element, including its children
  • Elements that create BFC (such as float, overflow property notvisibleDoes not add margins to its children
  • There is no margin overlay between an absolute positioning element and any other element, including its children
  • No margin overlay occurs between an inline-block element and any other element, including its children
  • The margin-bottom of a block-level element in a normal stream is always superimposed with the margin-top of the next block-level element, unless the neighboring sibling element is clear
  • Margin-top of the block-level element in the normal stream (no border-top, no padding-top) and its child element in the first normal stream (no clear) are margin-top superimposed
  • Margin-bottom occurs in a block-level element in a normal stream (height is auto, min-height is 0, no border-bottom, no padding-bottom) and in its last normal stream child (no margin overlay or clear of its own) The superposition
  • If an element has a min-height of 0, no border, no padding, a height of 0, or auto, and no child elements, its own margins will stack

If above content has a problem, ask each big guy to teach! Thank you very much!

References:

The relationship among Margin collapse, BFC and Containing blocks is deeply analyzed

CSS1.0 official specification

CSS2.0 official specification

Margin Collapse