1

My question is about the height of inline-block which contains only inline boxes

<div style="display: inline-block; 
            height: auto; 
            border: 1px solid red
"><span style="font-size: 16px; 
               line-height: 16px; 
               background-color: yellow;
">x</span></div>

In the example above I expect the following:

  • The height of the content area of the inline-block would be 16px because it contains only inline elements
  • The height of inline elements determined by "line-height" which equals 16px in my case but in reality, its height 18px

Inline-block element should create block formatting context (MDN):

A block formatting context is created by at least one of the following:

  • the root element or something that contains it
  • floats (elements where float is not none)
  • absolutely positioned elements (elements where position is absolute or fixed)
  • inline-blocks (elements with display: inline-block)
  • table cells (elements with display: table-cell, which is the default for HTML table cells)
  • table captions (elements with display: table-caption, which is the default for HTML table captions)
  • anonymous table cells implicitly created by the elements with display: table, table-row, table-row-group, table-header-group, table-footer-group (which is the default for HTML tables, table rows, table bodies, table headers and table footers, respectively), or inline-table
  • block elements where overflow has a value other than visible
  • display: flow-root
  • elements with contain: layout, content, or strict
  • flex items (direct children of the element with display: flex or inline-flex)
  • grid items (direct children of the element with display: grid or inline-grid)
  • multicol containers (elements where column-count or column-width is not auto, including elements with column-count: 1)
  • column-span: all should always create a new formatting context, even when the column-span: all element isn't contained by a multicol container (Spec change, Chrome bug). https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context

The height of block formatting context roots which contains only inline elements defined by a height of line boxes (from spec):

10.6.7 'Auto' heights for block formatting context roots

In certain cases (see, e.g., sections 10.6.4 and 10.6.6 above), the height of an element that establishes a block formatting context is computed as follows:

If it only has inline-level children, the height is the distance between the top of the topmost line box and the bottom of the bottommost line box.

https://www.w3.org/TR/CSS2/visudet.html#root-height

Height of line box equals "line-height" (from spec)

On a non-replaced inline element, 'line-height' specifies the height that is used in the calculation of the line box height.

https://www.w3.org/TR/CSS2/visudet.html#leading

If I change "display: inline-block" on "display: inline-flex" it works as expected

Thanks

Community
  • 1
  • 1
maksimr
  • 4,891
  • 2
  • 23
  • 22

1 Answers1

0

Thanks @TemaniAfif

He was right the reason of 18px for height was in line-height of div element. div's line-height specify minimal height of line boxes

On a block container element whose content is composed of inline-level elements, 'line-height' specifies the minimal height of line boxes within the element.

In my case div doesn't specify line-height property so it has default value equals normal.

Name: line-height

Value: normal | <number> | <length> | <percentage> |

inherit Initial: normal

https://www.w3.org/TR/CSS22/visudet.html#leading

If line-height value is normal then computed value depends from user agent. But spec recommends to use value 1.0 to 1.2 of element's font-size. Looks like usually this value are equals to font-size * 1.2 but it's also depends from font's metrics like ascent, descent and em-box (so result would depends from font-family).

normal

Tells user agents to set the used value to a "reasonable" value based on the font of the element. The value has the same meaning as . We recommend a used value for 'normal' between 1.0 to 1.2. The computed value is 'normal'.

If you know font's metrics like ascender and descender and font-size which you would use on the web you can calculate line-heigh by (ascender + Math.abs(descender)) * font-size / (units_per_em)

function lh(ascender, descender, unitsPerEm, fontSize) {
  return (ascender + Math.abs(descender)) * fontSize / unitsPerEm;
}

enter image description here enter image description here

In the pictures above ascender=5000, descender=-200, units_per_em=1000 and font-size=48px so line-height=(5000 + 200) * 48 / 1000 = 249.6 (lh(5000, 200, 1000, 48)) enter image description here

ascent, descent font's properties are shipped with font and defined by font's creator. You can use FontDrop! service to get information about font

Some implementations details from Chromium(Webkit) relates to line-height

LayoutUnit ComputedStyle::ComputedLineHeightAsFixed() const {
  const Length& lh = LineHeight();
  // Negative value means the line height is not set. Use the font's built-in
  // spacing, if avalible.
  if (lh.IsNegative() && GetFont().PrimaryFont())
    return GetFont().PrimaryFont()->GetFontMetrics().FixedLineSpacing();

https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/core/style/computed_style.cc#1835

FixedLineSpacing

 float line_gap = SkScalarToFloat(metrics.fLeading);
  font_metrics_.SetLineGap(line_gap);
  font_metrics_.SetLineSpacing(lroundf(ascent) + lroundf(descent) +
                               lroundf(line_gap));

https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/platform/fonts/simple_font_data.cc#123

maksimr
  • 4,891
  • 2
  • 23
  • 22