重学CSS(8)—— 内联元素的掌管者line-height和vertical-align(下)

1.vertical-align的五类属性

抛开inherit这类全局属性不谈,个人把vertical-align分成五类,作者将第一类和第二类总结成线类。

(1)跟x字母打交道的线类:baseline/middle

(2)基于行框盒子边缘的线类:top/bottom

(3)跟父级基线相关的文本类:text-top/text-bottom

(4)常用于公式的上标下标类:super/sub

(5)具体数值类:2px/2em/20%等

通常情况下,内联元素默认都是沿着字母x的下边缘对齐的,也就是vertical-align的默认值是baseline。但对于图片等替换元素,往往使用元素本身的下边缘作为基线,这一点在过去的简陋布局中显得非常好用,二十年前的网页你甚至都不需要会写CSS就可以让读者正常浏览网站内容,但是如今这些"好用的"特点会给我们的CSS布局带来很多不便之处。下面我们通过实战来一一测试这些属性的表现以及利用这些表现实现一些布局方式。

2.跟x字母打交道的vertical-align:baseline/middle

前面说到了,vertical-align的默认值是baseline,也就是字母x的下边缘,为了更好的看清x的下边缘在哪里,我们需要借助最常用的替换元素——图片。图片的下边缘通常为元素本身,我们来看字母x和图片都基于baseline对齐会有什么表现吧。

<div>
    <span>字母x</span>
    <img src="../小和尚.jpg">
</div>

最终效果如下图所示:

可以看到,表现结果跟理论相同,x下边缘与图片下边缘完全持平,那么为什么中文"字母"的下边缘没有和x下边缘对齐呢?没为什么,大部分中文和部分字母的下边缘就是低于baseline的,别问,问就是不知道。同时,你会发现,图片的下边缘会有4px的空隙,导致最终容器的高度多了4px,很多人第一反应就是甩锅中文,因为中文看起来比字母x大一些,低一些,然而就算你把span标签删除了依旧会多出这4个像素。那么多出的4px是哪里来的呢?这里还要请出vertical-align的好朋友line-height一起来解释这个问题。

首先line-height的默认值是normal,这个值是根据font-size和font-family计算得到的,得到的值一般会大于字母x的高度,由于高度多出来的部分由line-height计算后在文字上下均匀分布,因此你可以理解为多出来的4px是baseline到文字下边缘的距离。因此,要解决这多出来的4px其实很简单,修改图片的vertical-align即可,如,让他基于字母x的中点对齐。当然这只是理论上,你可以根据实际需求解决这个问题。

修改后的结果如下图所示:

说完了baseline,再来聊聊middle。我不敢说很多人,我自己之前在理解vertical-align:middle的时候,认为CSS在父容器中间找了一条中线,然后让所有的图文基于这条中线均匀分布。事实上,这样理解的坏处是,你会认为vertical-align需要加在父容器上,事实上vertical-align只在两类元素内生效,就是内联元素和table-cell元素。换句话说,vertical-align属性只能作用在display计算值为inline、inline-block、inline-table或table-cell元素上。需要注意的是,浮动,绝对定位等让元素块化的操作也会让vertical-align失效。了解了vertical-align的生效范围后,我们来看看如何让内联元素在垂直方向上居中吧。依旧是刚才的例子,我们想让图片在固定高度的容器里用vertical-align:middle属性垂直居中。

<div>
    <span>字母x</span>
    <img src="../小和尚.jpg">
</div>
<style>
div{
    height: 400px;
    background: rgba(0,0,0,0.1);
    text-align: center;
}
img{
    vertical-align: middle;
}
</style>

代码的结果如下图所示:

结果似乎不尽如人意,图片并没有垂直居中,为什么会这样呢?其实答案已经很明显了,vertical-align:middle属性已经生效了,在由span和img生成行框盒子中,图片已经基于字母x的中点垂直居中了,那么,怎么让图片在父级容器中居中呢?这里又要请到好朋友line-height的帮助了,只要让line-height的值等于父容器的高度即可,当然,为了简化代码,我们可以去掉height的申明,让元素保持流的特性,自动撑开容器高度。

这里图片已经完美垂直居中了,但对于文字,可能会有一定的偏差,因为字母x的中点和许多文字的实际中点会有所偏差,这个居中属性在文字偏大的时候就显得明显偏下或偏上了。因此在实际使用的过程中,不要盲目迷信vertical-align的文字居中能力。

3.基于行框盒子上下边缘对齐的top/bottom属性

vertical-align:top;表示当前内联元素的顶部在垂直上边缘对齐。在table-cell中表示元素底padding边缘和表格行的顶部对齐。这里我们只讨论内联元素。下面我们通过一个实例来探究一下这句话的涵义。代码如下:

<div>
    <span style="font-size: 14px">14px</span>
    <span style="font-size: 16px">16px</span>
    <span style="font-size: 18px">18px</span>
    <span style="font-size: 20px">字母x</span>
    <img src="../小和尚.jpg">
</div>
<style>
div{
    height: 400px;
    background: rgba(0,0,0,0.1);
}
span{
    vertical-align: bottom;
}
img{
    vertical-align: bottom;
}
</style>

产生的结果如下,从下图可以很明显的看出来,内联元素的上下边缘对齐的边缘是行框盒子的边缘,不要混淆理解成了父级容器的边缘。

4.从了解到弃用:vertical-align的文本属性类

当你深入理解了这个属性之后,你就会发现这个属性很难有什么软用。(这句话写在开头是为了让你少钻点牛角尖)

作者在给vertical-align属性分类的时候,将baseline/middle/top/bottom分为一类,其实都是基于行框盒子进行划分的,只是个人由其表现差异性又细分成了两类。而文本属性类text-top/text-bottom在垂直方向布局的时候则和行框盒子没有多大关系了。

vertical-align:text-top 表示盒子的顶部和父级应有内容区域的顶部对齐。vertical-align:text-bottom 表示盒子的底部和父级应有内容区域的底部对齐。

内容区域指的是在默认状态下用鼠标选中文本时的背景蓝色区域,这里说的父级应有的内容区域指的是根据父级的font-size和font-family计算得到的内容区域。

有兴趣的可以参考原文例子。这里就不深究这个看不到前途的属性了。

5.简单了解vertical-align的上标下标类属性

HTML里有两个标签,sup上标,和sub下标。

sup对应的默认vertical-align:super。

sub对应的默认vertical-align:sub

这两个属性无需多做说明,只需看一下他的具体效果即可。

<div>
    H<sub>2</sub>O<sup>[1]</sup>
</div>
<div>[1]:H<sub>2</sub>O是水的分子式</div>

由于markdown编辑器支持标签语言,因此我们可以直接预览最终效果如下(小提示:你可以通过浏览器直接检查下面的元素看到CSS样式)

H2O[1]

[1]:H2O是水的分子式

6.vertical-align被忽略的实用数值属性

作者在原文中嘲讽"很多即使工作很多年的前端开发人员,可能不知道vertical-align的属性值支持数值,更不知道支持负值",这着实让他感到意外,没错我就是那个可能过一万年都不会去知道这个值的程序员。在说明这个属性的好处之前,先来看一个利用vertical-align“垂直居中”元素的例子。


<div style="line-height: 150px;">
    <span style="vertical-align: middle;font-size: 50px">我想垂直居中,却有些偏下</span>
    <img src="../小和尚.jpg" style="vertical-align: middle;width: 50px;height: 50px">
</div>

从结果上来看,由于中文相对于x的middle表现的总体偏下,在文字偏大的时候这个问题就表现得尤为明显了,然而图片在这个时候表现得又比文字要好,如果是文字+图标(icon)的格式,往往会使得文字看起总是偏下,图标总有一些偏上,现在你知道锅应该甩给文字了。这个时候就要请我们的vertical-align数值属性来精确的调整文字的位置了。在不知道数值怎么设置的情况下,不如先来看看vertical-align:0,会发生什么,同时为了便于观察,把图片的垂直居中也改为基于基线对齐。

<div style="line-height:150px;position: relative;">
    <span style="vertical-align: 0;font-size: 50px">我的vertical-align是0,x</span>
    <img src="../小和尚.jpg" style="vertical-align: baseline;width: 50px;height: 50px">
</div>

这时候可以看到,vertical-align:0的表现和vertical-align:baseline的表现一模一样!因此,vertical-align:数值,是基于baseline对齐的,为了图片和文字最终能居中,我们当然先要保证图片先居中(因为图片替换属性的特性的总能保持完全居中),再去调整文字的数值。最终调整结果如下

<div style="line-height:150px;position: relative;">
    <span style="vertical-align: -10px;font-size: 50px">借助x辅助调整数值,x</span>
    <img src="../小和尚.jpg" style="vertical-align: middle;width: 50px;height: 50px">
</div>

除了数值,vertical-align还支持基于line-height的百分比计算数值,个人觉得没什么用就不说明了。

7.baseline在inline-block元素中的诡异表现

又到了CSS灵异事件的部分了,我觉得这些个灵异事件甚至可以单独抽出一个章节来讲。vertical-align属性的默认值baseline在文本之类的内联元素那里是指x的下边缘,对于替换元素则是替换元素的下边缘,看完这章应该对这两句话有很深的印象了,但是,如果是inline-block元素,规则就要复杂一些了。

一个inline-block元素,如果里面没有内联元素(包括匿名内联元素),且overflow不是visible,则该元素的基线是其margin盒子的底边缘,否则,其基线就是其元素里面最后一行内联元素的基线。

因为inline-block元素在实际开发中非常重要,搞清楚inline-block的诡异CSS是十分有必要的,理论看起太干,不如来个实际例子看看到底是怎么回事。

<div>
    <span style="margin-bottom: 10px"></span>
    <span>我有自己的内x</span>
</div>
<style>
div{
    background: rgba(0,0,0,0.1);
}
span{
    background: rgba(0,0,0,0.5);
    display: inline-block;
    width: 100px;
    height: 100px;
}
</style>

可以看到第一个inline-block元素由于没有内容导致其baseline位置发生改变,变成了margin盒子的下边缘,而另一个inline-block元素的基线是其最后一个行框盒子的基线,在本例中,就是第二行的x字母,由于inline元素的布局是基于baseline的,因此就出现了如图所示的"错位"。

除了空inline-block元素和非空inline-block元素会发生错位,行数不同的inline-block元素也会发生错位。如下图所示:

虽然这两种情况都会发生错位,但需要注意他们发生错位的机制完全不同!

想要解决这个错位问题其实很简单,只要你明白错位问题的产生的根本原因是inline-block元素和baseline有过节即可,所以inline-block元素的vertical-align可以用不基于基线的属性,由于数值属性也是基于基线的因此也会发生错位问题,所以需要具体问题具体分析,我只给出一种最简单的解决方案。如下所示

最后,给大家推荐一个前端学习进阶内推交流群685910553前端资料分享),不管你在地球哪个方位,
不管你参加工作几年都欢迎你的入驻!(群内会定期免费提供一些群主收藏的免费学习书籍资料以及整理好的面试题和答案文档!)

如果您对这个文章有任何异议,那么请在文章评论处写上你的评论。

如果您觉得这个文章有意思,那么请分享并转发,或者也可以关注一下表示您对我们文章的认可与鼓励。

愿大家都能在编程这条路,越走越远。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容