I am reading CSS Spec 2.1 and find the concepts hard to distinguish:
Except for table boxes, which are described in a later chapter, and replaced elements, a block-level box is also a block container box. A block container box either contains only block-level boxes or establishes an inline formatting context and thus contains only inline-level boxes. Not all block container boxes are block-level boxes: non-replaced inline blocks and non-replaced table cells are block containers but not block-level boxes. Block-level boxes that are also block containers are called block boxes.
May I interpret the description above as follow?:
Your interpretation is correct.
Here are some additional details:
The reason a table box is not a block container is because it establishes a table layout, not a block layout. Content goes into the cell elements rather than the table element, which is why it is the cell boxes that are block containers rather than the table box itself.
A replaced element doesn't contain any other content and therefore cannot be a block container.
The only difference between a block box and an inline-block is that the former is block-level while the latter is inline-level. Hence the display values display: block and display: inline-block respectively. As both are block containers, there is no difference in how their contents are formatted.
Note that replaced elements and table boxes can be either inline-level or block-level. Inline tables and inline replaced elements are simply excluded from the section you quote because that section only pertains to block-level boxes; you'll find references to them elsewhere in section 9, or in sections 10 and 17 respectively.
Also, even though a block container box can only either contain block-level boxes or inline-level boxes, you can still mix both in the same block container box; internally it simply segregates the block-level and inline-level boxes via anonymous block boxes.
Remember that HTML is a tree so each node can act as both a parent (of children) and child (of a parent)
Bearing this in mind, things start to make sense, Block-level box refers to box act as chlid
Block-level boxes are boxes that participate in a block formatting
context.
On the other hand, block container box refer to a parent who can contain others
A block container box either contains only block-level boxes or
establishes an inline formatting context and thus contains only
inline-level boxes
Just like a node can either be a child and a parent, an HTML node can either act as a parent(block container box) or child (block-level box) or BOTH
For example, if children in a node are not allowed (replaced element), it can never be a parent, it can only be a child (Block-level boxes) at most, not a parent (block container box)
And there is no reason to prevent a non-block parent contain a block parent. An inline-block itself is not a block, but it can contain block-level box
The point is a spec is easier to understand from a parent-child view
Related
W3 is very ambiguous about this. I've read everything about Inline-boxes, Line-boxes, anonymous boxes, block-boxes and all kinds of boxes, but nowhere is explicitly stated whether line boxes are formed inside inline-level elements.
W3 states that
"line box is the rectangular area that contains the (inline)boxes that
form a line".
Then it says that
"Line boxes are created as needed to hold inline-level content within
an inline formatting context"
So far, it seems that inline elements do contain line boxes, as they can contain inline-boxes, and their content participates in an inline formatting context.
However then it states that
Any text that is directly contained inside a block container element
(not inside an inline element) must be treated as an anonymous inline
element.
So, therefore, the text inside an inline-level element like span is not being wrapped inside an anonymous inline box.
Then they give the example of <P>Several <EM>emphasized words</EM> appear <STRONG>in this</STRONG> sentence, dear.</P> and explain that
The P element generates a block box that contains five inline boxes,
three of which are anonymous. To format the paragraph, the user agent
flows the five boxes into line boxes. In this example, the box
generated for the P element establishes the containing block for the
line boxes. If the containing block is sufficiently wide, all the
inline boxes will fit into a single line box. If not, the inline boxes
will be split up and distributed across several line boxes.
This explanation is confusing because the first sentence states that P generates a block-box that contains the inline-boxes, but the second sentence states that the containing block generated by the P element contains the line boxes.
Block box is a block container that is also a block-level box. So, inline-elements don't generate block boxes, but apparently they generate containing blocks. Are block-boxes and containing blocks the same thing in this context?
Since an inline-level box, like Span can contain other inline-boxes, like strong or em, that means that inline-level elements can also be block containers, but they don't form block boxes (or do they?), and their text content does not get wrapped inside an anonymous box.
It is stated that the Inline-boxes do have a containing block, but it is also explicitly stated that the line-boxes are contained inside the block-box, not the containing block.
So, are they the same? .. and does that mean that inline-level boxes like span also form a line box? If so, why doesn't the text inside inline-boxes get wrapped inside an anonymous inline box?
If line boxes only exist inside the block box, and if containing blocks are not block boxes, then that would mean that inline elements do not form line boxes for their content.
I wish W3 would be more explicit with their explanation.
Your heading and first paragraph ask two different questions:
Do Inline elements establish a Line Box for their content?
[Are] line boxes are formed inside inline-level elements?
They have different answers, "No", and "Sometimes" respectively, so the first thing that needs to be dealt with is the -level suffix.
An inline-level box is a broader category than an inline box. A span element which contains only text generates, by default, a sequence of inline boxes sufficient to lay out that text content over as many lines as is necessary. All inline boxes are also inline-level boxes, but the opposite is not true. Elements whose computed display is inline-block, inline-table, inline-flex and inline-grid all generate boxes that are inline-level, but are not inline boxes.
Similar applies to block versus block-level. Block-level describes how a box lays out relative to its parents and siblings. Block containers are boxes in which their child boxes are laid out either as sequence of block-level boxes, or within a stack of line boxes, and never as a mixture of both.
Elements whose computed display value is block, flow-root and list-item and are being laid out in a block formatting context (i.e. they're not a flex item or a grid item) generate a single box that is both block-level and a block container. These are called block boxes.
But boxes generated for elements that have computed display values of table, flex, and grid are block-level, but they are not block containers. Their descendants are laid out using different rules. These are not block boxes.
Conversely, elements that have computed display values of inline-block and table-cell generate boxes that are block containers but they are not block-level. They interact with their parents and siblings differently than block level boxes do.
So, specifically, inline-block boxes, which are inline-level, contain either a sequence of block-level boxes, or a stack of line boxes in which other inline-level boxes are laid out.
Now, an inline box can contain other inline-level boxes, but that does not make it a block container, even if one of those inline-level boxes is itself a block container. The block container of the inline box and all its descendant inline-level boxes that are not themselves inside other formatting contexts is the nearest ancestor that is a block container.
So, suppose we have this tree of boxes
display:block block level, block container
| ↑ ↑
+ - display:inline inline level ---------+ | \
| | |- In the same line box
+ - display:inline-block inline level, block container /
| ↑
+ some text anonymous inline box --+ in a line box
where the arrows point from inline-level boxes to their block container.
I am reading CSS Spec 2.1 and find the concepts hard to distinguish:
Except for table boxes, which are described in a later chapter, and replaced elements, a block-level box is also a block container box. A block container box either contains only block-level boxes or establishes an inline formatting context and thus contains only inline-level boxes. Not all block container boxes are block-level boxes: non-replaced inline blocks and non-replaced table cells are block containers but not block-level boxes. Block-level boxes that are also block containers are called block boxes.
May I interpret the description above as follow?:
Your interpretation is correct.
Here are some additional details:
The reason a table box is not a block container is because it establishes a table layout, not a block layout. Content goes into the cell elements rather than the table element, which is why it is the cell boxes that are block containers rather than the table box itself.
A replaced element doesn't contain any other content and therefore cannot be a block container.
The only difference between a block box and an inline-block is that the former is block-level while the latter is inline-level. Hence the display values display: block and display: inline-block respectively. As both are block containers, there is no difference in how their contents are formatted.
Note that replaced elements and table boxes can be either inline-level or block-level. Inline tables and inline replaced elements are simply excluded from the section you quote because that section only pertains to block-level boxes; you'll find references to them elsewhere in section 9, or in sections 10 and 17 respectively.
Also, even though a block container box can only either contain block-level boxes or inline-level boxes, you can still mix both in the same block container box; internally it simply segregates the block-level and inline-level boxes via anonymous block boxes.
Remember that HTML is a tree so each node can act as both a parent (of children) and child (of a parent)
Bearing this in mind, things start to make sense, Block-level box refers to box act as chlid
Block-level boxes are boxes that participate in a block formatting
context.
On the other hand, block container box refer to a parent who can contain others
A block container box either contains only block-level boxes or
establishes an inline formatting context and thus contains only
inline-level boxes
Just like a node can either be a child and a parent, an HTML node can either act as a parent(block container box) or child (block-level box) or BOTH
For example, if children in a node are not allowed (replaced element), it can never be a parent, it can only be a child (Block-level boxes) at most, not a parent (block container box)
And there is no reason to prevent a non-block parent contain a block parent. An inline-block itself is not a block, but it can contain block-level box
The point is a spec is easier to understand from a parent-child view
I noticed that people covered specifics of some display properties in a 1:1 comparison, but there are quite a few that have not been covered in illustrating the differences. Could someone explain the differences between the various inline-something display tags?
A more elaborated definition over places like w3schools would do wonders.
The only difference, for any display type that has block and inline variants, is that the inline-* display type has the box laid inline (i.e. in an inline formatting context) while the other has the box formatted as a block-level box, subject to most of the same formatting conventions as other block-level elements in a block formatting context. The difference between a block-level box and an inline-level box is covered in depth elsewhere.
Everything concerning how the box lays out its contents is pretty much the same (the specifics of which, of course, are governed by the display type itself); any other nuanced differences would have been stated explicitly in the spec. As far as I'm aware, there are in fact no such differences.
When in doubt, prefer block-level display types. If you find yourself asking whether inline-level is appropriate, chances are the answer is no. Certain scenarios may prevent a box from ever being formatted as an inline-level box anyway, such as absolute positioning or floating, or being formatted as a flex item or grid item instead. The result is a direct conversion from the inline-* variant to its usual block variant. That is, inline-block is converted to block, inline-table to table, inline-flex to flex, and inline-grid to grid. Again, this does not directly affect how an element's contents are formatted, not as far as the specifications go.
Examples of each display type and its inline-level counterpart follow.
In CSS2.1, section 9.2.4 describes block and inline-block as follows:
block
This value causes an element to generate a block box.
inline-block
This value causes an element to generate an inline-level block container. The inside of an inline-block is formatted as a block box, and the element itself is formatted as an atomic inline-level box.
Note that "block box" is a shorthand for "block-level block container", and a block container is something that can contain block-level boxes.
You can see that both of these two values cause an element to generate a block container box, in which its contents will always follow the same set of formatting rules, but that block container box itself is either formatted as block-level, or inline-level.
There is one additional difference between block and inline-block: an inline-block box always establishes a new block formatting context; block boxes only do so under a set of conditions. This does not hold true for any of the other display types that have block-level and inline-level counterparts.
Section 17.2 describes table and inline-table as follows:
table (In HTML: TABLE)
Specifies that an element defines a block-level table: it is a rectangular block that participates in a block formatting context.
inline-table (In HTML: TABLE)
Specifies that an element defines an inline-level table: it is a rectangular block that participates in an inline formatting context).
The Flexbox module describes flex and inline-flex as follows:
flex
This value causes an element to generate a block-level flex container box.
inline-flex
This value causes an element to generate an inline-level flex container box.
And the Grid Layout module describes grid and inline-grid as follows:
grid
This value causes an element to generate a block-level grid container box.
inline-grid
This value causes an element to generate an inline-level grid container box.
Again, in all of these scenarios, a table, a flex container, or a grid container will behave exactly the same way whether it is block-level or inline-level. A flex container always establishes a flex formatting context for its flex items, and a grid container always establishes a grid formatting context for its grid items.
I noticed that people covered specifics of some display properties in a 1:1 comparison, but there are quite a few that have not been covered in illustrating the differences. Could someone explain the differences between the various inline-something display tags?
A more elaborated definition over places like w3schools would do wonders.
The only difference, for any display type that has block and inline variants, is that the inline-* display type has the box laid inline (i.e. in an inline formatting context) while the other has the box formatted as a block-level box, subject to most of the same formatting conventions as other block-level elements in a block formatting context. The difference between a block-level box and an inline-level box is covered in depth elsewhere.
Everything concerning how the box lays out its contents is pretty much the same (the specifics of which, of course, are governed by the display type itself); any other nuanced differences would have been stated explicitly in the spec. As far as I'm aware, there are in fact no such differences.
When in doubt, prefer block-level display types. If you find yourself asking whether inline-level is appropriate, chances are the answer is no. Certain scenarios may prevent a box from ever being formatted as an inline-level box anyway, such as absolute positioning or floating, or being formatted as a flex item or grid item instead. The result is a direct conversion from the inline-* variant to its usual block variant. That is, inline-block is converted to block, inline-table to table, inline-flex to flex, and inline-grid to grid. Again, this does not directly affect how an element's contents are formatted, not as far as the specifications go.
Examples of each display type and its inline-level counterpart follow.
In CSS2.1, section 9.2.4 describes block and inline-block as follows:
block
This value causes an element to generate a block box.
inline-block
This value causes an element to generate an inline-level block container. The inside of an inline-block is formatted as a block box, and the element itself is formatted as an atomic inline-level box.
Note that "block box" is a shorthand for "block-level block container", and a block container is something that can contain block-level boxes.
You can see that both of these two values cause an element to generate a block container box, in which its contents will always follow the same set of formatting rules, but that block container box itself is either formatted as block-level, or inline-level.
There is one additional difference between block and inline-block: an inline-block box always establishes a new block formatting context; block boxes only do so under a set of conditions. This does not hold true for any of the other display types that have block-level and inline-level counterparts.
Section 17.2 describes table and inline-table as follows:
table (In HTML: TABLE)
Specifies that an element defines a block-level table: it is a rectangular block that participates in a block formatting context.
inline-table (In HTML: TABLE)
Specifies that an element defines an inline-level table: it is a rectangular block that participates in an inline formatting context).
The Flexbox module describes flex and inline-flex as follows:
flex
This value causes an element to generate a block-level flex container box.
inline-flex
This value causes an element to generate an inline-level flex container box.
And the Grid Layout module describes grid and inline-grid as follows:
grid
This value causes an element to generate a block-level grid container box.
inline-grid
This value causes an element to generate an inline-level grid container box.
Again, in all of these scenarios, a table, a flex container, or a grid container will behave exactly the same way whether it is block-level or inline-level. A flex container always establishes a flex formatting context for its flex items, and a grid container always establishes a grid formatting context for its grid items.
I read that a block formatting context is created in some cases from MDN:Block formatting context.
I wonder when does a box establish an inline formatting context?
One case I know is: when a block container box contains only inline-level boxes.
To answer your question, I reread Section 9.2.1 of the CSS 2.1 spec.
Based on my reading, you have your answer: the inline formatting context is triggered when a block container box contains only inline elements.
In contrast to a block formatting context that can be triggered explicitly (for example, setting overflow: hidden to a block-level element), an inline formatting context cannot be triggered explicitly.
Inline formatting contexts appear to always exist as descendant block boxes within a "principal block-level box", and these descendant block boxes may be anonymous.
I offer the following description as a mental model for understanding block/inline formatting contexts.
A block-level element (e.g. a <div>) fulfills two responsibilities: one, positioning, and two, content formatting.
When dealing with positioning, a block-level element acts as a "block-level box".
When dealing with formatting, a block-level element acts as a "block container box".
Acting as a "block-level box", the block-element behaves according to the type of positioning (static, absolute, relative, fixed) specified by the position property.
Acting as a "block container box", the block-element establishes a block-formatting context if the block-element has at least one child block-level element. If all the child elements are inline-level boxes, then an inline-formatting context is established.
If the "block container box" contains text and block elements, then the text is treated as being contained in one or more anonymous block-level boxes, and a block-formatting context is established.
Aside
The CSS spec is not exactly light reading. I have reread Chapters 9 and 10 several times and I have yet to come up with a plain-English translation.