CSS Visual Formatting Model
W3C: https://www.w3.org/TR/CSS2/visuren.html
MDN: https://developer.mozilla.org/docs/Web/Guide/CSS/Visual_formatting_model
Diagram
(Anonymous) Block Box
Atomic Inline-level Box
Inline-level Box(Anonymous) Inline Box
Inline Formatting Context
display { block | list-item | table }
Replaced Block-level Element, Table Element
Establish: Block Formatting Context (BFC)
Establish: Inline Formatting Context (IFC)
Non-replaced Inline Block, Non-replaced Table Cells
Replaced Inline-level Element, Inline-table Element
display { inline | inline-block | inline-table }
Non-replaced Inline Element
Case 1: Block-level Element in Inline-level Element
[W3C] When an inline box contains an in-flow block-level box, the inline box (and its inline ancestors within the same line box) are broken around the block-level box (and any block-level siblings that are consecutive or separated only by collapsible whitespace and/or out-of-flow elements), splitting the inline box into two boxes (even if either side is empty), one on each side of the block-level box(es). The line boxes before the break and after the break are enclosed in anonymous block boxes, and the block-level box becomes a sibling of those anonymous boxes.
<span> <span>Inline-level Element</span> <p>Block-level Element</p> Inline Text </span>
Block-level Element
Inline TextCase 2: float
vs display:inline-block
[W3C] However, the current and subsequent line boxes created next to the float are shortened as necessary to make room for the margin box of the float.
<div> <span style="float: left;">Float Box</span> <p style="display: inline-block;">Atomic Inline-level Box</p> </div>
Atomic Inline-level Box
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aspernatur quas quisquam beatae illo, sit aliquid. Debitis architecto distinctio perspiciatis commodi!
Lorem ipsum dolor sit amet commodi!
Atomic Inline-level Box
Case 3: float
vs overflow:hidden
[W3C] The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with ‘overflow’ other than ‘visible’) must not overlap the margin box of any floats in the same block formatting context as the element itself.
<div> <span style="float: left;">Float Element</span> <p style="overflow: hidden;">Block-level Element</p> </div>
Lorem ipsum dolor sit amet commodi!
Block-level Element [MDN]
- Condition:
display
{block
|list-item
|table
} - Genarate: Block-level Box (Principal + Additional)
Inline-level Element [MDN]
- Condition:
display
{inline
|inline-block
|inline-table
} - Genarate: Inline-level Box
Block-level Box [W3C]
Participating in Block Formatting Context
1. Block Box
Block-level Box ∩ Block Container Box
- Exculde: Table Box, Replaced Element
2. Anonymous Block Box
3. Block Container Box
Contains only Block-level Box or only Inline-level Box
- Inculde: Non-replaced Inline Block, Non-replaced Table Cell
Inline-level Box [W3C]
1. Inline Box
Contents participate in container’s Inline Formatting Context
- Condition:
display
{inline
} & Non-replaced Element
2. Anonymous Inline Box
3. Atomic Inline-level Box
Contents not participate in container’s Inline Formatting Context
- Inculde: Replaced Inline-level Element, Inline-block Element, Inline-table Element
Block Formatting Context [W3C, MDN]
- Contain: Block-level Box
Rules
- Begin at the top of Containing Block, boxes are laid out one after the other vertically.
- The vertical distance between two sibling boxes is determined by ‘margin’.
- Vertical Margins Collapsed between adjacent boxes in same BFC.
- Each box’s left outer edge touches the left edge of containing block (vice versa for right-to-left).
This is true even in the presence of floats, unless the box establishes a new BFC.
Conditions
Establish a new BFC for contents
- Floats
float
{left
|right
}
- Absolutely positioned element
position
{absolute
|fixed
}
- Block Container Box that are not Block Box
display
{inline-*
|table-*
} - {table-column
|table-column-group
}
- Block Box with ‘overflow’ other than ‘visible’
overflow
{auto
|hidden
|scroll
}
- Root element or it’s container
<html>
Inline Formatting Context [W3C]
- Contain: Inline-level Box
Rules
- Begin at the top of Containing Block, boxes are laid out one after the other horizontally.
- The boxes may be aligned vertically in different ways:
their bottoms or tops may be aligned, or the baselines of text within them may be aligned.
Line Box
The rectangular area that contains the boxes that form a line
- Line box’s height ≥ tallest box’s height.
- When box’s height < line box’s height, it’s vertical alignment is determined by the ‘vertical-align’.
- When boxes’s total width < line box’s width, their horizontal distribution is determined by the ‘text-align’
- When boxes cannot fit within a line box, they are distributed among two or more vertically-stacked line boxes.
- Line boxes are stacked with no vertical separation (except as specified elsewhere) and they never overlap.
- When an Inline Box exceeds a line box, it is split into several boxes across several line boxes.
It’s margins, borders, and padding have no visual effect where the split occurs.
If it cannot be split (e.g.white-space:nowrap
), then it overflows the line box. - In general, line box’s left edge touches the left edge of containing block (vice versa for right-to-left).
However, floating boxes may come between the containing block edge and the line box edge.