深入理解line-height和vertical-align
1.什么是行高(line-height)?
line-height用于设置文本的最小行高,可以简单理解为一行文字所占据的高度。但是行高的严格的定义是:两行文字基线(baseline)之间的距离。
那么什么是基线(baseline)呢?
- 基线是与小写字母x最底部对齐的线,具体可参考下面的图。
注意区分height和line-height的区别:
- height:元素的整体高度;
- line-height:元素中一行文字所占据的高度;
- 如果想要文字在元素内部垂直居中,让line-height等于元素的height即可;
2.vertical-align属性
参考官方文档的解释,vertical-align会影响行内级元素在一个行盒(line boxes)中垂直方向的位置。简单来说vertical-align可以设置行内级元素在一行上的对齐方式。
2.1.什么是行盒(line boxes)?
通过以下这些问题进一步了解行盒。
首先可以思考一下,一个div在没有设置高度时,会不会有高度?
- 如果div中没有内容,就没有高度;
- 如果div中有内容,内容可以撑起来div的高度;
内容能够撑起来div高度的本质是什么?
- 根据上面行高的解释,内容具有行高(line-height),本质是行高撑起了div的高度;
这里又会有一个疑问,行高为什么可以撑起div高度?
- 这是因为有行盒的存在,并且行盒有一个特性,它会包裹每行的行内级元素;
- 而其中的文字有行高,行盒必须将整个行高包裹进去,多个行盒的高度加在一起就组成了div的高度;
如果这个div中有图片、文字、inline-block等行内级元素,他们如何进行对齐呢?
- 默认都是基线对齐;
2.2.深入了解基线对齐
行内级元素基线对齐,可能会出现以下这些情况:
(1)情况一:只有文字时。
- 行盒包裹整个文字的行高;
(2)情况二:既有文字,又有图片。
- 图片的底部与文字的基线进行对齐,这就是为什么图片底部会留出几个像素;
- 行盒包裹整个行内级元素,较大的图片也会被包裹进去;
(3)情况三:既有文字,又有图片,还有inline-block。
- inline-block和图片的底部都与文字的基线进行对齐;
- 行盒包裹整个行内级元素,高度由较高的那一个决定;
(4)情况四:既有文字,又有图片,还有inline-block,并且给inline-block设置底边距。
- 行盒会将设置的底边距一起包裹进去;
(5)情况五:既有文字,又有图片,还有inline-block,并且给inline-block内添加文字。
- 这时inline-block不是底部对齐了,而是使用里面文本最后一行的基线进行对齐;
- 虽然inline-block盒子整体下移,但是行盒必须将其包裹进去,所以行盒的高度自然变大;
总结:
-
行盒一定会包裹住当前行中所有的内容;
-
对于平时遇到的千奇百怪的对齐方式,其原理就是基线(baseline)对齐;
-
vertical-align的默认值就是baseline;
-
不同行内级元素的baseline具体都在哪里?
- 文本的baseline是字母x的底部;
- inline-block默认的baseline是margin-bottom的底部(如果没有底边距,就是盒子的底部);
- 当inline-block里面含有文本时,baseline是最后一行文本字母x底部;
- 图片的baseline就是最底部;
2.3.vertical-align的属性值
-
baseline:默认值、基线对齐;
-
top:把行内级盒子的顶部与行盒的顶部对齐;
-
middle:行内级盒子的中心点与父盒中小写字母x的中心点的线对齐;
-
bottom:吧行内级盒子的底部与行盒的底部对齐;
3.实现行内级元素垂直居中
3.1.使用vertical-align: middle
-
将父元素的高度设置为300px,并且将子元素的line-height也设置为300px。
-
示例代码:
.box { background-color: skyblue; height: 300px; line-height: 300px; } img { vertical-align: middle; }
<div class="box"> <img src="../img/eqq.webp" width="200" alt=""> div元素的文本内容xxxxxx </div>
-
运行结果:可以发现图片在设置
vertical-align: middle;
后,并不是在父盒子中垂直居中的,很明显距离上边缘比距离下边缘的距离要大; -
为什么会出现上面不能垂直居中对齐的情况?
- 原因是大部分文字都会下沉,所以x的中心点并不是位于父元素高度中线上的,位置要稍微偏下,所以就导致了图片偏下对齐的现象;
-
如何解决上面的问题?
- 其原因还是因为图片在设置
vertical-align: middle;
后,必须要与文字中小写字母x的中心点对齐,所以将文字大小设置为0即可; - 没有了字体大小,文字自然就没有下沉了,并且该行盒中不能再出现文本,一旦有文本又会找到文本的x中心点进行对齐;
- 其原因还是因为图片在设置
-
3.2.使用relative+transform
使用vertical-align: middle设置垂直居中很明显是麻烦的,所以一般不用该属性设置元素垂直居中。一般使用relative+transform。
示例代码:
.box {
background-color: skyblue;
height: 300px;
font-size: 80px;
}
img {
position: relative;
top: 50%; /* 先下移父元素高度一半 */
transform: translateY(-50%); /* 再上移自己高度的一半 */
}
<div class="box">
<img src="../img/eqq.webp" width="200" alt="">
div元素的文本内容xxxxxx
</div>
运行结果:完美居中。