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.
Related
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 am reading CSS specs, the section on Visual Formatting Model and trying to understand what is the difference between these two terms: containing block and block container box.
What confuses me is the variation of words that are used for what seems to be completely different concepts:
box vs block
containing vs container
Is block same as box when talking about visual formatting CSS? If not, what is the difference? Are both of these something that is "visible" on the screen?
In general, how should I think when I see block in the specification? Also what should first come to my mind when I read box in the specs?
Some helpful metaphors or analogies for these concepts would be very helpful to create a mental model.
Let's start at the beginning. CSS is almost entirely about boxes. A box is just a rectangular area of the canvas. The canvas is the entire 2D space on which everything is drawn.
CSS Boxes have a whole range of flavours. Block boxes, block-level boxes, inline boxes, inline-level boxes, content boxes, padding boxes, border boxes, margin boxes, table boxes, line boxes, flex boxes, and so on. They're all just rectangular areas.
So a block is just one type of box. Many of the above boxes are characterized by two behaviours - how they are laid out relative to their containers and peers, and how their content is laid out within them. The CSS-display spec refers to these as display-outside and display-inside respectively
Display-outside refers to the "*-level" nature of the boxes. They're not what we're interested in here.
All block boxes, and some inline-level boxes are block container boxes. A block container box is a box of type "block container", not necessarily a box that contains blocks. Block containers that are not block-level boxes include those that are display:inline-block and display:table-cell
The "block" in "block container" refers to its display-inside behaviour. Block boxes are laid out vertically within them and text flows horizontally, ordinarily limited by its edges of the rectangle.
So a "block container box" is a type of box. In contrast, "containing block" refers to a specific box. Each box defined on the canvas has exactly one containing block, with just one exception, called the initial containing block, which has no containing block.
Only a box of type "block container box" can be a box's containing block.
Time for an example. Let's suppose we have the HTML below: I'm deliberately going to use <span> elements throughout, because this is all about CSS, and I don't want to confuse with HTML behaviour.
<span id="level1">
foo
<span id="level2">
bar
<span id="level3">
baz
<span id="level4">
qux
</span>
</span>
</span>
</span>
The CSS is very simple. Just
#level1 { display:inline-block }
The other spans are the CSS default display setting, "inline".
Now, consider the #level4 span. Its parent is the '#level3' span, which is display:inline so the '#level3' span does not form a block container box. Similarly, the #level2 span also does not form a block container box. But the #level1 element is display:inline-block. That forms an inline-level box, but one that is a block container box. (This is what "inline-block" means).
So the containing block for all the inline boxes formed by the #level2, #level3, #level4 spans and their text content is the block container box formed by the #level1 element's box.
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 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.