Margin merge rules


The merge rules written in the previous margin are the most complicated part of the CSS box model. Because this part of the content involves many concepts that are not easy to understand, such as clearance (clearance), normal flow/in-flow (regular flow), BFC (block formatting context), line box (line box), inline box (inline box) ), bidi (two-way environment), etc.

The CSS box model is not just 7 horizontal attributes + 7 vertical attributes:


margin
  border
    padding
      width/height

PS thinks of the stalk of high heels-"not only padding, but also margin today"

The relevant content includes at least:

context-box与border-box

Calculation method of padding/margin percentage

background与padding/margin/border

negative margin

margin merge

The box model is the basic unit in the visual formatting model and an essential part of the CSS layout model

The CSS box model describes a rectangular box generated for elements in the document tree and laid out according to the visual formatting model

(Quoted from 8 box model)

Therefore, the box model is also the first level of abstraction established by CSS on top of the document tree, and is the part where CSS layout control is directly related to document elements. Consolidation of margins is one of the factors that directly affect vertical formatting. It is necessary to understand

1. Classic scenario In the
following example, it is assumed that the UA does not have a default style sheet, and the undeclared style attributes are taken to their initial values ​​according to the specification

In addition, it is assumed that UA complies with the CSS specification

1. Merge margins between list items


li {
    margin: 8px;
}
那么列表项之间的间距是多少?

.li-case1 li {
    margin: 8px;
    /* 添个上内边距 */
    padding-top: 1px;
}

.li-case2 li {
    margin: 8px;
    /* 添个下边框 */
    border-bottom: 1px solid;
}

What is the spacing between list items in case1 and case2?

2. Deep nested margin merge


/* 缩进表示对应文档结的构嵌套关系 */
div.outer,
  div.container,
    div.content,
      div.inner {
    margin: 10px;
    min-width: 100px;
    min-height: 100px;
}

What is the rendering result of these 4 nested divs?


div.outer,
  div.container,
    div.content,
      div.inner {
    margin: 10px;
    min-width: 100px;
    min-height: 100px;
    /* 添个border */
    border: 1px solid;
}

now what?


div.outer,
  div.container,
    div.content,
      div.inner {
    margin: 10px;
    /* 删掉min-width, min-height和border */
}

What about now?

3. Combination of margins with gaps


div.container {
border-top: 1px solid;
background: #ccc;
margin-bottom: 60px;
}
/* 缩进表示对应文档结的构嵌套关系 */
div.float {
float: left;
width: 100px;
height: 50px;
}
div.following-float {
clear: left;
margin-top: 50px;
}
div.following-container {
color: red;
}

What is the distance between the top of the red text and the bottom of the .following-float?


div.container {
    border-top: 1px solid;
    background: #ccc;
    margin-bottom: 60px;
}
  /* 缩进表示对应文档结的构嵌套关系 */
  div.float {
      float: left;
      width: 100px;
      height: 50px;
  }
  div.following-float {
      clear: left;
      /* 把50改成49 */
      margin-top: 49px;
  }
div.following-container {
    color: red;
}

now what?

How about changing 50 to 0 and 51? What will happen separately?

PS The answer to these questions is still unknown at the moment, because the Demo has not yet started to write ;-) Then there is enough time for us to guess carefully

2. Merge conditions
What kind of margins will merge?

The horizontal margins are not merged. Adjacent vertical margins will be merged, except for 2 special cases:

The outer margins of the root element box are not merged

If the top margin of an element with a gap is adjacent to the bottom margin, its margin will be merged with the neighboring margin of the next sibling (element), but will not be merged with the parent block after the merge. Bottom margin merge

No. 1 skip, applying margins to the root element is not reasonable

Article 2 introduces a new concept called "clearance". The English name is clearance. It seems to be related to the clear attribute, but it is actually intuitive. It refers to the gap formed by the movement of the element position caused by the clear attribute. See CSS Specification 9 Visual Formatting Model. Two key points are implied:

Has the clear attribute

And (clear attribute) moved the position of the element

If these two conditions are met, it is said that an element has a gap

Note: If the clear attribute is applied, the actual position of the element does not change. For example, if the element is placed at that position through margin-top, the layout position of the element itself is the same as the clear effect position (that is, the clear attribute does not bring extra space Occupation, the so-called gap), there is no gap. Conversely, if the application of the clear attribute causes the actual position of the element to change, that is, a part of the space above the element is brought by the clear attribute, even if there is a gap

With a gap is not enough, but the upper and lower margins of the element are adjacent (meaning that the actual height of the element is 0, and there is no padding, border), and if it is satisfied at the same time, the combination of the outer margins of this element will be restricted: Only merge with the adjacent margin of the next brother, the merged result will not be merged with the lower margin of the parent block

PS There is a ticket to challenge the classic scene 3 here, but it is still far away

Definition of "adjacent" When
two outer margins are considered "adjacent"?

All belong to in-flow block-level boxes, in the same block formatting context

There is no line box, gaps, padding and borders to separate them

All belong to the vertical-adjacent box edges (vertically-adjacent box edges)

3 sentences and 4 new concepts, give priority to depth

Stream
Stream / outer stream (in-flow / out-of -flow) refers to whether a conventional flow scheme layout of the positioning element

Continue to depth first, there are 3 types of positioning schemes:

Regular flow. Including block formatting, inline formatting and relative positioning

float. Take out from the position of the regular stream to move left/right

Absolute positioning. Break away from the regular stream and determine its position according to its containing block

The element has neither float (the application value of the float attribute is none), nor absolute positioning (the application value of the position attribute is not absolute), and it is not the root element, then it is laid out according to the regular flow, and it belongs to the element in the flow, otherwise it is Outflow element

Block formatting context
floats, absolutely positioned elements, block containers that are not block boxes (such as inline-blocks, table-cells, and table-captions), and block boxes whose'overflow' is not'visible' (when the value has been (Except when propagating to the viewport) will establish a new block formatting context for its content

In a block formatting context, boxes are placed one after another in the vertical direction, starting from the top of the containing block. The vertical distance between two sibling boxes is determined by the'margin' attribute

In other words, if no one creates a new BFC, then it is in the current BFC. Like the JS scope, everyone is located in the outermost scope (outermost block formatting context) by default. When encountering ordinary block-level boxes, they are placed in the block formatting context. When encountering special (floating, absolute positioning, etc.) Etc.) Just create a new layer of scope (create a new block formatting context), and the elements in it are put into this inner scope (new block formatting context)

After the layout is completed, from the perspective of the formatting context, it is a series of nested BFCs, each BFC is responsible for managing the layout of a set of block boxes (or block-level elements)

Note: The inline formatting context is not mentioned here, because it doesn't make much sense to distinguish different inline formatting contexts (in the specification definition, there is no special scene about the interline formatting context). So, when will a new inline formatting context be created? According to the specification, a new inline formatting context is created only when the block container contains only inline level boxes, unlike BFC which can be explicitly forced to create

PS For more discussion about when a new inline formatting context will be created, please see When does a box establish an inline formatting context?


A rectangular area containing boxes from the same row is called a row box

A line box is always high enough to hold all the boxes it contains.

The line box is an abstract representation of the line in CSS, and each line element is in the same line box. If it is too long to fit and automatically wrap, then another line box will be created for the next line. On the other hand, the line box is not a purely abstract definition, it has a width and a height, used to determine the line layout

The "no line frame" between adjacent margins can be simply understood as no inline elements to separate them from

vertical adjacent frame boundaries. The

following four scenarios satisfy the situation that the external margins are all vertically adjacent frame boundaries:

The upper margin of the box and the upper margin of the first in-flow child

The bottom margin of the box and the top margin of the next sibling in the next stream

The bottom margin of the child in the last stream and the bottom margin of the parent element whose height is calculated as'auto'

The upper and lower margins of the box require that the box has not established a new block formatting context, and the calculated value of'min-height' is 0, the calculated value of'height' is 0 or'auto', and there are no children in the stream.

It seems too long. Let's simplify the conditions and assume that all elements are in the stream. Then:

Parent-child: the margin on the parent element and the margin on the eldest child

Siblings: the bottom margin of the element and the top margin of the right brother

Father and son: Yaoer's bottom margin and parent element's bottom margin

Self: 0 Upper margin and lower margin of high "vacuum" element

PS "Vacuum" here refers to the vacuum of potato chips. Either there is nothing in it, or the children in the exile have been taken away

In other words, the definition of the position of "adjacent margins" is specifically divided into three situations: father and son, brother and self (the combination of the upper and lower margins of itself is quite peculiar)

Re-understanding the combination of "adjacent" and outer margins
has laid the foundation for the previous concept. Now we integrate the scattered points, and first redefine "adjacent":

Parent and child, brothers, or the margins of the element themselves are "adjacent" if they are close together

There is another key point: close to each other. That is to say, the two outer margins are not separated by the "wall", which can be divided into 3 types:

Race: Both parties must be in-stream block-level boxes

Belief: Being in the same block formatting context

Region: There is no line box, gap, inner margin and border between the two

At this point, "adjacent" is already very clear, let's reverse the definition of margin merge:

The adjacent vertical margins of non-root elements will be merged, if there is a gap, the merge is limited

Restricted means that if the upper and lower margins of the element with a gap are adjacent to each other, it can only be merged with the outer margin of the sibling element, and cannot be merged with the lower margin of the parent element.

3. Inferences
on merger conditions According to the conditions for the merger of margins, there are 8 inferences:

The margins between a floating box and any other boxes will not merge (not even between a floating box and its in-stream children)

The margins of elements that establish a new block formatting context (for example, floating boxes and elements whose'overflow' is not'visible') will not merge with their in-flow children

The margins of absolutely positioned boxes will not merge (not even with their in-stream children)

The margins of inline block boxes will not be merged (not even with their in-stream children)

The lower margin of the block-level element in the stream will always be merged with the upper margin of its next in-stream block-level sibling, unless the sibling (element) has a gap

The upper margin of the block-level element in the stream will be merged with the upper margin of its first in-stream block-level child, provided that the element has no upper border and upper inner margin, and its children have no gaps

The lower margin of an in-stream block-level box whose'height' is'auto' and'min-height' is 0 will be merged with the lower margin of its last in-stream block-level child, provided that the box has no lower margin Margin and bottom border, and the bottom margin of its children is not merged with the top margin with gap

The outer margins of the box itself will also be merged, provided that the'min-height' property is 0, there is neither a top-bottom border nor a top-bottom inner margin, and the'height' is 0 or'auto', and there is no line box, then The margins of all children in the stream (if any) will be merged

Simplified summary, but 4 items:

Non-in-stream (absolute positioning or floating) do not merge

Trigger the creation of a new BFC (floating, absolutely positioned elements, block containers that are not block boxes, and certain block boxes whose'overflow' is not'visible') not merged with children

Non-block-level boxes (inline blocks) are not merged

In general, the bottom and top margins of sibling elements, the top and bottom margins of parent and child elements, and the top and bottom margins of the element itself will merge

The first 3 points are aimed at the preconditions of "adjacent" (in-stream, same BFC, block-level box), and the fourth point is the paraphrase of 4 kinds of "adjacent" scenes. The expansion is 8 inferences.

4. Merge behavior After
two adjacent margins are merged, the resulting margin is called folded margin

PScollapsed margin is deliberately translated as folding to indicate the result, separate from the combined action

There are 2 characteristics of margin merge:

Recursion: that is, deep merge. After merging once, check whether the outer margins adjacent to the merged result can be merged, if so, then merge

Greed: Pursue the widest merge result. Two margin positive values ​​take the maximum value, two negative values ​​take the maximum absolute value

For recursive characteristics, the definition of "adjacent" extends a recursive formula:

The folded margin can also be adjacent to another margin, as long as any part of its margin is adjacent to that margin

Greed is related to the calculation method of the merged result of the margin, because the margin allows negative values, the situation is a little more complicated:

Both are positive values, directly find the maximum of the two

One positive and one negative, add and sum

Both are negative, find the maximum of the absolute value of the two

E.g:


ul {margin-bottom: -15px;}
  /* 缩进表示对应文档结的构嵌套关系 */
  li {margin-bottom: 20px;}
h1 {margin-top: -18px;}

Then the vertical distance between h1 and the last li is 20 + -max(|-15|, |-18|) = 2px

Regardless of whether the positive value or the negative value, the principle of seeking the maximum value is to make the merge result as wide as possible (a negative value with a larger absolute value can shift the content of the element farther), that is, greedy.

5. Online Demo

Demo address : Http://ayqy.net/temp/margin-collapse.html

PS answers are in the Demo, explanations are in the source code

Reference material
When does a box establish an inline formatting context?: Question comments are valuable and help understand the inline formatting context

Margin collapse and clearance:clearance的示例

Example of merging margins with gaps: Use Firefox to view, because Chrome and Safari don’t follow the specifications

Collapsing Margins: You don’t need to read this after reading this article

Guess you like

Origin blog.51cto.com/15080030/2592687