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.
Box Model for Inline Elements
For the second question you may refer to this part of the specification:
The 'height' property does not apply. The height of the content area
should be based on the font, but this specification does not specify
how. A UA may, e.g., use the em-box or the maximum ascender and
descender of the font. (The latter would ensure that glyphs with parts
above or below the em-box still fall within the content area, but
leads to differently sized boxes for different fonts; the former would
ensure authors can control background styling relative to the
'line-height', but leads to glyphs painting outside their content
area.)The vertical padding, border and margin of an inline, non-replaced box
start at the top and bottom of the content area, and has nothing to do
with the 'line-height'. But only the 'line-height' is used when
calculating the height of the line box.
.test { margin: 0 10px; padding: 20px; border: 5px solid blue;}
div { border:1px solid red; margin:50px 0;}
<div><span class="test">test2test2test2test2test2test2test2 test</span></div>
<div><span class="test">test2test2test2test2test2test2test2 test st2test2test2test2 test st2test2test2test2 test st2test2test2test2 test</span></div>
<div><span class="test" style="line-height:50px;">test2test2test2test2test2test2test2 test2test2</span></div>
<div><span class="test" style="line-height:50px;">test2test2test2test2test2test2test2 test2test2 test2test2test2test2test2test2test2 test2test2</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.
Box model properties on anonymous inline boxes
No; since margins, borders and padding are not inherited properties, and you cannot style anonymous boxes directly with CSS (not even with the universal selector, or pseudo-elements), anonymous inline boxes cannot have margins, borders or padding.
Line boxes cannot have margins, borders or padding either.
Inline anonymous boxes?
Section 9.2.2.1 in the Visual Formatting Model actually has an almost identical example to yours, e.g.
Any text that is directly contained inside a block container element (not inside an inline element) must be treated as an anonymous inline element.
In a document with HTML markup like this:
<p>Some <em>emphasized</em> text</p>
the
<p>
generates a block box, with several inline boxes inside it. The box for "emphasized" is an inline box generated by an inline element (<em>
), but the other boxes ("Some" and "text") are inline boxes generated by a block-level element (<p>
). The latter are called anonymous inline boxes, because they do not have an associated inline-level element.
What you're seeing in Chrome's developer tools is the display value for the element that the anonymous boxes lives in, not of the inline boxes themselves. They're all actually inline boxes, but "In 1912"
& "sank on her maiden voyage"
would be anonymous while the <em>
element would create a non-anonymous inline box as it is an inline-level element.
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 span
s 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 span
s, just like the div
does for its text.
Inline elements and line-height
This might be confusing because in the inline formatting model there are different heights.
Height of an inline box
An element with display: inline
generates an inline box:
An inline box is one that is both inline-level and whose contents
participate in its containing inline formatting context. A
non-replaced element with adisplay
value ofinline
generates an
inline box.
And line-height
determines the height of that box:
The height of the inline box encloses all glyphs and their
half-leading on each side and is thus exactly 'line-height'
Therefore, your box is, in fact, 15px
tall.
Height of a line box
There are also line boxes:
In an inline formatting context, boxes are laid out horizontally, one
after the other, beginning at the top of a containing block.
Horizontal margins, borders, and padding are respected between these
boxes. 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. The rectangular area that contains the boxes that form
a line is called a line box.The height of a line box is determined by the rules given in the
section on line height calculations.
In case a line box only contains non-replaced inline boxes with the same line-height
and vertical-align
, those rules say that the height of the line box will be given by line-height
.
So in your case, this is also 15px
.
Height of the content area of an inline box
However, the developer tools of your browser said 18px
. That's because those 18px
are the height of the content area. It's also this content area (together with paddings) which is painted by the green background.
Note those 18px
might vary because CSS 2.1 doesn't specify an algorithm:
The height of the content area should be based on the font, but this
specification does not specify how. A UA may, e.g., use the em-box or
the maximum ascender and descender of the font. (The latter would
ensure that glyphs with parts above or below the em-box still fall
within the content area, but leads to differently sized boxes for
different fonts; the former would ensure authors can control
background styling relative to the 'line-height', but leads to glyphs
painting outside their content area.)
If an UA implements the first suggestion, the content height will be given by font-size
, which determines the em-box. This would what you expected, with the green box being 15px
tall.
However, most UAs don't seem to do that. That means that, probably, the height will be the height of the tallest glyph in the font-family
and font-size
used.
But using a font-size
value of 15px
doesn't mean that the tallest glyph will be 15px
tall too. That depends on the font. This is somewhat analogous to normal
, the initial value of line-height
, which is defined as
Tells user agents to set the used value to a "reasonable" value based
on the font of the element[...]. We recommend a used value for
'normal' between1.0
to1.2
.
That means that, if you use font-size: 15px
, a "reasonable" line-height
would be between 15px
and 18px
. In the "Verdana" font, Firefox thinks the best is 18px
; in the "sans-serif", it uses 17px
.
`padding` and `border` for inline elements being shown
The vertical padding, border and margin of an inline, non-replaced box start at the top and bottom of the content area, and has nothing to do with the 'line-height'. But only the 'line-height' is used when calculating the height of the line box.
https://www.w3.org/TR/CSS22/visudet.html#inline-non-replaced
padding, margin and border exists but have no influence on the calculation of the line box height. Margin cannot be seen unlike padding border but it does exist. You can notice it when you inspect the element.
Related Topics
Sass/Scss @Extend Rule Selectors
Browser as a Design Tool - Change Colors, Save Them
Animating a Smooth CSS Grid-Column Change
Css: Problems When Using Object-Fit and Transform Together on Webkit
How to Set Maximum Number of Rows in a Flexbox Container and Hide Extra Element
Google Fonts Font-Weight of 100 Is Not Working
Adding CSS Border Changes Positioning in HTML5 Webpage
Styling HTML5 Number Input (Spin Box) in Chrome
Does a Cache Buster on an Image Url in CSS Cause an Extra Request
Did Chrome 40 Break Justify-Content CSS Overriding
Why Does Fixed Positioning Alter the Width of an Element
How to Use CSS to Distort Borders So They Look Like Sketched
Putting Emoticons in Paragraphs Without Affecting 'Line-Height'
CSS Negative Margins for Positioning