从一个内联元素布局引发对line-height的探讨

从一个内联元素布局引发对line-height的探讨

一、前言

line-height这个属性对于各位前端的小伙伴来说并不陌生。在之前写页面的时候碰到过一个该属性相关的问题,在查阅资料后决定跟大家分享一下我所理解的line-height。所讲述的内容不一定都是正确的,仅供参考。

二、line-height 定义

文档规范

line-height CSS 属性用于设置多行元素的空间量,如多行文本的间距。对于块级元素,它指定元素行盒(line boxes)的最小高度。对于非替代的 inline 元素,它用于计算行盒(line box)的高度。

属性值

属性描述
normal默认值。合理的行间距。根据浏览器和字体’font-family’不同而不同。
number设置数值,此数值会与当前的字体尺寸相乘来设置行间距。
length设置固定的行间距。
%基于当前字体尺寸的百分比间距。
inherit规定应该从父元素继承line-height属性的值

三、遇到的问题

相信大家都有写过这样一个布局 一个大标题,然后接着一个小标题,需要垂直居中

.title {
    font-size: 20px;
    line-height: 20px;
}

.sub-title {
    font-size: 14px;
    line-height: 20px;
}

<div>
    <span class="title">大标题</span>
    <span class="sub-title">小标题</span>
</div>

两个相邻的内联元素,字体一大一小。畅想的结果是两个 span 的高度都是20px, div的高度也是20px,多么完美,但结果往往不近人意….

《从一个内联元素布局引发对line-height的探讨》《从一个内联元素布局引发对line-height的探讨》《从一个内联元素布局引发对line-height的探讨》

div的高度为22.4 .title 的高度为26.4 .sub-title 的高度为19

那么问题来了:为什么没有一个元素的高度为20?

然而 规范 告诉我们,对于非替代的 inline 元素,它用于计算行盒(line box)的高度。

这里引出了两个概念:替代元素行盒(line-box)

替代元素

替代元素是指内容可以替换的元素,实际上就是content box可以被替换的元素。如存在src=””属性的<img> <audio> <video> <iframe>元素和可以输入文本的<input> <select> <textarea>元素等。
所有替换元素都是内联元素,默认display属性是inline或inline-block(除了input[type=”hidden”]默认display: none;)。替换元素有自己默认的样式、尺寸(根据浏览器不同而不同),而且其vertical-align属性默认是bottom(非替换元素默认值是baseline)。

行盒-line box

由内联元素组成的每一行都是一个行框盒子。行框盒子由一个个内联盒子组成,如果换行,那就是两个行框盒子。比如一个不换行的的p标签,就存在一个行框盒子。值得注意的是,如果给元素设置display:inline-block,则创建了一个独立的行框盒子。line-height是作用在行框盒子上的,并最终决定高度

《从一个内联元素布局引发对line-height的探讨》

一行有很多行内框,而行框的高度就是包含这一行行内框最高点和最低点的

然后继续探前面的问题

这里的span标签为inline元素,高度只会受到内容区域大小的影响

《从一个内联元素布局引发对line-height的探讨》font-size设置为30px时

为了查看实际高度,我们给 span 加上inline-block属性, 使其变成内行框

.title {
    display: inline-block;
    font-size: 28px;
    line-height: 20px;
}
.sub-title {
    display: inline-block;
    font-size: 14px;
    line-height: 20px;
}

《从一个内联元素布局引发对line-height的探讨》《从一个内联元素布局引发对line-height的探讨》《从一个内联元素布局引发对line-height的探讨》

可以看到 设置为inline-blockspan标签高度正常。但是为什么div高度还是 23 ?

由上图可以看到,.title.sub-title 是没有对齐的,由此可以思考是不是元素没有对齐而撑开了div的高度

为此给.sub-title加个 vertical-align 样式继续探讨

《从一个内联元素布局引发对line-height的探讨》vertical-align:top

可以看见div的元素高度小了1px, 可以得出父元素的高度被撑开了,但是还是多出了2px;

通过查阅资料,发现一个叫作[幽灵空白节点]的抽象概念(此概念并非权威,仅用于理解)

在HTML5文档声明下,块状元素内部的内联元素的行为表现,就好像块状元素内部还有一个(更有可能两个-前后)看不见摸不着没有宽度没有实体的空白节点,这个假想又似乎存在的空白节点,称之为“幽灵空白节点”。

既然这个节点看不见,决定用一个em标签来假装,

em {
    <!--为了查看元素的真实高度加此属性-->
    display: inline-block;
    font-style: normal;
}

<div>
    <em>X</em>
    <span class="title">大标题</span>
    <span class="sub-title">小标题</span>
</div>

《从一个内联元素布局引发对line-height的探讨》
可以看到该元素的真实高度为21px,撑开了父元素高度

然后因为子元素会继承父元素的line-height属性,将divline-height属性设置为一个较小的值

div {
    line-height: 5px;
}

《从一个内联元素布局引发对line-height的探讨》《从一个内联元素布局引发对line-height的探讨》

可以看到该节点的真实高度变为5px,div的高度也是正常的了;

四、解决办法

1、设置较小的line-height属性,通常都会设置成0。
div {
    line-height: 0;
}

em {
    display: inline-block; 
    font-style: normal;
}

.title {
    display: inline-block;
    line-height: 20px;
    font-size: 20px;
    background: red;
}

.sub-title {
    display: inline-block;
    line-height: 20px;
    font-size: 14px;
    vertical-align: top;
    background: yellow
}

《从一个内联元素布局引发对line-height的探讨》《从一个内联元素布局引发对line-height的探讨》

2、 因为line-height默认值为[数值],计算时跟font-size有关,又因为font-size是可以继承的。所以可以设置父元素font-size为 0。
div {
    font-size: 0;
}

em {
    display: inline-block; 
    font-style: normal;
}

.title {
    display: inline-block;
    line-height: 20px;
    font-size: 20px;
}

.sub-title {
    display: inline-block;
    line-height: 20px;
    font-size: 14px;
    vertical-align: top;
}

《从一个内联元素布局引发对line-height的探讨》《从一个内联元素布局引发对line-height的探讨》

可以看到[幽灵节点]的宽高都是0,div的高度也是正常的。

五、line-height的其他应用

1、多行文字的垂直居中

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

div {
    width: 300px;
    height: 150px;
    line-height: 150px;
    border: 1px dashed #ccc;
}

span {
    font-size: 12px;
    display: inline-block;
    line-height: 1;
}

<div>
    <span>多行文字的垂直居中多行文字的垂直居中多行文字的垂直居中多行文字的垂直居中</span>
</div>

《从一个内联元素布局引发对line-height的探讨》

2、图片的水平垂直居中


li {
    display: inline-block;
    width: 150px;
    height: 150px;
    line-height: 150px;
    text-align: center;
    border: 1px solid #ddd;
}

img {
    vertical-align: middle;
}

<ul>
    <li><img src="http://image.zhangxinxu.com/image/study/s/s128/mm1.jpg" /></li>
    <li><img src="http://image.zhangxinxu.com/image/study/s/s128/mm2.jpg" /></li>
    <li><img src="http://image.zhangxinxu.com/image/study/s/s128/mm3.jpg" /></li>
    <li><img src="http://image.zhangxinxu.com/image/study/s/s128/mm4.jpg" /></li>
    <li><img src="http://image.zhangxinxu.com/image/study/s/s128/mm5.jpg" /></li>
    <li><img src="http://image.zhangxinxu.com/image/study/s/s128/mm6.jpg" /></li>
</ul>

《从一个内联元素布局引发对line-height的探讨》

六、总结

以上就是本人对行内布局以及line-height的一些思考总结。

另外也可以使用flex布局一把梭,就没这么多事了~。

参考

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

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

    原文作者:一条咸鱼
    原文地址: https://segmentfault.com/a/1190000019889602
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞