Css: How Is Height of Block-Elements Calculated

CSS: How is height of block-elements calculated?

Regarding the general question of "How is the height of an element calculated", some info can be found here: http://www.w3.org/TR/CSS2/visudet.html#Computing_heights_and_margins

As you can see, it's a bit complicated.

Some excerpts:

Block-level non-replaced elements in normal flow when 'overflow' computes to 'visible'
This section also applies to block-level non-replaced elements in normal flow when 'overflow' does not compute to 'visible' but has been propagated to the viewport.

[. . .]

If 'height' is 'auto', the height depends on whether the element has any block-level children and whether it has padding or borders:

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.

If it has block-level children, the height is the distance between the top border-edge of the topmost block-level child box that does not have margins collapsed through it and the bottom border-edge of the bottommost block-level child box that does not have margins collapsed through it.

[. . . ]

Only children in the normal flow are taken into account (i.e., floating boxes and absolutely positioned boxes are ignored, and relatively positioned boxes are considered without their offset).

[. . . ]

Block-level, non-replaced elements in normal flow when 'overflow' does not compute to 'visible' (except if the 'overflow' property's value has been propagated to the viewport).
If 'height' is 'auto', the height depends on the element's descendants.

How to determine height of content-box of a block and inline element

For block elements its quite easy but you need to distinguish between two different cases. When we have an IFC (inline formatting context) or BFC (block formatting context). From the specification you can read

If 'height' is 'auto', the height depends on whether the element has any block-level children and whether it has padding or borders:

The element's height is the distance from its top content edge to the first applicable of the following:

  1. the bottom edge of the last line box, if the box establishes a inline formatting context with one or more lines
  2. the bottom edge of the bottom (possibly collapsed) margin of its last in-flow child, if the child's bottom margin does not collapse with the element's bottom margin
  3. the bottom border edge of the last in-flow child whose top margin doesn't collapse with the element's bottom margin
  4. zero, otherwise

Only children in the normal flow are taken into account (i.e., floating boxes and absolutely positioned boxes are ignored, and relatively positioned boxes are considered without their offset)

If we consider an IFC then the line boxes will define our height exactly like your examples where in the div and p you have one line box defined by the line-height.

If we consider a BFC then the (2) and (3) apply. Here, you can see it as a recursive definition because having a BFC means we have other blocks inside and those blocks will follow the same rules (either BFC or IFC and so on). In addition, we consider the margin collapsing rules to get the final height.

If the block is empty then it's zero.

Of course, this consider the case of height:auto. If you explicitely set a height then it's trivial.


For inline elements you can 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.)

Here is a bit tricky but the rule is simple: you cannot control or set the height of the content area. Only the font properties you will be using will define the final height.

You should also note that the content area is different from the line box.

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.

<span style="background-color: aquamarine; font-size: 16px; line-height: 2em;">Is line-height same as height of span tag?</span>
<br>
<span style="background-color: aquamarine; font-size: 16px; line-height: 4em;">Is line-height same as height of span tag?</span>
<br>
<span style="background-color: aquamarine; font-size: 16px; line-height: 8em;">Is line-height same as height of span tag?</span>

In CSS, how is the height computed for block element?

Setting a line height with a CSS unit (em or px, etc) means that the line height is computed (in this case, the line height becomes 19.2px) and then the computed value will inherit to the span. The span will therefore also have a line height of 19 (rounded) pixels rather than the 192 pixels you expect.

Solution: set the line height without a CSS unit. If you write line-height:1.2 the inherited value of the line height will be what you want.

div > span {

font-size: 10em;

}

div {

line-height: 1.2;

}

/* Normalize the default font size */

body {

font-size: 16px;

}
<div>

<span>Cat</span>

</div>

How to calculate the height of an inline element

The CSS 2.1 spec says:

10.6.1 Inline, non-replaced elements

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.

As it happens the height, as opposed to the line-height, of a non-replaced inline element has very little effect on anything else so browsers are pretty free to report whatever number they like here.

However, a little reverse engineering can be instructive.

If we look at the font metrics for Times New Roman, we see EM size of 2048, WinAscent of 1825, and WinDescent of 443. Sum the ascent and descent, divide by the EM size, multiply by the font size (20px) and round to the integer and we get 22px.

Taking Arial as another font, we have EM size of 2048, WinAscent of 1854, and WinDescent of 434. Do the calculation again and we again get 22px.

What about a different font? Tahoma has EM size of 2048, WinAscent of 2049, and WinDescent of 423. Do the calculation again and this time we get 24px. And hey presto, if you try your JsBin with the Tahoma font, Firefox does indeed show a height of 24px.

The font metrics above were obtained from loading the fonts into Type Light 3.2.

Not conclusive, but a reasonable suggestion of how it all works.

Is it possible to make it tall 20px without using inline-block ?

Assuming the above is correct, you should be able to achieve it by using a custom font and modifying the font metrics of that font to suit. I wouldn't like to predict the knock-on effects of doing that though.

Height Calculation By Browsers : Containing Blocks and Children

The height CSS property on MDN:

Percentages

The percentage is calculated with respect to the height of the
generated box's containing block. If the height of the containing
block is not specified explicitly (i.e., it depends on content
height), and this element is not absolutely positioned, the value
computes to auto.
A percentage height on the root element is relative
to the initial containing block.

In 1., the height attribute of the parent isn't explicitly specified, therefore the value computes to auto.

In 2., the height attribute is specified and therefore it's calculated with respect to the parent

How to use CSS calc() with an element's height

I think you are trying to run script in a css syntax, which is NOT POSSIBLE.

calc() can do basic math operation with absolute values, it cannot find the height of an element and then perform math on it.

How Exactly Is The Containing Block Determined

First, the containing block in both cases is the same for inner and it's outer. overflow play no role here, same for the usage of flexbox. More detail: https://www.w3.org/TR/CSS2/visudet.html#containing-block-details

Now, you need to understand the trickery around percentage height. The general rule is: "the containing block need to have an explicit height"

Specifies a percentage height. The percentage is calculated with respect to the height of the generated box's containing block. If the height of the containing block is not specified explicitly (i.e., it depends on content height), and this element is not absolutely positioned, the value computes to 'auto'. ref

Considering this, you can assume that your percentage height will fail in both cases BUT things have changed and now we can resolve percentage height in some particular cases where we don't have any explicit height defined on the containing block.

Sometimes the size of a percentage-sized box’s containing block depends on the intrinsic size contribution of the box itself, creating a cyclic dependency. When calculating the intrinsic size contribution of such a box (including any calculations for a content-based automatic minimum size), a percentage value that resolves against a size in the same axis as the intrinsic size contribution (a cyclic percentage size) is resolved specially: ref

If you keep reading, you will find a lot of complex concept and definition not easy to understand. I will not detail all of them but your second case is one of them.

To make it easy: Flexbox force some sizes to be definite allowing percentage height to be resolved (https://drafts.csswg.org/css-flexbox-1/#definite-sizes).

There are more cases like that related to flexbox and CSS grid as well:

Percentage 'min-height' works only when element has indirect parent with 'display: flex'

Why does `height: 100%` value 'work' for child tags of grid-items?

https://stackoverflow.com/a/52137966/8620333

Strange calculated height on div display:inline-block element

Figured it out. Because the font was set on only the child divs (div.ela, div.elb) and not the parent row div, the line-height was something totally different on the parent div.row causing the box to be bigger than normal (also due to the fact that all the elements in there were inline-block). I guess it defaulted to a line height based on whatever the font would have been there had I added some text (confirmed, it looks like this is what it did).

So, the fix is to make sure you set the font on the parent div to the either something the same as or smaller than that of the child divs so the parent resizes correctly.



Related Topics



Leave a reply



Submit