Contents
  1. 1. 几个基本概念
    1. 1.1. 顶线、中线、基线、底线
    2. 1.2. 行高、行距、半行距
    3. 1.3. inline box、line box
    4. 1.4. 替代元素和非替代元素
  2. 2. line-height
    1. 2.1. 定义
    2. 2.2. 取值
  3. 3. vertical-align
  4. 4. 应用
    1. 4.1. 幽灵空白节点
    2. 4.2. 解决问题
  5. 5. 个人总结
  6. 6. 最后一个例子

虽然写过不少css代码,可是在实战中关于css的问题依旧很多,比如有时想利用line-height来实现垂直居中的效果,但是结果却经常令我费解。

这篇文章就整理一下css中关于line-heightvertical-align的概念和知识。

几个基本概念

在进入正题之前,我们需要先了解几个概念:

顶线、中线、基线、底线

上图标识出了顶线、中线、基线、底线的位置,而他们正好对应vertical-align中的topmiddlebaselinebottom这几个属性属性值。

其中,font-size即为顶线到底线之间的垂直距离。

行高、行距、半行距

其中行高(line-height)为文本行基线间的垂直距离。

行距为上一行的底线和下一行的顶线之间的距离,而半行距为行距的一半。

inline box、line box

inline box(行内框):每个行内元素会生成一个行内框。行内框是浏览器渲染模型中的一个概念,无法现实出来。行内框的高度等于font-size。设置line-height时,行内框的高度不会变,改变的是行距。

line-box(行框):行框指本行中一个虚拟的矩形框,由该行中行内框组成。行框高度取决于本行中所有行内框高度的最大值以及line-height。当由多行内容时,每一行都有自己的行框。

替代元素和非替代元素

替代元素就是指浏览器根据元素的属性来判断具体要显示什么内容,比如img标签,浏览器是根据src的属性值来显示图片内容的。

常见的替代元素还有inputselectvideo等。这些元素,浏览器都不直接显示其内容,而是根据某个属性值来显示对应的内容,比如根据input元素的type属性值来决定显示哪一种类型的的input。


而对于非替代元素,浏览器则直接显示元素所包含的内容,比如plabel等。

line-height

下面我们来进入正题,来聊一聊line-height这个属性。

定义

MDN line-height给出了以下定义:


  1. 对于块级元素,line-height指定了元素内部的line boxes的最小高度。
  2. 对于非替代行内元素(span、a等),line-height用于计算line box的高度。
  3. 对于替代行内元素(img,input等),line-height没有影响。

总结来说,line-height设置行框(line-box)的高度,如果一个标签没有设置height属性,那么其最终表现的高度一定是由line-height起作用。

取值

取值 说明 继承
normal 取决与用户代理,桌面浏览器默认约为1.2 继承1.2,然后乘以本身font-size
[ number ] line-height值为font-size乘以[ number ] 继承[ number ],然后乘以本身font-size
[ length ] length为具体长度,比如20px或者50rem 继承20px
[ percentage ] 百分比,比如200%,若font-size为100px,则line-height为200px 继承计算后的200px

而最为推荐的方式是,使用[ number ]来为line-height赋值。

vertical-align

vertical-align属性用来设置行内元素的垂直对齐方式

该属性定义行内元素的基线相对于该元素所在行的基线的垂直对齐。

它可能的取值有以下:

1
2
3
4
5
6
7
8
9
10
baseline(默认) // 元素放置在父元素的基线上。
sub // 垂直对齐文本的下标
super // 垂直对齐文本的上标
top // 把元素的顶端和行中最高元素的顶端对齐
text-top // 把元素的顶端和父元素字体的顶端对齐
middle(常用) // 把此元素放置在父元素的中部
bottom // 把元素与父元素底端对齐
length
%(与line-height有关) // 使用line-height乘以百分比来排列此元素
inherit // 从父元素继承

比如我们可以使用vertical-align来将一个块级元素中,所有内联元素垂直居中:

刚开始是这样的:

当我们加入以下样式之后:

1
2
3
main *{
vertical-align: middle;
}

这样就实现了垂直居中。

应用

假设我们在一个div中添加了一个图片,并给这个div设置了一个背景色。HTML如下:

1
2
3
<div>
<img src="img/2.jpg" height="200px"/>xwj
</div>

然后,我们在浏览器中运行,发现结果如下:

其中图片的高度为200px,但是div的高度为什么却是203px?div的高度为什么会多出来几个像素呢?

上面这个令人费解的表现,其实就可以使用line-heightvertical-align来解释。

幽灵空白节点

这个名词取自这篇文章,它表达的意思为;

在HTML5文档声明下,块状元素内部的内联元素行为表现,就好像块状元素内部还有一个看不见的宽度为0的空白节点,这个空白的节点的表现就像一个匿名的inline-box一样。

假如我们在img标签后面加上几个字符,并且把这几个字符的font-size属性调为200px,那么表现会更加明显:

如果我们再给图像加上100px的margin-bottom,那么会变成以下的样子:

从上面可以看出,vertical-align默认值是baseline,也就是基线对齐。

解决问题

既然知道了以上问题是由于基线对齐引起的,那么我们就可以对症下药,来把图片下面多的几个像素去掉吧。

有以下几种解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*方法一:让 vertical-align失效,因为其只对行内元素起作用*/
img{
display: block;
}
/*方法二:使用其他vertical-align值,比如bottom/middle/top等.*/
img{
vertical-align: bottom;
}
/*方法三:直接修改line-height值*/
div{
line-height: 1px;
}
/*方法四:line-height为相对单位,font-size间接控制,本质为修改line-height*/
div{
font-size: 0px;
}

以上几种方法,都能去掉图片下面多出来的几像素,其中方法一迫使后面的字符换行,方法四会让后面文字消失,方法二和方法三则会影响后面文字的表现:


个人总结

以下是我个人的总结,正确性有待考究:

对于块级元素,如果里面有行内元素(可能是img,也可能是inline-block的span等),则第一个元素的基线就是父元素的基线,其后的行内元素都会依照此基线对齐

如果第一个元素内部有inline boxes,比如一些字符,那么该元素基线为字母x的下边缘,如果第一个元素没有inline boxes,比如一个空的span,那么该元素的基线就是margin的底边缘

最后一个例子

最后通过一个例子来说明以上总结:

html如下,两个span,一个包含字符,一个没有包含;

1
2
3
4
<div id="main">
<span>xwj</span>
<span></span>
</div>

css如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#main{
background-color: #0bc;
font-size: 100px;
}
#main span{
display: inline-block;
border: solid 1px #0AA284;
background-color: #BBBBBB;
}
#main span:first-child{
width: 200px;
height: 200px;
}
#main span:last-child{
width: 300px;
height: 300px;
}

最终的结果如下:

如果我们作出一点点改变呢?比如,将两个span标签的顺序调换一下,那么将结果如下:

哈哈,是不是很有趣。

那么,这并非我们的期望,我们如何是他们表现正常呢?答案当然还是line-heightvertical-align,大家自己考虑一下吧~

完结。

Contents
  1. 1. 几个基本概念
    1. 1.1. 顶线、中线、基线、底线
    2. 1.2. 行高、行距、半行距
    3. 1.3. inline box、line box
    4. 1.4. 替代元素和非替代元素
  2. 2. line-height
    1. 2.1. 定义
    2. 2.2. 取值
  3. 3. vertical-align
  4. 4. 应用
    1. 4.1. 幽灵空白节点
    2. 4.2. 解决问题
  5. 5. 个人总结
  6. 6. 最后一个例子