添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

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

这篇文章发布于 2009年11月28日,星期六,02:51,归类于 CSS相关 。 阅读 565634 次, 今日 26 次 127 条评论

补充于2017年12月31日:写本文时本人尚年轻,很多措辞和观点并不严谨,内容仅供参考。更体系更深入的理解在我的 《CSS世界》 这边书中有详细阐述。

前两天在腾讯ISD团队博客上看到一篇翻译的文章“深入理解CSS行高”(原地址失效已久),是个不错的文章,学到了不少东西,建议您看看。

这里,我也要讲讲我对 line-height 的一些理解,所讲解的东西绝大多数与上面提到的“ 深入理解css 行高 ”是不重复的,可以说是补充或是另外一个角度的思考。另外,将结合实际,展示 line-height 的一些特性和一些常见应用,帮助您对CSS行高 line-height 的理解。所讲述的并不一定都是正确的,欢迎指正欢迎交流。

二、一些字面意思

“行高”顾名思意指一行文字的高度。具体来说是指两行文字间基线之间的距离。基线实在英文字母中用到的一个概念,我们刚学英语的时使用的那个英语本子每行有四条线,其中底部第二条线就是基线,是a,c,z,x等字母的底边线。下图的红色线即为基线。

vertical-align 中有 top , middle , baseline , bottom 与之是由关联的,但具体细节如何,浏览器差异怎样,我还不是很清楚。

但是由于中文跟英文长得不一样,所以基线的说法就像老太太穿线——对不上眼。您理解为底线之差也不为不可。只是定义一回事,表现则另一回事。

三、line-height与line boxes高度

CSS中起高度作用的应该就是 height 以及 line-height 了吧!如果一个标签没有定义 height 属性(包括百分比高度),那么其最终表现的高度一定是由 line-height 起作用,即使是IE6下 11 像素左右默认高度bug也是如此。待我慢慢叙来。

先说一个大家都熟知的现象,有一个空的 div <div></div> ,如果没有设置至少大于 1 像素高度 height 值时,该 div 的高度就是个 0 。如果该 div 里面打入了一个空格或是文字,则此 div 就会有一个高度。那么您思考过没有,为什么 div 里面有文字后就会有高度呢?

这是个看上去很简单的问题,是理解 line-height 非常重要的一个问题。可能有人会跟认为是:文字撑开的!文字占据空间,自然将 div 撑开。我一开始也是这样理解的,但是事实上,深入理解 inline 模型后,我发现,根本不是文字撑开了 div 的高度,而是 line-height !要证明很简单(如下测试代码):

CSS代码:

.test1{font-size:20px; line-height:0; border:1px solid #cccccc; background:#eeeeee;}
.test2{font-size:0; line-height:20px; border:1px solid #cccccc; background:#eeeeee;}

HTML代码:

<div class="test1">测试</div>
<div class="test2">测试</div>

结果如下图(windows IE6浏览器下):

结果是如此的显而易见,test1 div有文字大小,但行高为0,结果div的高度就是个0;test2 div文字大小为0,但是有行高,为20像素,结果div高度就是20像素。这就说明撑开div高度的是line-height不是文字内容。

到底这个line-height行高怎么就产生了高度呢?在inline box模型中,有个line boxes,这玩意是看不见的,这个玩意的工作就是包裹每行文字。一行文字一个line boxes。例如“艾佛森退役”这5个字,如果它们在一行显示,你艾佛森再牛逼,对不起,只有一个line boxes罩着你;但“春哥纯爷们”这5个字,要是竖着写,一行一个,那真是够爷们,一个字罩着一个line boxes,于是总计五个line boxesline boxes什么特性也没有,就高度。所以一个没有设置height属性的div的高度就是由一个一个line boxes的高度堆积而成的。

其实line boxes不是直接的生产者,属于中层干部,真正的活儿都是它的手下 – inline boxes干的,这些手下就是文字啦,图片啊,<span>之类的inline属性的标签啦。line boxes只是个考察汇报人员,考察它的手下谁的实际line-height值最高,谁最高,它就要谁的值,然后向上汇报,形成高度。例如,<span style="line-height:20px;">取手下line-height<span style="line-height:40px;">最高</span>的值</span>。则line boxes的高度就是40像素了。

四、行高的垂直居中性

行高还有一个特性,叫做垂直居中性。line-height的最终表现是通过line boxes实现的,而无论line boxes所占据的高度是多少(无论比文字大还是比文字小),其占据的空间都是与文字内容公用水平中垂线的。还拿上面这张图来说吧。

看test1的结果,此时line boxes的高度为0,但是它是以文字的水平中垂线对称分布的。这一重要的特性可以用来实现文字或图片的垂直居中对齐。

五、在单行或多行或图片垂直居中实现上的应用

您可以狠狠地点击这里:行高实现单行和多行文字垂直居中demo

1、单行文字的垂直居中对齐

网上都是这么说的,把line-height值设置为height一样大小的值可以实现单行文字的垂直居中。这句话确实是正确的,但其实也是有问题的。问题在于height,看我的表述:“把line-height设置为您需要的box的大小可以实现单行文字的垂直居中”,差别在于我把height去掉了,这个height是多余的,您不信您可以自己试试。

2、多行文字的垂直居中

要实现高度不固定的文字垂直居中使用padding就好了。对于高度固定的div,里面文字单行或多行显示,字体大小有大有小的情况怎么办呢?方法之一就是借助于line-height

下图为demo页面的截图批注图:

正如上面所说,line boxes的高度取决于它的下属职员的最高高度。而这个高度由一个不占据任何空间的空格完成,方法即使设置font-size0line-height为所需要的高度。同时,我们为了分隔line boxes,同时要保持在一行上,需要设置display属性值为inline-block。如下代码,有别于demo:

CSS代码:

.mulit_line{line-height:150px; border:1px dashed #cccccc; padding-left:5px; font-size:0;}
.mulit_line span{display:-moz-inline-stack; display:inline-block; line-height:1.4em; vertical-align:middle;}
.mulit_line i{width:0; display:-moz-inline-stack; display:inline-block; vertical-align:middle;}

感谢小西的提醒,下为修复IE8问题后的代码:

.mulit_line{line-height:150px; border:1px dashed #cccccc; padding-left:5px;}
.mulit_line span{display:-moz-inline-stack; display:inline-block; line-height:1.4em; vertical-align:middle;}
.mulit_line i{width:0; display:-moz-inline-stack; display:inline-block; vertical-align:middle; font-size:0;}

html代码:

<p class="mulit_line">
    <span style="font-size:12px;">这里是高度为150像素的标签内的多行文字,文字大小为12像素。<br />这里是第二行,用来测试多行的显示效果。</span><i>&nbsp;</i>

效果如上批注图。已通过IE8以外的主流浏览器的兼容性检测。以前曾见过说IE8的line-height有些问题,如果谁发现IE8下有问题,欢迎指出,不甚感谢。

3、图片的垂直居中

您可以狠狠地单击这里:行高使图片垂直居中显示demo

此方法在“大小不固定的图片、多行文字的水平垂直居中”一文中的最后补充内容里已经详细讲解了。这里不多说了。

//zxx:之前未能在IE8下测试,现发现此方法不仅在Opera下有问题,在IE8下也是表现欠佳。所以仅仅使用line-height的垂直居中法有待斟酌,或许要使用与上面多行文字垂直居中的同样的方法来实现图片垂直居中的效果。

六、行高在文章显示中的应用

一般社交型的网站都会有发博文或写日志的功能,其中发表后的文章显示也是有学问的,其中之一就是line-height行高。

首先要知道行高的几种表示方法:px/em,或normal,或百分值,或数值,或inherit继承。

在显示文章的box里,px的表示方法首先是要被淘汰的。因为文章里面的文字是有大有小的,使用px定值,由于继承性,无法实现根据文字大小自动调整间距,会出现大号文字重叠的现象。normal也是不行的,一般文章显示最好是650像素的宽度,1.5倍的行距较好。一般浏览器的normal值在1~1.2之间,使用normal必然文字间距过小,阅读吃力。百分值也有继承性,但是有个很搓的办法可以实现文字间距自动适应于文字的大小,那就是使用*通配符,例如:

.article_box *{line-height:150%;}

就不会出现文字重叠的情况了。网易博客就是使用的这个方法,下图为证:

为什么说这个方法搓呢,使用*通配符大大增加了CSS的渲染,效率低,而且有更好的方法,就是使用数值。150%虽然和1.5在值上是一样的,但是它们也是有差别的,差别在于继承性,使用百分比会计算line-height的值,然后以px像素为单位继承下去,而1.5则是先继承1.5这个值,遍历到了该标签再计算去line-height的像素值。所以同样的效果只需要下面CSS就可以实现了。

.article_box{line-height:1.5;}

七、使用行高代替高度避免haslayout

在某些情形下,line-height可以和height互换,因为实现的效果一样。都能撑开一个高度,然而这两个CSS属性有一个较隐蔽的差异,就是使用height会使标签haslayout,而使用line-height则不会。以前只有IE6的时候曾流行使用height清除浮动,就是利用了IE下height使haslayout的属性。但有时候,haslayout并不需要,反而要避免。

读过我前面有关自适应按钮文章的人可能会发现我使用了line-height代替了height,其原因在于:IE6,IE7下,类似inline-block属性的元素里如果有block属性的元素,如果该block haslayout,则该标签会冲破外部inline-block的显示而宽度100%显示,从使按钮自适应文字大小的效果失效,解决方法就是使用line-height代替height

上图中第一个标签使用height定高,结果宽度直接100%显示;第二个标签使用line-height定高,结果很规矩,自适应与内部文字大小。其代码如下:

CSS部分:

.out{display:inline-block; background:#a0b3d6; margin-top:20px;}
.in1{display:block; height:20px;}
.in2{display:block; line-height:20px;}

HTML部分:

<span class="out">
    <span class="in1">height:20px;</span>
</span>
<span class="out">
    <span class="in2">line-height:20px;</span>
</span>

很多关于line-height的基础的知识这里并没有详细讲述,本文一开始提到的腾讯ISD团队的那篇关于行高的文章是不错的,对于了解line-height的一些特性及inline box模型很有帮助。本文更多的是讲述自己对于line-height的一些理解,简述了我使用line-height的一些经验。由于都是个人的些东西,加上本身自己的资历有限,所以可能会出现一些错误,一些遗漏之处等,还望了解。欢迎指正。要是能对您的学习有所帮助就再好不过了。

(本篇完)

2020年05月30日 13:40

移动端,一行文字带背景,文字总是不能垂直居中,使用line-height或者display:flex,aligin-items:center,都不能做到兼容;
有时候苹果可以,但是安卓不行。如果安卓垂直居中了,苹果就偏上或者偏下1

2020年06月6日 17:54

移动端的line-height问题,他与pc端还是有差别的,可能安卓调整好了,但是ios却不行,这个问题一直困扰着我,试了很多方法 ,一直无法去完美适配。

2020年08月8日 17:30

用了line-height === height在ios上表现垂直居中,在android偏下显示;用了display: flex; align-items: center则在android上垂直居中,在ios偏上显示

不适用 html5 的docType ,
2 docType 为html5 时应如何实现 Transitional 的效果
那么 以下html 如何满足 根据字体大小 自适应行高呢?
https://codepen.io/sguoe/pen/oNvYWXq

.quill-editor{
font-size:30px;
line-height:1.2;
.smaller{
font-size:0.75em;
background:#eee;
border:1px solid #999;

正常字体:预期行高30*1.2=36px
小号:预期行高30*0.75*1.2=27px

.out{display:inline-block; background:#a0b3d6; margin-top:20px;}
.in1{display:block; height:20px;}
.in2{display:block; line-height:20px;}
这个样式里面in1的block不是在out的inline-block里面么?为什么两个out的块会换行显示呢?

height:20px;

line-height:20px;

height:20px和line-height:20px还是在同一行啊。为什么你文中的换行了呢?

“行高”顾名思意指一行文字的高度。具体来说是指两行文字间基线之间的距离。
————————————————————————————————————-
张老师,w3.org 中规定行框的高度是其中盒子们的最高点和最低点的高度。
如果有两个 span,line-height 都是400px,一个 font-size:200px 另外一个font-size:100px。如果该行盒的 vertical-align:baseline,那么第二个 span 的字符的底部必然要往下沉,既然 line-height 不变,那么第二个 span 的盒子整体往下沉。
因此,该行盒的高度势必大于 400px。如果 p 标签中有多个行盒,那么其中 span 所在行盒的高度肯定比其他只有文字的行盒要高。那么“两行文字间基线之间的距离”就存在问题了。

还有,不太明白这句话:
“我们为了分隔line boxes,同时要保持在一行上,需要设置display属性为inline-block。”

为什么加上inline-block之后,就显示在一行了呢?
而且也不是显示在一行啊,仍然在呀。。?

2017年10月25日 15:48

line-height 在安卓机器显示不是居中,而是总往上偏。比方所 box height是24px 正常设置line-height:24px;但是在安卓机器上明显看出文字是偏上。问一下这个问题怎么解决,苹果是正常上下居中。

2017年10月11日 13:08

[要实现高度不固定的文字垂直居中使用padding就好了。对于高度固定的div,里面文字单行或多行显示,字体大小有大有小的情况怎么办呢?方法之一就是借助于line-height。]———–这句话是不是写错了,应该: 固定高度的文字垂直居中使用padding,高度不固定的div,使用line-height

2017年08月15日 14:16

在IE浏览器中,你的line-height压根就不会响应如果不设置height的话。虽然设置line-height为150px,但是在IE浏览器中只能布局出56px的效果。

2017年07月14日 23:04

非常感谢LZ的解释,看过了其它的文章,感觉有待考虑。可能是时间久远的缘故。https://www.w3cplus.com/css/css-font-metrics-line-height-and-vertical-align.html 这个上面解释也很全面

2017年05月18日 14:22

现在最新版本的chrome浏览器,改变了渲染。如果一个div没有高度,你给它设置line-height是没有效果的。我记得以前不是这样,直接设置line-height的高度值,是有高度的。
所以现在chrome下的垂直居中,vertical-align:middle只能搭配文字使用。

2017年05月1日 15:12

旭神,不知道是不是历史原因,我现在用的Firefox和chrome在line-height继承上的表现都不像font-size那样,line-height值的含义也与font-size表示的不一样。line-height值设为1.5或150%是一样的。line-height的1.5和150%都表示自己原本的行高的1.5倍,而不是父亲行高的1.5倍,实际的表现只与自己的font-size有关。

2017年05月1日 15:37

我说错了一个地方:1.5和150%是不一样的,150%是一个替换数值,继承的时候150%会被计算出来,然后将计算得到得到的值往下继承,如果子元素没有line-height属性,那么子元素的line-height就是这个父亲传递下来的值。而父亲的line-height值为1.5且子元素没有line-height属性时,父亲将1.5传递下去,子元素的line-height的值为1.5,也就是1.5倍行高(此时子元素的表现与自己的font-size有关)。但当子元素有line-height属性,无论其为1.5还是150%都与父亲无关,实际表现为1.5倍行间距(也是和子元素的font-size有关)

2017年01月18日 22:53

在多行文字应用那里,我试了下把《i》给去掉,按理说外层元素的行高是通过继承给内部元素撑开的,但为什么《span》的line-height重置了,《i》又被我去掉了,外层元素的行高还是保持150px?百思不得解

2017年01月18日 22:51

在多行文字,我试了下把 给去掉,按理说外层元素的行高是通过继承给内部元素撑开的,但为什么的line-height重置了, 又被我去掉了,外层元素的行高还是保持150px?百思不得解

2016年12月29日 16:05

《div style=”border:1px solid black;line-height:100px;”》《a style=”font-size:100px;”》A《/a》《/div》
这样使用line-height 为什么会导致 子元素置顶 而且 下面会多出一段空白,按道理讲他应该会和父元素没有间隙才对啊。

(话说站长,是不是该给一个尖括号不能成对出现的提示喃)

<div style="border:1px solid black;line-height:100px;"A</a></div>
这样使用line-height 为什么会导致 子元素置顶 而且 下面会多出一段空白,按道理讲他应该会和父元素没有间隙才对啊。

2016年11月22日 15:04

今天扩展我自己的控件样式的时候,由于输入框同按钮的高度及垂直对齐的问题,打算把原先的padding实现的按字体大小自适应的控件,更改为垂直方向用line-height来实现,在FF和Chrome中表现良好,但是对于input的文本输入框在IE下line-height却没有把他的高度撑开,虽然我定义了display:inline-block的属性。请问是否有方法能协调这块。
html{ font-size:10px;}
.rexInput{ display :inline-block; font-size: inherit; padding: 0 0.8rem; border: 1px solid #ccc; line-height: 3rem;}
—————————————————

博主,”差别在于我把height去掉了,这个height是多余的“ 这个height是不能够被去掉的。
这个height有一个调节的作用,假设现在height为20px,而你设置的line-height为50px,你试下此时文字会不会居中显示???
height-line-height的值会被平分到font-size 的两边;

2016年11月22日 14:45

没有很理解你说的这个实际意思,用到line-height了,一般就不会再去刻意书写height,按你说的样式定义,文字会显示在DOM块的底部以下。

2017年11月21日 19:34

最后一句不太懂,按照我的测试,如果设置height为20px,line-height为50px时,文字应该处于元素底部或者超出元素底部范围,假设文字的font-size为30px;line-height所占区域分配是字体上下各10px;字体本身30px;然后由于高度为20px,字体会在三分之一高度处被截取

2016年09月2日 11:14

旭神,您好! 我是一个前端小渣,看了您的这篇博文对line-height有了更深的理解,我自己也动手实现和测试了用line-height来实现多行文字和图片的水平垂直居中,有几点不同和问题:1、可以采用伪元素:after 节省一个标签 2、当内容是图片的时候,给图片设定宽度或者高度,图片会得到一个宽高度的比值,宽:高=5:3(问题,不造怎么来的~~~)【测试环境:window8.1 IE7+和现代浏览器】
Code:

水平垂直居中—line-height

margin: 0;
padding: 0;

.parent {

border: 1px dashed #cccccc;
padding-left: 5px;
line-height: 600px;
text-align: center;

background-color: #666;

.parent-img {

/*宽度和高度之比 width:height = 5:3*/
/*width: 500px;*/
height: 300px;
vertical-align: middle;

.parent-content {

display: inline-block;
line-height: 1.4em;
text-align: left;
vertical-align: middle;

.parent-img:after,
.parent-content:after { /*直接使用伪元素 可以省去一个标签*/

content: “.”;
display: inline-block;
width: 0;
font-size: 0;
vertical-align: middle;
这里是高度为150像素的标签内的多行文字。

这里是第二行,用来测试多行的显示效果。

给 textarea 设置 line-height 后,第 1 行 cursor 的高度会比第 2 行 cursor 的高度小。如下图:

![textarea-cursor.png]( http://ww1.sinaimg.cn/large/72f96cbagw1f6pnb17e09j205y0210sp.jpg )

我观察了腾讯视频、豆瓣和微博,它们也都存在这样的问题。不知道是否有解决办法?

2016年07月26日 11:23

line-height:1(无单位)此时叫缩放因子,子元素会继承父元素的缩放因子值1,再根据子元素的font-size动态计算出子元素的行高。即如果不设置该文章下的元素的行高,默认行高等于默认字号的高度

2016年05月28日 12:21

css中起高度作用的应该就是height以及line-height了吧!如果一个标签没有定义height属性(包括百分比高度),那么其最终表现的高度一定是由line-height起作用?
请问 如果一个div 没有设置高度也没有设置行高,只有一行文字,那么按照楼主的解释,那么这段文字的高度应该是有行框来决定的,既然是由行框来决定,那么请问 行框 属于 行高吗 ?明显是悖论 !

2016年06月7日 16:26

div 没有设置height以及line-height,是由里面文字ine boxes 这个模型决定,而文字会继承body里面的line-height属性!

2016年05月7日 19:39

您好!关于三、line-height与line boxes高度,我在chrome下测试的是div确实如您所说的,但是span元素却是相反的表现,也就是行高设置为0,而字体大小设置不为0时,有高度,而相反情况,没有高度~

2016年03月18日 22:49

当div是空的状态下,设置line-height的值,div会被撑开,那么是不是说line-height把值赋给了lineboxes所以div才会被撑开;
另一种情况是当给div的line-height设置为50px,给div中文字的font-size设置为100,这时取出了div的line-height的值为1,文字部分超出到div的外面去了,那么这种情况
是否可以这样总结,当给div同时设置了line-height和文字的font-size,lineboxes有优先取line-height的值。
那么我想问一下lineboxes和line-height的是个什么关系?是否可以说line-height是lineboxes高度值的一种设置方式,在给lineboxes设置是line-height的优先级别比
文字高度、图片高度等值的优先级高呢?

$(document).ready(function(){

var lineHig = $(“#div2”).css(“line-height”);
alert(“height-line高度:”+lineHig);

#div1{font-size:30px;border:2px solid red;line-height:0px;}
#div2{font-size:50px;border:2px solid blue;line-height:1px;}

2016年02月25日 14:42

懂了。vertical-align 指的的元素的垂直布局,而不是元素内部文字的布局。一开始一直以为vertical-align是指元素内部文子的垂直布局,所以一开始怎么看都糊涂。

2016年01月28日 21:19

网上都是这么说的,把line-height值设置为height一样大小的值可以实现单行文字的垂直居中。这句话确实是正确的,但其实也是有问题的。问题在于height,看我的表述:“把line-height设置为您需要的box的大小可以实现单行文字的垂直居中”,差别在于我把height去掉了,这个height是多余的,您不信您可以自己试试。

我觉得你的表述是有问题的line-height是不可能设置为BOX一样大小的。BOX是一个盒子有宽有高。而问题的关键就在于height,你却说是多余的。

2017年02月20日 11:51

如果你想利用line-height来垂直居中,那height就是多余的,但是如果你需要元素可设置背景,那height就是必须的,文主所说的情况就是居中,所以没错

张鑫旭 ,09年 华中科技大学 毕业,现 上海 ,就职于 阅文集团 ,专注 web前端 偏前领域,著有 《CSS世界》 《CSS选择器世界》 《CSS新世界》

邮箱: [email protected]

关注我: 微信 微博 掘金 知乎 头条 B站 Gitee

  • 小tip: margin:auto实现绝对定位元素的水平垂直居中 (60)
  • AI代码辅助工具codeium和copilot在前端表现对比 (58)
  • 以20像素为基准的CSS网页布局实践分享 (51)
  • jQuery页面滚动图片等元素动态加载实现 (47)
  • JS判断图像背景颜色单一还是丰富 (44)
  • 页面级可视动画View Transitions API初体验 (42)
  • jQuery powerFloat万能浮动层下拉层插件 (36)
  • 使用jsPDF导出PDF文件实践分享 (35)
  • CSS3 transform对普通元素的N多渲染影响 (34)
  • 让CSS flex布局最后一行列表左对齐的N种方法 (34)
  • 今年热议

  •