Learn more about CSS Font metrics, line heights, and Vertical-align

Source: Internet
Author: User

line-heightand vertical-align in CSS is a two simple property. So simple, most people believe they have a full understanding of how they work and how to use them. But in fact it's not so. They are complex and one of the most difficult aspects of CSS and one of the features of CSS: inline formatting context (inline formatting contexts).

For example, you can set a line-height value with a length unit or a value without a unit, but its default value is normal . So normal what's in CSS? We often think that it is (or should be) 1 or 1.2 , or even can be said, that the CSS specification is not clear which one. We also know that no units line-height are relative to font-size each other, but the problem is that the font-size: 100px; behavior of using different fonts () behaves differently font-family , so is it always the line-height same or different? Really, 1 or is it 1.2 ? vertical-alignWhat are line-height the other influences?

To delve into the mechanism of CSS can be said not so simple ...

First to talk about Font-size.

Let's start with a simple HTML code that <p> contains three <span> tags, each with a different one <span> font-family :

<P>    <spanclass= "a">Ba</span>    <spanclass= "B">Ba</span>    <spanclass= "C">Ba</span></P>

P   {    font-size: 100px;}  {    font-family: Helvetica;}  {    font-family: Gruppo;}  {    font-family: catamaran;}

Each element uses the same font-size , but uses a different font-family one, but the rendering line-height is different:

Even though we are aware of this behavior, it is unclear why font-size:100px the element is height not 100px ? I measured the discovery: the height of the font is, the height of the font is Helvetica 115px Gruppo 97px and Catamaran the height of the font is 164px .

At first it seemed a little strange, but it was perfectly predictable. This is mostly font-family the reason. Then you need to figure out how it works:

    • The font defines its em-square, and each character will be drawn out of its own container. This square uses relative units and generates a 1000 unit. But it can also be 1024 , 2048 or other
    • Depending on the recommended unit, font metrics can be determined based on some settings (Ascender,descender,capital height,x-height, etc.). Note that some values are values other than Em-square
    • In the browser, the relative units are used for scaling to fit the desiredfont-size

Let's look Catamaran at the font and look at the metric of the font in FontForge:

    • Em-square is1000
    • Ascent (Ascender) is 1100 and descent (Descender) is 540 . Under the same test, the browser uses the Hhead ascent/descent value (MAC) and the win Ascent/descent value (Windows), which may be different. We also need to note that the capital height is 640 and the value of X-height is485

This means that the Catamaran font 1000 is used in units of Em-square 1100 + 540 , that font-size:100px is, when the height of a unit is 164px . This calculation highly defines the height of the element content (the term content-areais referenced in the rest of this article). You might think of a content area equivalent to an background attribute.

We can also predict that uppercase letters are 68px height (680 units) and lowercase letters (X-HEGIHT) are 49px height (485 units). So, 1ex = 49px and rather 1em = 100px than 164px (thankfully, em is based on font-size calculations, not height ).

Before you go any further, understand what this involves? When an element is rendered on the <p> screen, it can have many lines depending on its width. Each line consists of one or more inline elements (HTML tag elements or anonymous inline element text content), and the jargon is called the Line box (Line-box). The height of the Line-box is based on the height of its child elements. The height that the browser calculates for each inline element is Line-box (the highest point of the child element to the lowest point). Therefore, the total height of the line-box is sufficient to contain all child elements (by default).

Each HTML element is actually a stack of line-box. If you know the height of each line-box, you actually know the height of each element.

If we update the previous HTML structure to:

<P>good design would be better. <spanclass= "a">Ba</span>    <spanclass= "B">Ba</span>    <spanclass= "C">Ba</span>We get to make a consequence.</P>

It will generate three line-box:

    • First and last each containing an anonymous inline element (text content)
    • The second one contains two anonymous inline elements and three<span>

<p>The element (black border) produces a line-box (white border) that contains an inline element (a solid border) and an anonymous inline element (a dashed border).

We see clearly that the second line-box is significantly higher than the other line-box, calculated from the content area of the child element (Content-area), and more specifically, using a Catamaran font.

The hard part is that we can't see the line-box, nor do we use CSS to control it. It is ::first-line background not possible to visually see the height of the first line-box even if it is applied.

Line-height problems

Until now, we have introduced two concepts:Content-area and line-box. If you read the previous content carefully, you should know that the height of the Line-box is based on the height of the child element, and I'm not saying the height of the content area (Content-area) of the child element. That's a big difference.

Although this may sound strange, inline elements have two different heights: the content area (Content-area) height and the virtual area (virtual-area) height (this is the term virtual-area height that I invented, and you can't find anything relevant in the specification).

    • The height of the content area is determined by the font (described earlier)
    • The height of the virtual area (Virtual-area) is line-height , its height is used to calculate the height of the Line-box

The inline element has two different heights.

In other words, the line-height prevailing view is the distance between the different baselines (baseline). In CSS, it's not like this.

The calculated virtual region (Virtual-area) and the content area (content-area) height difference are called leading. Leading is added at the top of the content area and the other half is added at the bottom of the content area. Therefore, the content area is always in the middle of the virtual zone.

Based on its calculated value, line-height (Virtual-area) is higher or lower than content-area in the same case. For smaller virtual-area,leading, negative values and line-box are smaller than their child elements.

There are other inline elements as well:

    • Replace inline elements within inline ( ,, <input> , <svg> etc.)
    • inline-blockElements
    • Inline elements participate in specific formatting contexts (e.g., flexbox elements, and all flex projects)

For these specific inline elements, the height calculation is based on their height , margin and border attributes. If hegiht the value is auto , then line-height content-area strictly equals when used line-height .

Anyway, the question we still face is line-height normal How small is the value? The answer is that the calculation of the Content-area height is based on the font inside the measurement.

We went back to FontForge. Catamaran's em-square is 1000, but we see the value of Ascender/descender:

    • The generated Ascent/descent:ascender is 770,descender is 230. Used to draw characters (OS/2)
    • The Ascent/descent:ascender of the metric is 1100,descender is 540. For content Area Heights (Hhea and OS/2)
    • Spacing of measure lines: Using Ascent/descent metrics line-height: normal (Hhea)

In our example, the catamaran font defines the 0 line gap for each unit, so line-height: normal the value will be equal to the content area, that is, the 1640 unit or 1.64 .

As a comparison, a em-square of Arial font is a 2048 unit, its ascender is 1854 , Descender is 434 , the line spacing is 67 . This means that font-size: 100px the content area is 112px ( 1117 units) and line-height is 115px ( 1150 units or 1.15 ). All of these metrics are special glyphs that are set by the font designer.

Obviously, setting line-height:1 is a very bad practice. I remind you that font-size no unit concept is relative, but the content area is not relative and there are many problems with dealing with virtual regions smaller than the content area.

But and is only line-height:1 . Whether true or FALSE, I installed a font on my Computer 1117 (yes, I installed all the Google Web fonts), one of the 1059 fonts, which accounted for the entire font of the 95% left and right, calculated line-height greater than 1 . They line-height are calculated from 0.618 the to 3.378 . You have to remember, yes 3.378 !

Small details of the Line-box calculation:

    • For inline elements, padding and border increases its background area, but does not increase the height of the content area (even the line-box height). Therefore, what you see on the screen is not necessarily the content area. margin-topand margin-bottom inline elements do not take effect.
    • For inline substitution elements, inline-block and blocksified inline elements, padding margin and border both increase the height, the height of the content area and Line-box also increases
Vertical-align: A property controls everything

I didn't mention the vertical-align property in front, even though it was an important factor in calculating the line-box height. We can even say that vertical-align attributes have a great effect on leading in the inline formatting context.

vertical-alignThe default value is baseline . Do you notice the Ascender and descender of the metric font? These values are based on baseline , with a certain proportion. So the ratio between Ascender and Descender is really 50/50 , it can produce unexpected results, such as all sibling elements.

Let's start with this code:

< P >    < span > BA</span>    <span>Ba</  span></p>p {    font-family: Catamaran;    font-size:100px;    line-height:200px;}

Two<span>element inherits the<p>Elements offont-family,font-sizeand a fixedline-height. The baseline will match to the height of the Line-box equal to theirline-height. 

What if the second element is set to a smaller one font-size ?

{    font-size: 50px;}

This sounds strange, but the default baseline alignment may result in a higher line-box, as shown in. I remind you that the height of the line-box is calculated from the highest and lowest points of its sub-elements.

One idea that can be supported is to line-height set the value without any units, but sometimes you need to make a perfect vertical-rhythm. To tell the truth, no matter what you choose, you will always have difficulty.

Look at another example. <p>the value of the element is set and contains an element that inherits the element line-height 200px <span> <span> <p> 's line-height .

< P >    < span > Ba</span></p>p {    line-height:200px;} span {    Font-family:catamaran;    font-size:100px;}

How high is the Line-box? We expect 200px , but if not, what are we getting? The difference here is that the <p> element has its own font (the default is serif ). <p>the <span> baseline between and may be different, so the height of the line-box is higher than expected. This is because the browser gives each line-box calculation to start with an arbitrary character. The specification is called strut.

An invisible character, but it does have a visible effect.

On my own experience, we will face the same problem, that is the sibling element.

Baseline alignment is over, but vertical-align:middle can you save them? You can read the specification:

Middle "aligns the vertical midpoint of the box with the baseline of the parent box plus half the x-height of the parent".

The scale of the baseline is different, as well as the x-height ratio, so the middle alignment is unreliable. In the worst case, in most cases, the middle is never really halfway through. There are too many factors involved, and the use of CSS is not able to set these factors (X-height,ascender and descender proportions, etc.).

It has four values, which may be useful in some cases:

    • vertical-align: top | bottomAligns with the top or bottom of the Line-box
    • vertical-align: text-top | text-bottomAligns with the top or bottom of the content area

Note that in all cases it is in the virtual area, so it is invisible to the height. Looking at this simple example, the use of vertical-align:top unseen line-height may produce some very strange results.

Finally, vertical-align you can also accept values to increase or decrease the box's baseline. The last option can be useful.

CSS omnipotent

We've talked about line-height how it vertical-align works together, but now the question is how do you use CSS to control the metrics of the word level? A short answer: No. Even if that's true, I think we should be able to do something about it. So what should we be able to do about font metrics?

For example, if we want to use the catamaran font for text, can we extend its capital height to 100px? By some mathematical calculations, it seems feasible.

First set the five custom properties of the metric font, and then calculate font-size , thus getting the capital height is 100 .

P{/*Font Metrics*/--font:Catamaran;--capitalheight:0.68;--descender:0.54;--ascender:1.1;--linegap:0;/*desired font-size for capital height*/--fontsize: -;/*Apply font-family*/font-family:var (--font);/*compute font-size to get capital height equal desired font-size*/--computedfontsize:(Var (--fontsize)/var (--capitalheight));font-size:Calc (var (--computedfontsize) * 1px);}

It's simple, isn't it? But what if we want the text to be centered in the viewable area, so that the rest of the space is evenly divided between the top and bottom of the "B" word? To achieve this, we must calculate based on Ascender and descender ratios vertical-align .

First, line-height:normal the height of the calculation and content area.

{    ...    --lineheightnormal: (Var (--ascender) + var (--descender) + var (--linegap));     --contentarea: (VAR (--lineheightnormal) * VAR (--computedfontsize));}

At this point, we need:

    • The distance from the bottom edge of each bottom of the main letter
    • Distance from top edge of capital letter top

Like this:

{    ...    --distancebottom: (Var (--descender));     --distancetop: (Var (--ascender)-VAR (--capitalheight));}

We can now font-size calculate by the distance multiplied vertical-align .

{    ...    --valign: ((Var (--distancebottom)-VAR (--distancetop)) * VAR (--computedfontsize));}  {    vertical-align: Calc (var (--valign) * -1px);}

Finally, we set the desired line-height and calculated it, maintaining a vertical alignment:

{    ...     /*  */    --lineheight: 3;     Line-height: Calc (((Var (--lineheight) * VAR (--fontsize))-VAR (--valign)) * 1px);}

Add an icon and the letter "B" to align vertically, and now it's easy to do:

{    content: ';     display: inline-block;     width: calc (1px * VAR (--fontsize));     height: Calc (1px * VAR (--fontsize));     margin-right: 10px;     background: url (' https://cdn.pbrd.co/images/yBAKn5bbv.png ');     background-size: cover;}

The address of the example can be clicked here.

Note: This test is for demonstration purposes only. You can't rely on this. If the font does not load, the alternate word may have different font metric parameters, and it will not work properly.

In some of the examples, you can see that -- this is the original CSS variable, also known as CSS custom properties. If you have never been in touch with this before, it is recommended that you click here to find out.

Summarize

What we learned in this article:

    • Inline formatting context is really hard to understand
    • All inline elements have two heights
    • Content area (Content-area) font-based metric parameters
    • The virtual region (Virtual-area) isline-height
    • These two heights are not visible (if you can see through the developer tools)
    • line-height:normalis based on the font metric parameter
    • line-height: nIt is possible to create a virtual region that is smaller than the content area
    • vertical-alignNot very reliable.
    • The height of a line-box is calculated based on its child elements line-height and vertical-align attributes
    • We have no way to get or set the metric parameters of the font directly through CSS
    • There may be a vertical alignment specification to address these seemingly problematic issues in the future: line Grid Module

Article Source: http://www.w3cplus.com/css/css-font-metrics-line-height-and-vertical-align.html

Learn more about CSS Font metrics, line heights, and Vertical-align

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.