CSS魔法堂:深入理解line-height和vertical-align

时间:2022-09-06 10:49:12

前言

一直听说line-height是指两行文本的基线间的距离,然后又说行高等于行距,最近还听说有个叫行间距的家伙,@张鑫旭还说line-height和vertical-align基情四射,贵圈真乱啊。。。。。。于是通过本篇来一探究竟:)

line-height到底有多height?

行距、行间距傻傻分不清

 首先看看“有道词典”的解析!

Leading = Line Space + Font Size(即是 行距 = 行间距 + 字体大小)

Leading: 指相邻文本行间上一个文本行基线和下一文本行基线间的距离。

Line Space: 指相邻文本行间上一个文本行下行线(ascent)和下一文本行上行线(descent)间的距离。

而在一些面向普通消费者的软件中,Leading往往是指Line Space。Leading

 在CSS当中,Leading就是指Line Space。而CSS属性line-height则是用于设置真实的Leading。参考

Still for each glyph, determine the leading L to add, where L = 'line-height' - AD

AD是指字形ascent和descent间的距离,即是font-size。

 这里为更清晰地叙说,我将以广义Leading指代行间距,而狭义Leading则指代行距。

从W3C Rec中看出,line-height就是狭义Leading,而line-height的字面意思即为“行高”,推导结果CSS中行高即是行距。

这里我们了解到行高行距行间距的区别了。那接下来要介绍line-height的一个重要特性——垂直居中性。

line-height的垂直居中性

 通过L = 'line-height' - AD我们知道line-height=行间距+字形大小,字形大小我们可以通过font-size来设置,而line-height就更不用说了,而家问题是行间距所占的空间是怎样分配的呢?

方案1:不是说行间距就是上一行的descent到下一行的ascent间的距离吗?那直接分配到A位置就好了。

CSS魔法堂:深入理解line-height和vertical-align

方案2:如果方案1的分配方案合理,那么分配到B位置就也是OK的。

CSS魔法堂:深入理解line-height和vertical-align

方案3:一边倒的分配方案太不美观了吧!不如将行间距对半开,然后分别分配到上下两端不就OK了吗!

CSS魔法堂:深入理解line-height和vertical-align

CSS采用的就是方案3。这是引用了Half-leading的概念,Half-leading = Leading/2.

Half the leading is called the half-leading. User agents center glyphs vertically in an inline box, which adds half-leading on the top and bottom. For example, if a piece of text is "12pt" high and the line-height value is "14pt", 2pt of extra space should be added: 1pt above and 1pt below the text (this applies to empty boxes as well, as if the empty box contained zero-height text).参考

在深入垂直居中性之前,我们先看一个容易引起误解的示例。(其实是我自己误解而已:()

<div id="container" style="border:solid 1px red;"><span style="background:blue;color:#fff;font-size:20px;line-height:60px;">center glyphs vertically in an inline box.</span></div>

不是说好了会垂直居中吗?你看字母x明明就在div#container中线的下方呢!

我们用空格符代替文字就可以看清楚了。

<div style="border:solid 1px red;"><span style="background:blue;color:#fff;font-size:20px;line-height:60px;">&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;</span></div>

CSS魔法堂:深入理解line-height和vertical-align

“垂直居中”是指字形所在的盒子的垂直中线与line-height所占据的盒子的垂直中线重合,不是指字形的mean line和line-height所占据的盒子的垂直中线重合。

L = "line-height" - AD可以知道行间距可能会负数,那么垂直居中性还有效吗?

答案是肯定的,L为负数时,Half-leading自然也是负数,只是上下两端从增加空间变为减少等量空间而已。不信你看

<body style="margin:0 10px;padding:0;">
<div style="position:relative;top:100px;font-size:90px;line-height:10px;background:yellow;"><span style="border:solid 1px red;line-height:10px;">x</span></div>
</body>

CSS魔法堂:深入理解line-height和vertical-align

line-height属性

'line-height'

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

Initial: normal

Applies to: all elements

Inherited: yes

Percentages: refer to the font size of the element itself

Media: visual

Computed value: for and the absolute value; otherwise as specified

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'.

 normal其实就是一个值,不过实际值则由浏览器决定,实际值一般在1.0~1.2之间(含两端)浮动。但实际真的是这样吗?

<body style="font-family: Arial, Tahoma, Sans-serif;">
<div style="background:blue;color:#FFF;font-size:10px;">line-height-x-L</div>
<div style="background:blue;color:#FFF;font-size:40px;">line-height-x-L</div>
<div style="background:blue;color:#FFF;font-size:80px;">line-height-x-L</div>
<script type="text/javascript">
var els = document.getElementsByTagName('div')
for (var i = 0, len = els.length; i < len; ++i){
console.log(els[i].offsetHeight)
}
</script>
</body>

Chrome43的结果

CSS魔法堂:深入理解line-height和vertical-align

14/10 = 1.4
45/40 = 1.125
92/80 = 1.15
average: 1.225 约为1.2

Firefox44.0.2

CSS魔法堂:深入理解line-height和vertical-align

13/10 = 1.3
46/40 = 1.15
92/80 = 1.15
average: 1.2

IE9

CSS魔法堂:深入理解line-height和vertical-align

11/10 = 1.1
46/40 = 1.15
92/80 = 1.15
average: 1.13333 约为1.1

通过小数据统计得出normal值的规律:

  1. 不同浏览器的normal值不相同;
  2. 同一个浏览器下,font-size值不同,normal值也会有变化;
  3. 同一浏览器下,font-size值相同,font-family值不同,normal值也会有变化;
  4. normal的平均值确实是在1.0~1.2之间(含两端),但具体到特定浏览器、font-family和font-size时,normal的实际值可能会大于1.2。

<length>

The specified length is used in the calculation of the line box height. Negative values are illegal.

 设置固定值,单位可以是px、pt。好处是简单——设置是什么,line-height的实际高度就是什么。坏处是子元素默认情况下会继承父容器的line-height属性,若子元素的font-size大于父容器的font-size属性值,那么子元素的文本行会十分密集,降低可阅读性。所以我们一般采用相对font-size实际大小来设置line-height值的方式,如默认normal方式。

<percentage>

The computed value of the property is this percentage multiplied by the element's computed font size. Negative values are illegal.

 既然采用副作用那么大,那采用这个相对值就万事大吉了吧!非也,首先我们要弄清楚这个的参考系是啥,另外还要明白子元素的line-height到底继承的了哪个值,是值还是父容器实际的line-height值。

  1. 的参考系的确是font-size;
  2. 子元素继承的是父容器实际的line-height值。也就是说父容器设置为font-size:20px;line-height:200%;,那么子元素继承来的line-height值为40px,而不是200%。因此又回到方式的问题上了。

<number>

The used value of the property is this number multiplied by the element's font size. Negative values are illegal. The computed value is the same as the specified value.

 和方式一样,以font-size作为参考系,以相对值的方式设置line-height。唯一的不同就是子元素继承的是父容器的值,参考系自动变更为子元素的font-size

 其实line-height:1.2em;line-height:1.2;是等价的。若想将参考系改为根元素的font-size,则需要采用CSS3新增的line-height:1.2rem单位了。

 根据WCAG2.0(万维网内容可存取性指南)规定“段落中的行距至少要1.5倍”,那么是否在body那设置一个就一劳永逸呢?请看

<style type="text/css">
body{
font-size: 16px;
line-height: 1.5;
}
h1 {font-size:32px;}
p {font-size:16px;}
#footer {font-size:12px;}
</style>
<h1>CSS魔法堂:深入理解line-height和vertical-align</h1>
<p>In my dual profession as an educator and health care provider, I have worked with numerous children infected with the virus that causes AIDS. The relationships that I have had with these special kids have been gifts in my life. They have taught me so many things, but I have especially learned that great courage can be found in the smallest of packages. Let me tell you about Tyler. </p>
<div id="footer">bed and whispered, “I might die soon. I’m not scared. When I die, please dress me in red. Mom promised she’s coming to heaven, too. I’ll be playing when she gets there, and I want to make sure she can find me.”</div>

CSS魔法堂:深入理解line-height和vertical-align

看对于h1标题栏而言,行距太多了。于是得出如下配置:

body{line-height:1.5;}
h1,h2,h3,h4,h5,h6{line-height:1.2;}

vertical-align到底如何对齐呢?

 下面我们稍微将line-height垂直居中特性中Leading为负数的示例代码修改一下,将font-size:90px;line-height:10px;迁移到子元素中.

<div style="position:relative;top:100px;background:yellow;"><span style="border:solid 1px red;font-size:90px;line-height:10px;">x</span></div>

CSS魔法堂:深入理解line-height和vertical-align

不是说垂直居中吗?这里就涉及到一个相对复杂的CSS垂直对齐规则——vertical-align。

注意:前方高能,需要IFC、line box作为前提知识。(可参考CSS魔法堂:重新认识Box Model、IFC、BFC和Collapsing margins

vertical-algin属性

'vertical-align'

Value: baseline | sub | super | top | text-top | middle | bottom | text-bottom | <percentage> | <length> | inherit

Initial: baseline

Applies to: inline-level and 'table-cell' elements

Inherited: no

Percentages: refer to the 'line-height' of the element itself

Media: visual

Computed value: for and the absolute length, otherwise as specified

<lenght>:设置相对于baseline的距离,正数表示位于baseline的上方,负数表示位于baseline的下方;

<percentage>:设置以line-height为参考系,相对于baseline的距离,正数表示位于baseline的上方,负数表示位于baseline的下方;

baseline:默认值。元素的基线与父元素的基线对齐;

top:把元素line box上边框对齐父元素的line box上边框;

text-top:把元素line box上边框对齐父元素的ascent(即content top edge);

super:升高元素的基线到父元素合适的上标位置;

middle:把元素line box中垂点与父元素基线 + x-height/2的高度对齐;

sub:降低元素的基线到父元素合适的下标位置;

text-bottom:把元素line box下边框对齐父元素的descent(即content bottom edge);

bottom:把元素line box下边框对齐父元素的line box下边框;

inherit:继承父元素的对齐方式。

 怎么这么多规则要记啊?我记性不好难道到时还要挨个查吗?其实归纳一下就OK了!

  1. 对齐操作必定涉及操作元素和参考系元素,而vertical-align的值全是指参考系元素的位置,而操作元素则以baseline或linebox上中下作对齐;
  2. 默认对齐方式为baseline,数量值均是相对于baseline而言。

vertical-align仅对inline-level和table-cell元素有效

注意:vertical-align仅对inline-level和table-cell元素有效,下面示例无效是正常不过的。

<div>
<div style="float:left;font-size:20px;vertical-align:middle;">I'm former</div>
<div style="float:left;font-size:50px;vertical-align:middle;">I'm latter</div>
</div>

CSS魔法堂:深入理解line-height和vertical-align

IE9+下的vertical-align属性值详解(以下内容均在Chrome43中测试)

1.默认对齐方式——baseline

<div style="font-size:14px;">
<span id="obj" style="font-size:40px;">line-height x vertical-align</span>
x for reference frame
</div>

CSS魔法堂:深入理解line-height和vertical-align

这里x for reference frame作为参考系,而它的baseline就是span#obj所要对齐的baseline了。

那么在baseline的基础上的设置<length>和<percentage>

<div style="font-size:14px;">
<span id="obj" style="font-size:40px;vertical-align:10px;">line-height x vertical-align</span>
x for reference frame
</div>
<div style="font-size:14px;">
<span id="obj" style="font-size:40px;vertical-align:-10px;">line-height x vertical-align</span>
x for reference frame
</div>
<div style="font-size:14px;line-height:1;">
<span id="obj" style="font-size:40px;vertical-align:50%;">line-height x vertical-align</span>
x for reference frame
</div>
<div style="font-size:14px;line-height:1;">
<span id="obj" style="font-size:40px;vertical-align:-50%;">line-height x vertical-align</span>
x for reference frame
</div>

CSS魔法堂:深入理解line-height和vertical-align

2.top——把元素line box上边框对齐父元素的line box上边框

 我们将上面的示例稍微改一下

<span style="font-size:14px;">
<span id="obj" style="font-size:40px;vertical-align:top;">line-height x vertical-align</span>
x for reference frame
</span>

CSS魔法堂:深入理解line-height和vertical-align

确实不同了,但这无法证明是元素的line box上边框对齐父元素的line box上边框哦。那么我们改改代码看看

  <body style="margin:0 10px;padding:0;">
<div style="border:solid 1px blue;font-size:14px;line-height:1;">
<span id="parent" style="background:red;line-height:1;">
<span id="obj" style="background:yellow;font-size:40px;vertical-align:top;line-height:1;">line-height x vertical-align</span>
x for reference frame
</span>
</div>
</body>

CSS魔法堂:深入理解line-height和vertical-align

通过line-height:1使line box与content box/area的高度一致,虽然span#parentspan#obj的上边框对齐,但还不能说明什么。

  <body style="margin:0 10px;padding:0;">
<div style="position:relative;top:100px;;border:solid 1px blue;font-size:14px;line-height:1;">
<span id="parent" style="background:red;line-height:1;">
<span id="obj" style="background:yellow;font-size:40px;vertical-align:top;line-height:1;margin-top:100px;padding-top:100px;background-clip:content-box;">line-height x vertical-align</span>
x for reference frame
</span>
</div>
</body>

CSS魔法堂:深入理解line-height和vertical-align

没有任何变化。那改变line-height又如何呢?

  <body style="margin:0 10px;padding:0;">
<div style="border:solid 1px blue;font-size:14px;line-height:1;">
<span id="parent" style="background:red;line-height:2;">
<span style="display:inline-block;vertical-align:top;background:green;">
<span id="obj" style="background:yellow;font-size:40px;line-height:2;">line-height x vertical-align</span>
</span>
x for reference frame
</span>
</div>
</body>

CSS魔法堂:深入理解line-height和vertical-align

为了让span#obj的Half-leading清晰可见,特意添加一个display:inline-block的inline box包裹着span#obj。而span#parent也增大了Half-leading的高度。现在可以我们清晰看到确实是span#obj的line box的上边框对齐父元素的line box上边框。(同理证明了vertical-align:bottom是把元素line box下边框对齐父元素的line box下边框;)

注意:chrome下若外层div不添加font-size:14px;line-height:1;属性,将导致span#parent上有条空白间隙

CSS魔法堂:深入理解line-height和vertical-align

原因十分简单,那是因为span#parent的对齐方式是baseline,参考系是div的baseline,而div的line-height为normal,有空白间隙就是当然的事了。通过JS就可以看清楚了。

var div = document.getElementsByTagName('div')[0]
console.log(div.childNodes[0].nodeType) // 显示3,就是TextNode

其实除了在div上设置line-height:1之外,我们还可以在span#parent上设置vertical-align:top来解决。

  <body style="margin:0 10px;padding:0;">
<div style="border:solid 1px blue;font-size:14px;">
<span id="parent" style="background:red;line-height:1;vertical-align:top;">
<span id="obj" style="background:yellow;font-size:40px;vertical-align:top;line-height:1;">line-height x vertical-align</span>
x for reference frame
</span>
</div>
</body>

CSS魔法堂:深入理解line-height和vertical-align

3.text-top——把元素的line box上边框对齐父元素的ascent(即content top edge)

  <body style="margin:0 10px;padding:0;">
<div style="position:relative;top:100px;border:solid 1px blue;font-size:14px;line-height:1;"> <span id="parent" style="background:red;line-height:2;">
<span id="obj" style="background:yellow;vertical-align:text-top;font-size:2px;line-height:1;">*</span>
x for reference frame
</span>
</div>
</body>

CSS魔法堂:深入理解line-height和vertical-align

  <body style="margin:0 10px;padding:0;">
<div style="position:relative;top:100px;border:solid 1px blue;font-size:14px;line-height:1;"> <span id="parent" style="background:red;line-height:2;">
<span style="display:inline-block;vertical-align:text-top;border-top:solid 2px green;">
<span id="obj" style="background:yellow;font-size:2px;line-height:2;">*******</span>
</span>
x for reference frame
</span>
</div>
</body>

CSS魔法堂:深入理解line-height和vertical-align

4.middle——把元素line box中垂点与父元素基线 + x-height/2的高度对齐

  <body style="margin:0 10px;padding:0;">
<div style="border:solid 1px blue;font-size:40px;line-height:1;">
<span id="parent" style="background:red;line-height:1;">
<span id="obj" style="padding-top:10px;display:inline-block;background:yellow;font-size:15px;line-height:1;vertical-align:middle;">*******</span>x for reference frame
</span>
</div>
</body>

CSS魔法堂:深入理解line-height和vertical-align

注意

当元素的display:inline-block/inline-table等对应的是atomic inline-level box时,其line box高度为margin box的高度。若元素对应的是inline box,则其最小高度为line-height,最大则由子盒子决定。

IE5.5~8下vertical-align属性值详解

 由于我工作中没有适配IE8等历史浏览器的需求,因此详细内容请参考@张鑫旭的CSS vertical-align的深入理解(二)之text-top篇

 简单来说IE5.5~IE8下vertical-align:text-top是把元素的ascent对齐父元素的ascent(即content top edge)

真的掌握vertical-align了吗?

 到这里理论部分已经介绍完了,是时候通过示例来验证自己了!

单行文字的垂直居中对齐

    <style type="text/css">
.slma1{
border:solid 3px #888; font-size: 14px;
line-height: 100px;
}
</style>
<p class="slma1">
字体大小14px
</p> <style type="text/css">
.slma2{
border:solid 3px #888; font-size: 14px;
line-height: 100px;
}
.slma2 i{font-style:normal;font-weight:bolder;vertical-align:middle;}
.slma2 span{font-size:30px;vertical-align:middle;}
</style>
<p class="slma2">
<i>* </i>字体大小为14px<span>字体大小为30px</span>
</p>

CSS魔法堂:深入理解line-height和vertical-align

行数不固定的多行文字的垂直居中对齐

<style type="text/css">
.mlma1{
border:solid 3px #888; font-size: 14px;
line-height: 100px;
}
.mlma1 span{
line-height: 1.5;
display: inline-block;
vertical-align: middle;
}
</style>
<p class="mlma1">
<span> 第一行文本<br/>the second one.</span>&nbsp;
</p>

CSS魔法堂:深入理解line-height和vertical-align

大小不固定的图片的垂直居中对齐

    <style type="text/css">
.a{width: 100px; height: 100px;}
.b{width: 80px; height: 80px;}
.c{width: 60px; height: 60px;}
.container{
background: #ccc; line-height: 200px;
}
img{padding:5px;border:solid 1px blue;vertical-align:middle;}
</style>
<div class="container">
<img class="a" src="./john.png"/>
<img class="b" src="./john.png"/>
<img class="c" src="./john.png"/>
<img class="b" src="./john.png"/>
</div>

CSS魔法堂:深入理解line-height和vertical-align

总结

尊重原创,转载请注明来自:http://www.cnblogs.com/fsjohnhuang/p/5307706.html_肥子John

感谢

深入了解css的行高Line Height属性

我对CSS vertical-align的一些理解与认识(一)

CSS vertical-align的深入理解(二)之text-top篇

CSS深入理解vertical-align和line-height的基友关系

css行高line-height的一些深入理解及应用

大小不固定的图片、多行文字的水平垂直居中

深入理解 CSS 中的行高与基线

CSS魔法堂:深入理解line-height和vertical-align的更多相关文章

  1. CSS魔法堂:重拾Border之——图片作边框

    前言  当CSS3推出border-radius属性时我们是那么欣喜若狂啊,一想到终于不用再添加额外元素来模拟圆角了,但发现border-radius还分水平半径和垂直半径,然后又发现border-t ...

  2. CSS魔法堂:&quot&semi;那不是bug,是你不懂我&excl;&quot&semi; by inline-block

    前言  每当来个需要既要水平排版又要设置固定高宽时,我就会想起display:inline-block,还有为了支持IE5.5/6/7的hack*display:inline;*zoom:1;.然后发 ...

  3. CSS魔法堂:说说Float那个被埋没的志向

    前言  定位系统中第一难理解就是Normal flow,而第二就非Float莫属了,而Float难理解的原因有俩,1. 一开头我们就用错了:2. 它跟Normal flow靠得太近了.本文尝试理清Fl ...

  4. CSS魔法堂:Box-Shadow没那么简单啦&colon;&rpar;

    前言  说起box-shadow那第一个想法当然就是用来实现阴影,其实它还能用于实现其他好玩的效果的,本篇就打算说说box-shadow的那些事. 二话不说看效果 3D小球 <style typ ...

  5. CSS魔法堂:重拾Border之——解构Border

    前言  当CSS3推出border-radius属性时我们是那么欣喜若狂啊,一想到终于不用再添加额外元素来模拟圆角了,但发现border-radius还分水平半径和垂直半径,然后又发现border-t ...

  6. CSS魔法堂:小结一下Box Model与Positioning Scheme

    前言  对于Box Model和Positioning Scheme中3种定位模式的细节,已经通过以下几篇文章记录了我对其的理解和思考.  <CSS魔法堂:重新认识Box Model.IFC.B ...

  7. CSS魔法堂:你一定误解过的Normal flow

    前言  刚接触CSS时经常听到看到一个词"文档流",那到底什么是"文档流"呢?然后会看到"绝对定位和浮动定位能脱离文档流",从这句可以看到文 ...

  8. CSS魔法堂:Absolute Positioning就这个样

    前言 当我们以position:absolute之名让元素脱离Normal flow的控制后,以为通过left和top属性值即可让元素得以无限的*时,却发现还有各种神秘的力量左右着它的来去,于是我们 ...

  9. CSS魔法堂:你真的懂text-align吗?

    前言 也许提及text-align你会想起水平居中,但除了这个你对它还有多少了解呢?本篇打算和大家一起来跟text-align来一次负距离的交往,你准备好了吗? text-align属性详解 The ...

随机推荐

  1. [linux basic 基础]----同步信号量

    直接使用一个共享变量,来是两个线程之间进行切换是非常笨拙而且没有效率的:信号量--互斥量--这两者是相互通过对方来实现的:比如,如果想控制某一时刻只有一个线程可以访问一些共享内存,使用互斥量要自然一些 ...

  2. 关于springboot启动的问题&period;

    IDE使用的是IDEA: 遇到的问题:使用springboot自带main方法无法启动示例,解决方案: 如果大家使用Application中的main方法无法正常启动时,可以去修改Project St ...

  3. BZOJ&lowbar;2223&lowbar;&lbrack;Coci 2009&rsqb;PATULJCI&lowbar;主席树

    BZOJ_2223_[Coci 2009]PATULJCI_主席树 Description Input 10 3 1 2 1 2 1 2 3 2 3 3 8 1 2 1 3 1 4 1 5 2 5 2 ...

  4. ASP&period;NET MVC &plus; EF 更新的几种方式(超赞)

    1.常用 db.Entry(实体).State = EntityState.Modified;db.SaveChanges(); 2.指定更新 db.Configuration.ValidateOnS ...

  5. JAVAWEB 一一 框架整合(SSH&comma;Spring&plus;Struts2&plus;Hibernate IOC&sol;DI AOP声明式事务处理 定时任务)

    package org.springframework.orm.hibernate3; import java.io.Serializable; import java.util.List; impo ...

  6. 无法将参数 1 从&OpenCurlyDoubleQuote;WCHAR &lbrack;256&rsqb;”转换为&OpenCurlyDoubleQuote;const char &ast;”

    https://blog.csdn.net/zhangxuechao_/article/details/81064037 字符集 修改为未设置 然后再修改回来unicode  居然好了

  7. jsp中的隐含9对象

    jsp中的隐含9对象 request ----> HttpServletRequest. response ---> HttpServletResponse. session ----&g ...

  8. Unity另外一套简单日志控制系统

    using UnityEngine; public class LogPrintf { static LogLevel logLevel = LogLevel.LOG_LEVEL_ERROR; pub ...

  9. 7&period;计算N元等式&lbrack;穷举&rsqb;

    穷举的一种应用,计算x+2y+3z=50的非负整数解.先约束每个变量的最大值,x=50,y=25,z=50/3. #include <iostream> using namespace s ...

  10. JVM类加载机制详解(二)类加载器与双亲委派模型

    在上一篇JVM类加载机制详解(一)JVM类加载过程中说到,类加载机制的第一个阶段加载做的工作有: 1.通过一个类的全限定名(包名与类名)来获取定义此类的二进制字节流(Class文件).而获取的方式,可 ...