CSS Spec - Atomic Inline Level Boxes

CSS Spec - Atomic Inline Level Boxes

It means that the box is a singular, solid unit, and that it cannot be split across lines like an inline box can when its text cannot all fit on a single line. See section 9.4.2 which describes this splitting behavior and the terms "inline formatting context" and "line box".

If there is no longer any space on a line to fit an atomic inline box, the entire box wraps to the next line if there is a line break opportunity (otherwise it overflows the line box), even if the atomic inline box contains inline content that would partially fit the remaining space on the current line. This is because the inline content of an atomic inline doesn't participate in the same inline formatting context as the atomic inline itself — it participates in a separate inline formatting context within the atomic inline box, and therefore must remain within the boundaries of the atomic inline box.

Compare:



p {

width: 5em;

background-color: #f0f0f0;

}

span {

background-color: #d0d0d0;

}

.inline-block {

display: inline-block;

width: 4.5em;

}
<p>text <span class=inline>inline text</span> more text

<p>text <span class=inline-block>inline block</span> more text

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.

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.

Are Block-Level Boxes Enclosed in Line Boxes?

I'm not actually sure if a block-level box can be said to be adjoining to a line box (or vice versa). However, in your example, there are in fact two line boxes — one that is generated by div.one when formatting its inline contents by establishing an inline formatting context, and another that is generated by the body element when formatting span.two (and its span.three child) — and the line box inside div.one can be said to be adjoining to the one containing span.two and span.three.

For the purposes of drawing inline boxes, it doesn't matter which block container is generating each line box that's adjoining to those containing those inline boxes. It doesn't even matter whether any of the block containers also establishes a block formatting context. That is why you see the inline box of span.three bleed into the line box inside div.one.

A block-level box cannot directly coexist with a line box, and by definition of "block-level" it cannot be enclosed in a line box either (to answer your title). In your example, the line box on which the spans are rendered resides in an anonymous block box that is then laid out as a sibling of the div. That anonymous block box establishes its own inline formatting context for the spans, just like the div does for its text.

Why do consecutive spans overflow their line box?

You need to consider line breaking to understand what is happening

When inline-level content is laid out into lines, it is broken across line boxes. Such a break is called a line break. When a line is broken due to explicit line-breaking controls (such as a preserved newline character), or due to the start or end of a block, it is a forced line break. When a line is broken due to content wrapping (i.e. when the UA creates unforced line breaks in order to fit the content within the measure), it is a soft wrap break. The process of breaking inline-level content into lines is called line breaking.

it's clear that you don't have any "forced line break" and no "soft wrap break" as well.

Wrapping is only performed at an allowed break point, called a soft wrap opportunity. When wrapping is enabled (see white-space), the UA must minimize the amount of content overflowing a line by wrapping the line at a soft wrap opportunity, if one exists.

white-space is only used to either allow or not the wrapping but not to force the wrapping. For this you need to consider other properties:

While CSS does not fully define where soft wrap opportunities occur, some controls are provided to distinguish common variations:

  • The line-break property ...
  • The word-break property ...
  • The hyphens property ...
  • The overflow-wrap ...

I won't dig into them but you can keep reading to understand how each one affect the wrapping

Examples:

.box {
margin:5px;
border:1px solid;
width:150px;
}
<div class="box">
<span>Hello.</span><span>Hallo.</span><span>Hello.</span><span>Hallo.</span><span>Hello.</span>
</div>
<div class="box" style="word-break:break-all">
<span>Hello.</span><span>Hallo.</span><span>Hello.</span><span>Hallo.</span><span>Hello.</span>
</div>
<div class="box" style="overflow-wrap:break-word">
<span>Hello.</span><span>Hallo.</span><span>Hello.</span><span>Hallo.</span><span>Hello.</span>
</div>
<div class="box" style="line-break: anywhere">
<span>Hello.</span><span>Hallo.</span><span>Hello.</span><span>Hallo.</span><span>Hello.</span>
</div>

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.

CSS Spec: block-level box, block container box and block box

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.

Why does the extra space between two inline-elements get filled with background-color, but it doesn't for the space between two inline-block elements?

Your answer is within the specification.

For each inline (including anonymous inlines; see [CSS2] section 9.2.2.1) within an inline formatting context, ...

Any collapsible space immediately following another collapsible space—even one outside the boundary of the inline containing that space, provided both spaces are within the same inline formatting context—is collapsed to have zero advance width. (It is invisible, but retains its soft wrap opportunity, if any.)

It's a bit complex but in the case of inline element the spaces will collapse into one space that will be inside the first inline element and not between both inline element. This is because you had a space at the end of your inline element. In other words, all the spaces will collapse into the first one and the position of the first space will decide about the visual.

Remove the space at the end of your inline elements and you will have a different result:

.div1 {
display: inline;
background-color: lightblue;
}

.div2 {
display: inline;
background-color: orange;
}
<div class="box">
<div class="div1"> Lorem ipsum </div>
<div class="div2"> Lorem ipsum </div>
</div>
<div class="box">
<div class="div1"> Lorem ipsum</div>
<div class="div2"> Lorem ipsum </div>
</div>


Related Topics



Leave a reply



Submit