What's the Difference Between a Block-Level Box and a Principal Block-Level Box

What's the difference between a block-level box and a principal block-level box?

A principal block-level box is the block-level box generated by a given element that's directly affected by style rules that apply to the element.

Most elements generate only one box. For these elements, they are essentially the same thing, since there are no other boxes involved.

However, an element can generate more than one box depending on its display type, such as a list item; when you declare styles for such an element, the styles are typically applied to the principal box and any additional boxes that are generated will be rendered accordingly.

For example, a list item has a marker box in addition to the principal box; if you specify list-style-position: outside, the list marker will be placed outside the boundaries of the principal box but the background and borders of the principal box won't be affected. Note that the marker box is still a descendant of the principal box, so inheritable properties such as color will apply to the marker (this is why color: red turns both the text and its bullet marker red).

Most other block-level elements, including display: block but excluding display: table (see section 17.4), will simply generate a principal block box for their content and nothing else, making them essentially just "block boxes", but only for those elements.

In other words, all principal block-level boxes are block-level boxes, but not all block-level boxes are principal, for example anonymous block boxes. Also, inline elements, including inline blocks, do not generate any principal boxes themselves, nor is there such a thing as a principal inline box.

Clarifying definition of block container and block box

HTML elements are not CSS boxes. Zero, one, or multiple boxes are generated for a single HTML element.

The primary concept you're missing is that of an anonymous box.

Suppose you have

<section>
<span>Foo</span>
<div>Bar</div>
Baz
</section>

where section and div are display:block and span is display:inline, just as they are by default.

Now "Bar" and "Baz" get wrapped in anonymous inline boxes, and the span generates an inline box.

Further, because the block box generated by the section element would contain both inline boxes and block boxes, the span and "Baz" inline boxes are wrapped in anonymous block boxes. So the final box tree looks like this.

Block Box             <= from `section` element
+--- Block Box <= anonymous block box
| +--- Inline Box <= from `span` element
+--- Block Box <= from `div` element
| +--- Inline Box <= anonymous inline box from "Bar"
+--- Block Box <= anonymous block box
+--- Inline Box <= anonymous inline box from "Baz"

As you can see from this, no block box contains both a block box and an inline box as direct children, which is what your quoted paragraph is saying.

Contradiction in Definition of Inline-Level Boxes and Inline Boxes (W3C)

There is not a contradiction in the standard, but we have to read carefully to spot the differences.

  1. Inline-level boxes are boxes that participate in an inline formatting context.
  2. An inline box is a inline-level box whose contents participate in its containing inline formatting context

A span-element inside a paragraph is an inline box, because the text inside the span-element participate in the paragraphs' surround content.

An element with display: inline-block; will flow with surrounding content as if it were a single inline box, but since this element actually will generate a block element box, the elements contents do not participate in its containing inline formatting context.

Block containers and the Visual Formatting Model

Your example is broken. The span element is a child element of a paragraph.

Let us use this for the example instead:



<DIV>

Some text

<P>More text</p>

<span>An inline element</span>

<span>An inline element</span>

</DIV>

Identifying Anonymous Block Boxes

Box Generation will treat any boxes inside this block container as a block-level boxes. And by doing so, any boxes that is not a block-level box will be internally/conceptually treated as an anonymous block boxes, which is basically a block-level box anyway.

No, it creates anonymous block boxes with inline formatting contexts, which enclose the inlines. The inlines (or whatever other boxes that aren't block-level boxes) do not change. They continue to participate in the same formatting contexts they normally would; this algorithm ensures those formatting contexts are established by anonymous block boxes, that in turn participate in the same block formatting context as the parent element.

The illustration is mostly correct, with the exception that the principal block-level box doesn't always establish a block formatting context. You may also be getting the terms "block formatting context", "block-level box", "block container box", and "block box" mixed up; see my answers to these questions for additional clarification:

  • CSS Spec: block-level box, block container box and block box
  • Block Level Element vs Block Formatting Context

When does a box establish an inline formatting context?

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.

Do Inline elements establish a Line Box for their content?

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.

Understanding CSS2.1 specification regarding height on inline-level boxes

Is the height of inline-level boxes equal to the line-height property set on them (with the minimum being the line-height set on the parent block container element),

Yes it is.

OR is it just determined by the font height (and UA implementation)?

No it isn't

CSS is really about boxes, not elements, and you should try not to confuse the two.

So an inline element has associated with it a number of boxes. A content box, padding box, border box and margin box. It also has zero (if display:none), one, or multiple inline boxes. The content box, paddings, borders and margins may be divided among the inline boxes so that the inline content can be spread over more than one line.

The inline box's height is the content height adjusted by the leading. It's the leading that does the magic here. The leading is defined as the line-height of the element minus the content height of that inline box.

Simply rearranging that equation tells us that the height of the inline box depends only on the line-height and not on the content box (or padding, border, margin boxes).

Note that none of the above discusses the line box, which is a different thing again and not a direct property of inline elements or their boxes. The line box is constructed by arranging the inline boxes that occur on the same line such that their vertical alignments fit the rules computed for the elements, including the zero width inline box formed by the strut.

Each line box is bounded by the top of uppermost inline box and the bottom of the lowestmost inline box that that line box contains.


Digression: On why the height of the line box can surprise.

Suppose we have a simple case of a containing block which just contains one short inline element (i.e. short enough that it fits in a single line box). Also suppose that everything is aligned on the baseline. Let's say that the line-height is set on the containing box to 20px, and the inline element inherits that. Also suppose that the font-size (em-square) of the containing block is 16px, and that means that the font metrics compute to an ascent (above the baseline) of 14px and a descent (below the baseline) of 4px.

So the content area for the strut is (14px + 4px =) 18px high. The line-height is 20px, so there is 2px leading, 1px goes above the ascent, and 1px below the descent. So the line-height of the strut is made of 15px above the baseline and 5px below the baseline.

Now, suppose that the font-size of the inline element is set to 0.5em (i.e. half that of the containing block). The content area for the inline element will be an ascent of 7px and a descent of 2px. The line-height is still 20px, so the leading is 20px - (7px + 2px) = 11px, meaning that 5.5px goes above the ascent and 5.5px goes below the descent. This results in the line-height for the inline element is made of 12.5px above the baseline and 7.5px below the baseline.

Since the strut and the inline element are aligned vertically to their baselines, the top of the uppermost inline box (the strut) is 15px above the baseline and the bottom of the the lowermost inline box (the inline element) is 7.5px below the baseline, the actual height of the line box is not 20px but (15px + 7.5px =) 22.5px.

Is marker box of an list-item generated inside of the principal box or next to it?

The property list-style-position determines whether the marker box is next to the principal box or inside it.

The values are outside and inside respectively. The default is outside.



Related Topics



Leave a reply



Submit