简体   繁体   中英

How can I mix vertically-centered elements with different font sizes and retain consistent line height?

When you mix font-sizes of elements with vertical-align: middle inside of a container, the container's height can be larger than the line-height or height of either individual element. Here is a fiddle :

 body { line-height: 20px; font-size: 14px; } .smaller { font-size: 0.9em; vertical-align: middle; } 
 <div class="body"> <div class="why-not-twenty-px"> containing div has height <span class="smaller">&bull;</span> of 21px, not 20px </div> <div class="why-not-sixty-px"> containing div has height of 61 px, not 60px multiline multiline multiline multiline multiline multiline <span class="smaller">&bull;</span> multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline </div> </div> 

In this example, the two containing divs are 21px and 61px instead of 20px and 60px.

How can I retain a container height that is a multiple of the line-height when mixing in an element like .smaller ? .smaller must be vertically centered on the line. Ideally, any solution would only involve CSS changes to .smaller .

§10.8 explains how the height of the line boxes is calculated:

As described in the section on inline formatting contexts , user agents flow inline-level boxes into a vertical stack of line boxes . The height of a line box is determined as follows:

  1. The height of each inline-level box in the line box is calculated. [...] For inline boxes, this is their 'line-height'

    Since .smaller inherits line-height: 20px and is an inline box (ie non-replaced with display: inline ), its height is 20px

  2. The inline-level boxes are aligned vertically according to their 'vertical-align' property.

    .smaller has vertical-align : middle , which means

    Align the vertical midpoint of the box with the baseline of the parent box plus half the x-height of the parent.

  3. The line box height is the distance between the uppermost box top and the lowermost box bottom.

So both the text and .smaller have a height of 20px , but they have different alignment. Therefore, the line box grows:

在此输入图像描述

Then, as other answers explain, a way to solve the problem is reducing .smaller 's line-height :

在此输入图像描述

However, there is an alternative solution, without modifying line-height : negative margins can be added to prevent .smaller from increasing the height of the line box.

As quoted above, the height of an inline box is its line-height , so to make the margins work, display: inline-block is also needed:

The height of each inline-level box in the line box is calculated. For [...] inline-block elements [...] this is the height of their margin box.

Note this solution won't break the alignment, because since .smaller has vartical-align: middle , if we use the same amount in margin-top and margin-bottom , it will remain centered.

在此输入图像描述

To summarize, you can use this code:

.smaller {
    vertical-align: middle;
    display: inline-block;
    margin: -1em 0;
}

 body { line-height: 20px; font-size: 14px; } .smaller { font-size: 0.9em; vertical-align: middle; display: inline-block; margin: -1em 0; } 
 <div class="body"> <div class="why-not-twenty-px"> nor<span class="smaller">&bull;</span>mal </div> <div class="why-not-sixty-px"> multiline multiline multiline multiline multiline multiline <span class="smaller">&bull;</span> multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline </div> </div> 

You can fix this by making the line-height relative to the font-size , instead of a fixed one.

body {
    line-height: 1.4285;
    font-size: 14px;
}

will fix the issue of the extra pixels on the containers.

Demo at http://jsfiddle.net/gaby/b5zgpktj/


To only affect the .smaller element you can give it a line-height of 1

.smaller
{
    line-height:1;
    font-size: 0.9em;
    vertical-align:middle;
}

Demo at http://jsfiddle.net/gaby/b5zgpktj/1/

Put line-height: 100% or line-height: 1 (preffered) on .smaller element. Also, if you put vertical-align: top or vertical-align: bottom without changing line-height containers would be 20px and 60px.

By making line-height computed from actual font-size or ensuring element top/bottom is aligned with parent, height remains same (this assumes your child element always has smaller font-size than parent). Otherwise you inherit 20px fixed line-height which adds to parent total height when parent and child boxes are not aligned (this happens when font-size differs and vertical-align is anything than top/bottom, including middle or default baseline value).

 body { line-height: 20px; font-size: 14px; } .smaller { font-size: 0.9em; line-height: 1 // or 100% vertical-align: middle; } 
 <div class="body"> <div class="why-not-twenty-px"> containing div has height <span class="smaller">&bull;</span> of 21px, not 20px </div> <div class="why-not-sixty-px"> containing div has height of 61 px, not 60px multiline multiline multiline multiline multiline multiline <span class="smaller">&bull;</span> multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline </div> </div> 

Reference:

The container div is taking a height of 21px because the span.smaller element is having a line-height of 20px. The siblings of span element also have a line height of 20px. You need to understand that line-height property is used while calculating the vertical-align property. Now if you want to apply "vertical-align: middle" to the span.smaller change its line-height to something smaller than their siblings line-height ie 20px, or else it will try to center the span.smaller element with respect to its siblings. Since span.smaller line-height is also 20px it will cause the container to have more height.

For example

    <div class="body">
 <div class="why-not-twenty-px">
    containing div has height 
     <span class="smaller"> &bull;</span> 
     of 21px, not 20px
  </div>
<div class="abcd">
    <span>The same problem can </span>
    <span style="vertical-align:middle;color:grey;"> be             replicated </span> 
    <span> while using tags with same font-size and line-height, height will be 21px</span>
  </div>
<div class="why-not-sixty-px">
containing div has height of 61 px, not 60px multiline multiline multiline multiline multiline multiline <span class="smaller">&bull;</span> multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline multiline

CSS

    body
    {
        line-height: 20px;
        font-size: 14px;
    }
    .smaller
    {
        font-size: 12px;/*I prefer to use px over em, same as 0.9em*/
        vertical-align: middle;
        line-height: 12px;/*use any smaller line height compared to         siblings*/
    }
    .abcd span{
        text-decoration: underline;
    }

OR Please follow this link https://jsfiddle.net/osha90/meeLL0u9/4/

line-height: 1em;

将此样式添加到.smaller ,bullet将垂直对齐到中心。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM