CSS进阶(7)—— 内联元素的掌管者line-height和vertical-align(上)

在CSS世界中,块级元素通常负责结构,而内联元素则负责文字内容,而CSS设计的初衷就是面向图文混合排版,所以内联元素在CSS世界中有着很是重要的地位。因为本章内容较多,所以特分为上下两章,依旧能够根据兴趣按小标题获取你所须要的信息。 css

1.字母x与CSS世界的基线

要了解内联元素,就不得不提到字母x,正是有了x,内联元素才肯定了本身的基线(baseline),有了baseline以后,才有了line-height和vertical-align。所以在学习后面的内容以前,必需要了解一个概念: html

字母x的下边缘线就是内联元素的基线(baseline)! 小程序

既然x那么重要,所以CSS还给了它一个特殊的称呼叫x-height。顾名思义,x-height指的就是小写字母x的高度,那么这个x-height有没有用呢?答案是确定的,如vertical-align:middle的定义就是baseline往上1/2*x-height的位置,所以咱们看到的vertical-align:middle在font-size较大的时候会显得不是特别“垂直居中”,由于不是每一个字/字母的高度都和字母x相同,或者说,大部分都是不相同的。 微信小程序

因为vertical-align:middle须要基于x-height进行运算,那么CSS干脆给这个x-height一个名份,进一步衍生出了相对尺寸单位ex,1ex = x-height,所以这个单位会随着font属性的变化而变化,很是的不稳定,因此不太适合用来限定元素的尺寸,但某些状况下,ex的表现至关出色。如:咱们须要以下效果 浏览器

须要在文字后面加一个倒三角符号,这时候咱们要让文字和图标对齐可能会借助vertical-align:middle,让文字和图片都基于中线对齐,事实上因为文字自己是基于baseline排版的,这时候咱们只要让icon也基于baseline布局不就好了吗?那怎么让图标也基于基线布局呢?加个height:1ex不就完事了吗?以下所示: 微信

<style> .icon-arrow { display: inline-block; width: 20px; height: 1ex; background: url(/images/5/arrow.png) no-repeat center; } </style>
复制代码

2.内联元素中真实存在的“行框盒子”

因为以前没有好好解析内联盒子的基础知识,这里要补充一个关于内联盒子的基础内容,这对于学习后面的知识有必定的帮助。首先咱们须要明确两个非官方概念:什么是行框盒子以及行框盒子有什么用? markdown

什么是行框盒子?事实上我并不敢说这是官方给出的一个盒模型,做者也没有提到,但他彷佛真实存在于文字的每一行,并且是以行做为计算单位的,也就是每一行文字(无论他们是否是一个内联标签或匿名标签生成的),都在外面自动生成一个“行框盒子”。注意,这里仅表明我从书本上获取的观点,在后面的幽灵节点中会继续探讨官方是否给出了这个盒子。这么说可能不够直观,来看一个例子吧。 dom

这是我用span标签生成的一段话,他被浏览器自动分割成了两行,你能够理解每行文字的外包裹就是一个行框盒子。那么何时会生成行框盒子呢?这里我仅凭我的测试提出两种生成行框盒子的状况,第一种,就是非空内联元素,注意这个非空,很关键,做者彷佛老是忽略空元素的测试,我本人则对空元素比较在乎。第二种,就是inline-block元素内部自动生成,注意这里能够为空了,具体为何我也不知道,测试结果如此。 编辑器

第二个问题是,行框盒子有什么用?做者为何要提出行框盒子?由于这有助于咱们理解不少问题。首先来看下面这个测试代码以及他们生成的结果。 布局

<div style="background: yellow;">
    <span style="line-height: 40px">我行高40px</span>
    <span style="line-height: 60px">我行高60px</span>
    <span style="line-height: 30px">我行高30px</span>
    <span style="line-height: 90px">我行高90px</span>
</div>
复制代码

此时div的角色就像是“行框盒子”,由于div包裹了一行“行框盒子”(这里只有一行,两行状况又不一样了),这样作是为了让你更直观的看到最终这些内联元素最终生成的“行框盒子”,生成的高度是90px,也就是说,同一行!内联元素生成的行框盒子的高度,取决于line-height最高的那个元素。为了加深你对这个结果的印象,我再放一张图,仍是刚才那几个元素,此次我把父容器div的宽度压缩了。

最终结果跟上面测试的结论相同,第一行行高最高的是60px,第二行行高最高的是90px,两个“行框盒子”一相加,获得最终的150px,对于行框盒子的印象应该够深了吧!

3.内联元素的基石line-height

明白了行框盒子的概念以后,再来看line-height,就会容易的多了。做为内联元素的基石,line-height彻底掌控了内联盒子的高度,注意,我说的是彻底掌控,跟font-size没有半毛钱关系。

来思考一下下面这个问题,一个空的div的高度是0,在里面写上几个字,他的高度就被撑开了,那么这个高度是由何而来呢?首先能够肯定的是,是由新增的文字撑开的,在内联元素中,还有一类叫作“匿名内联元素”的近亲,他们外面没有包裹任何内联元素标签,但事实上他们的表现跟内联元素相同,只是不能单独定义本身的样式(固然能够从父级去继承一些过来,虽然继承的权重最低,但总比没有强)。好了,咱们知道这几个字是匿名内联元素了,所以高度是由这个内联元素的高度撑开的,那么这个内联元素的高度又取决于什么呢?下面咱们来作两个测试。

如结果所示,最终撑开高度的是line-height,而不是font-size。注意这里说的是非替换元素的纯内联元素,替换元素的概念能够看一下以前的文章。以前说过padding和border能够影响元素的高度,那么在内联元素中,是否也能够呢?答案是:不行!但有些状况下,视觉上仍是有一些误差。以下测试

<div style="background: yellow">
    <span style="line-height: 40px;padding: 20px;border: 1px solid">我有padding和border</span>
</div>
复制代码

因为markdown编辑器支持标签语言,所以咱们能够直接预览最终效果以下(小提示:你能够经过浏览器直接检查下面的元素看到CSS样式)

我有padding和border

所以对于纯内联元素,他的高度计算只跟line-height相关。 line-height === 纯内联元素height !!!

关于line-height的计算方式,做者“啰哩吧嗦”算了半天,我只总结成一个公式,line-height = font-size + 上半行距 + 下半行距 。对于CSS来说,font-size是已知的,所以他只须要计算半行距便可,至于它是怎么算的,就不必深究了。我只讲这个计算方式会致使一种状况,第一行文字和最后一行文字的上方和下方都只有半行距的距离,中间部分则是一个行距,如对样式有较高要求的能够考虑一下这个因素,用其余方式去弥补这里的高度差。

4.line-height在块级元素和内联替换元素中的疲软性

说完了line-height在内联元素中的表现,再来讲说line-height在块级元素和内联替换元素中承担什么样的角色吧。

首先咱们先来看简单的,line-height在块级元素中承担一个什么样的角色呢?答案是:屁用没有。固然,本章第三点的第一个例子就是在块级元素上直接写line-height属性,因此,仍是有那么丁点做用的,这个做用是line-height无处不在的继承属性决定的,正好块级元素内的匿名内联元素本身写不了样式,那就只能继承父级的line-height了,因此line-height最终仍是做用于内联元素,而不是块级元素。而后由内联元素生成的行框盒子相加,撑开了块级元素的高度。

既然line-height在块级元素中没用,那他在内联替换元素中又有哪些表现呢?这个等讲完vertical-align再总结。

5.深刻line-height的各种属性值

本节的标题让人以为摸不着头脑,line-height还有别的属性?还真没有,line-height就一个值,只是能够有不一样的类型。

line-height的默认值是normal,注意不是none,还支持数值,百分比值和具体长度值。

首先要了解一下这个看上去就不通常的normal,normal自己是一个跟font-family有关的变量,并且在不一样的浏览器中还有不一样的计算值,所以对于还原设计稿的这种要求,咱们不可能用默认的normal属性,同时因为line-height无处不在的继承属性,有时候不知不觉的你就把这个属性给改了,所以normal属性能够不讨论(咱们一切以实用性出发)。

实际上,咱们平时会设置line-height为具体的数值,如line-height:xx像素。这种作法彻底适用于如今高要求的精致网站,对于须要高保真还原设计稿的需求,彻底能够用用具体数值。固然也有一种状况你能够用数字或百分比,就是如今有不少网站有本身的设计标准,如微信小程序,ant-design之类的,他们会要求文章内部的行高是字号的1.3-1.4倍,文章标题的的行高是字号的多少多少倍,这种状况下你大能够根据设计要求,用比例计算方式来写行高。

这里我只推荐用长度值(1,2,3),而不是百分比值(100%,200%),你可能以为1不是等于100%嘛,其实我也这么认为,通常都是按照喜爱随便挑一个。事实上,这里面问题可大了去了。

长度值和百分比值的计算方式是彻底相同的。都是font-size*长度/百分比,向下取整,14*1.4 = 19.6 = 19px,注意不是四舍五入,是向下取整的。

那么长度和百分比哪里不一样呢?答案是:继承方式,就是line-height中无处不在的继承方式不一样。这里咱们来看一个实例:

<div class="box box-1">
    <h3>标题</h3>
    <p>内容</p>
</div>
<div class="box box-2">
    <h3>标题</h3>
    <p>内容</p>
</div>
<style> .box { font-size: 14px; } .box-1 { line-height: 1.5; } .box-2 { line-height: 150%; } </style>
复制代码

结果以下图所示:

最终表现得结果不同,问题就在于这个继承方式。

使用数值,line-height = 自己的font-size*数值

使用百分比,line-height = 继承来的line-height*数值

你会发现,一个是基于自身的font-size,一个是基于继承的line-height,彻底不一样,并且数值在大多数状况下的表现更优,也更符合实际状况。因此我我的推荐不要用line-height的百分比值,就当没听过。

6.内联元素line-height的“大值特性”

其实这个问题并不能单纯的理解为,内联元素line-height取最大那么简单,其中还包含以前所说的“行框盒子”的内容,以及行框盒子产生的幽灵节点。在探索大值特性以前,咱们得先了解一下,幽灵节点是什么。来看具体的实例:

<!DOCTYPE HTML>
<html>
<head>
<title></title>
</head>
<body>
<div style="background: yellow"><span style="display: inline-block;"></span></div>
</body>
</html>
复制代码

注意这段代码必需要有声明。这段代码的结果是:

这里的span标签的高度确实是0,那么到底是什么撑开了div的高度呢?就是上面提到的“幽灵空白节点”,你能够想象这个幽灵空白节点是一个没有宽度的空白节点,固然你不要去dom结构里找他,确定是找不到的。在了解幽灵空白节点以前,先得知道,何时会出现这个幽灵空白节点,根据个人测试,结果跟做者的描述相同。

产生行框盒子的前面自动生成幽灵空白节点。因为以前提到了,inline-block元素内部能够生成幽灵空白节点,所以这里确实存一个一个看不见的内联元素,且他有本身的line-height。

幽灵空白节点的line-height = font-size(默认12px) * normal,所以这个幽灵空白节点就有本身的高度了,有本身的高度就撑开了inline-block的高度,inline-block又撑开了父容器的高度,那么如今就一切都说得通了。

作好了一切的准备工做,最后作个总结和检测,理解了下面这个案例,你就真正理解了内联元素的line-height。

<div class="box box1">
    <span>span: line-height:20px</span>
</div>
<div class="box box2">
    <span>span: line-height:96px</span>
</div>
<style> .box { width: 280px; margin: 1em auto; outline: 1px solid #beceeb; background: #f0f3f9; } .box1 { line-height: 96px; } .box1 span { line-height: 20px; } .box2 { line-height: 20px; } .box2 span { line-height: 96px; } </style>
复制代码

因为markdown编辑器支持标签语言,所以咱们能够直接预览最终效果以下(小提示:你能够经过浏览器直接检查下面的元素看到CSS样式)

span: line-height:20px
span: line-height:96px

上面这两个box最终获得的高度是同样的,为何会这样呢?

刚才说到,每一个非空内联元素外面都会生出一层“行框盒子”,而每一个行框盒子左边就有一个幽灵空白节点,box1>span的line-height是20px,但他隔壁住了个幽灵空白节点,继承了父元素的line-height:96px,咱们已经知道行框盒子的高度是由最高的内联元素的行高决定的,所以box1的最终高度和box2的相同,都是96px。

本章内容过于多,vertical-align就放到下章讲,学了vertical-align以后咱们再来看如何结合二者实现多行元素的垂直居中展现,有兴趣的能够关注后续文章,点个关注。

不忘初心,方得始终

喜欢博主的童鞋能够扫描二维码加博主好友~ 也能够扫中间二维码入驻博主的粉丝群(708637831)~固然你也能够扫描二维码打赏并直接包养帅气的博主一枚。

相关文章