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

1. vertical-align

众所周知,vertical-align支持很多属性值,足足可以组成一个足球队了:

这里写图片描述

其中,有个属性值暴露了vertical-align和line-height之间的基友关系,大家猜猜看是哪个属性值?哇塞,好厉害!居然被大家一眼就看出来了,没错,就是“百分比值”

vertical-align的百分比值不是相对于字体大小或者其他什么属性计算的,而是相对于line-height计算的。举个简单的例子,如下CSS代码:

这里写图片描述

实际上,等同于:

这里写图片描述

2. 和line-height背地里无处不在的基友关系

2.1 基本现象

要八卦vertical-align和line-height之间的关系,我们不妨从一个极其简单的现象入手。假设,我们有一个
标签,然后,里面有一张图片,我们的HTML代码就是这样子:

这里写图片描述

然后,表现就是一张图片呈现,类似下面这样:

这里写图片描述

恩,看上去很正常,一切都是理所当然。然而,如果我们给这个
元素增加一个背景色,例如淡蓝色:

这里写图片描述

这里写图片描述

会发现图片下面有一段空白空间:

这里写图片描述

实际上,这段空白间隙就是vertical-align和line-height携手搞的鬼!首先,大家一定要意识到这么一点:对于内联元素(inline),vertical-align与line-height虽然看不见,但实际上「到处都是」!

2.2 幽灵空白节点

还是上面的图片下边缘留空隙的例子,实际上,这种行为表现,就跟图片前面或者后面有一个宽度为0的空格元素表现是一致的。但是,空格是透明的,为了便于大家理解,我就直接使用很明显的匿名inline box, 也就是字符代替。如下,大家会发现,图片下面的间隙,依旧是那个间隙

这里写图片描述

下面要解释这个间隙就好解释了。下面,我们让新增的文本inline-block化,然后弄个白色背景,显示其占据的高度

这里写图片描述

1. vertical-align默认值是baseline, 也就是基线对齐。而基线是什么,基线就是字母X的下边缘(参见“字母’x’在CSS世界中的角色和故事”一文)。所以,妹子图片的下边缘就和后面zxx中的字母x下边缘对齐(见下图)。而字符zxx本身是有高度的,对吧,于是,图片下面就留空了

这里写图片描述

2. 而zxx文字的高度是由行高决定的

因此,简单的图片下面留白行为表现,本质上,就是vertical-align和line-height背地里搞基造成的。

既然我们找到了这个问题的所在,那么我们现在搞定这对基友中的随便一个不就可以了吗?

★ 让vertical-align失效

图片默认是inline水平的,而vertical-align对块状的元素无感。因此,我们只要让图片display水平为block就可以了,我们可以直接设置display或者浮动、绝对定位等(如果布局允许)。例如:

这里写图片描述

★ 使用其他vertical-align值

告别baseline, 取用其他属性值,比方说bottom/middle/top都是可以的

★ 直接修改line-height值

下面的空隙高度,实际上是文字计算后的行高值和字母x下边缘的距离。因此,只要行高足够小,实际文字占据的高度的底部就会在x的上面,下面没有了高度区域支撑,自然,图片就会有容器底边贴合在一起了。比方说,我们设置行高5像素

这里写图片描述

★ line-height为相对单位,font-size间接控制

如果line-height是相对单位,例如line-height:1.6或者line-height:160%之类,也可以使用font-size间接控制,比方说来个狠的,font-size设为大鸡蛋0, 本质上还是改变line-height值

这里写图片描述

3. 基本现象衍生:垂直居中

由于「幽灵空白节点」的存在,因此,我们可以进一步衍生,实现其他更实用的效果,比方说任意尺寸的图片(或者内联块状化inline-block的多行文字)的垂直居中效果。就是借助本文的两位男主角,vertical-align和line-height

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

你想啊,图片(块状元素内部的内联元素)后面(前面)有个类似空格字符的节点,然后就能响应line-height形成高度来达到文字的居中,此时,图片再来个vertical-align:middle,当当当当,就可以和这个被行高撑高的「幽灵空白节点」(近似)垂直对齐了

这里写图片描述

这里写图片描述

不过上面的效果并不是完全的垂直居中,只是近似(稍微仔细看可以看出来)。为什么只是近似呢?那是因为「幽灵空白节点」高度行高撑开,其垂直中心是字符content area的中心,而对于字符x而言,都是比绝对中心位置要下沉的(不同字体下沉幅度不一样),换句更易懂的描述就是x的中心位置都是在字符内容区域高度中心点的下方,而这上下的偏差就是这里图片上下间距的偏差

这里写图片描述

因此,要想完全垂直居中,最先想到的方法就是让后面的“幽灵字符”也是vertical-align:middle,然而,呵呵,既然称之为“幽灵”就表示不会受非继承特性的属性影响,所以,根本没法设置vertical-align:middle,除非你自己创建一个显示的内联元素

我们就没有办法了吗?当然不是,“幽灵字符”可以受具有继承特性的CSS属性影响,于是,我们可以通过其他东西来做调整,让字符的中线和字符内容中心线在一起,或者说在一个位置上就可以了。有人可能要疑问了,这能行吗?啊,是可以的

怎么搞?很简单,font-size:0, 因此此时content area高度是0,各种乱七八糟的线都在高度为0的这条线上,绝对中心线和中线重合。自然全垂直居中:

这里写图片描述

4. 复杂现象

多年前曾分享过“text-align:justify下列表的两端对齐布局”的技术,其中,为了让任意个数的列表最后一行也是对齐排列,在列表最后会辅助列表等宽的空标签元素来占位,类似下面红色高亮HTML代码

这里写图片描述

这里写图片描述

同样的,在白色背景下,似乎看上去效果还不赖,但是,如果给div容器加个背景色~~,会惊讶的发现,下面多了很大一块间隙

这里写图片描述

为了便于大家看其究竟,我把占位i元素outline高亮下,于是,效果如下:

这里写图片描述

下面问题来了:上面的间隙是如何产生的?下面的间隙是如何产生的?如果去除这些间隙呢?很多时候,复杂问题是由简单问题组合而成的,实际上,这里的间隙现象的始作俑者和上面的简单现象一样,都是vertical-align和line-height搞基带来的不好的影响。

按照之前问题解决方法,我们可以直接来个line-height:0解决垂直间隙问题

这里写图片描述

这里写图片描述

结果图片和图片之间的间隙是没有了,但是,图片和最后的占位元素之间依然有个几像素的间距,啊啊啊啊,这究竟是什么鬼?

简单现象的背后往往有大的学问,接下来是本文的高潮了,究其原因,要说到inline-block元素和基线baseline之间的一些纠缠的关系

5. inline-block和baseline

这里写图片描述

一个inline-block元素,如果里面没有inline内联元素,或者overflow不是visible,则该元素的基线就是其margin底边缘,否则,其基线就是元素里面最后一行内联元素的基线。

两个同尺寸的inline-block水平元素,唯一区别就是一个空的,一个里面有字符,代码如下

这里写图片描述

这里写图片描述

会发现,明明尺寸、display水平都是一样的,结果呢,两个却不在一个水平线上对齐,为什么呢?哈哈,上面的规范已经说明了一切。第一个框框里面没有内联元素,因此,基线就是容器的margin下边缘,也就是下边框下面的位置;而第二个框框里面有字符,纯正的内联元素,因此,第二个框框就是这些字符的基线,也就是字母x的下边缘了。于是,我们就看到了框框1下边缘和框框2里面字符x底边对齐的好戏。框框2有个小彩蛋,点击可以toggle其innerHTML,会发现,如果框框2里面没文字,就和框框1举案齐眉了。

这里写图片描述

下面我们要做一件很有必要的事情,用来帮助我们理解上面复杂例子在line-height值为0后的表现,什么事情呢?哈,同境界模拟,我们也设置框框2的line-height值为0,于是,就会是下面这样的表现:

这里写图片描述

知道框框2为何又下沉了一点吗?因为字符实际占据的高度是由行高决定的,当行高变成0的时候,字符占据的高度也是0,此时,字符高度上的起始位置就不再是原来行高的值所对应的位置a,而是变成了字符content area的垂直中心位置b,于是,文字就一半落在框框2的外面了

这里写图片描述

由于文字字符上移了,自然基线位置(字母x的底边缘)也往上移动了,于是,两个框框的垂直落差就更大了

OK,明白了上面的简单例子,也就能明白上面的复杂例子。紧接着,如果我们在最后一个占位的<i>元素后面新增同样的x-baseline字符,则

这里写图片描述

因为line-height等于0,所以字符在垂直方向上的高度是从内容区域的垂直中心线处开始计算,再加上图片的默认基线是底部,所以x-baseline的垂直中线和上面一列的图片底端对齐。虽然字符占据的高度随着行高的改变而改变,但是其基线仍然在最下面,所以其和i标签基线的对齐导致图片和下边缘的间隙

现在行高line-height是0, 则最后的x-baseline的垂直中线就和上面一列的图片对齐,而基线呢,就在中线下面差不多半个x的高度地方,而这个高度落差就是最后图片和容器的间隙高度值,因为前面的<i class="justify-fix">是个空元素,基线是自身的底部,哈哈,造业啊!

OK,一旦知道了现象的本质,我们就能轻松对症下药了!要么改造占位<i>元素的基线、要么改造“幽灵空白节点”的基线位置、要么使用其他vertical-align对齐方式~

首先,来个最有意思的方法,对吧,改造占位<i>元素的基线。这个很简单,对吧,只要在空的<i>元素里面随便放几个字符就可以了,例如,里面有个x

这里写图片描述

会发现,间隙没有了! 为什么呢?哈哈,因为<i>元素的基线和“幽灵空白节点”的基线位置现在一致了,没有了错位,自然就不会有间隙啦!

改造“幽灵空白节点”的基线位置,哈哈,使用font-size,字体足够小时,基线和中线会重合在一起,什么时候字体足够小呢,就是0. 于是,CSS代码(line-height如果是相对值,line-height:0也可以省掉):

这里写图片描述

总结:

1.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/406925.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决html2canvas截取页面部分div黑屏问题

当截取页面的部分div时出现上述问题 原因&#xff1a; 当转存图片格式为jpeg时截取整个页面(document.body)没有问题&#xff0c;但截取部分div会有黑屏 将jpeg改为png时图片可正常显示。

遍历磁盘类型

// 遍历磁盘类型: GetDriveType()#include <iostream> #include <windows.h>using namespace std;int main() {char rootPath[10] {0}, driveType[21] {0};UINT nType;for(char a A; a < Z; a){sprintf(rootPath, "%c:\\", a);nType GetDriveType…

修改eclipse默认编码方式

原因&#xff1a;若是gbk或gb232编码方式的项目&#xff0c;在转换成utf-8编码方式时&#xff0c;致使代码中存在的中文乱码&#xff0c;为此应该统一编码方式。 设置js文件的默认编码格式为UTF-8 在Windows->Preference页面中&#xff0c;选择General->Content Types …

FTP的主动模式与被动模式

FTP协议有两种工作方式&#xff1a;PORT方式和PASV方式&#xff0c;即为主动式和被动式。PORT&#xff08;主动&#xff09;方式的连接过程是&#xff1a;客户端向服务器的FTP端口&#xff08;默认是21&#xff09;发送连接请求&#xff0c;服务器接受连接&#xff0c;建立一条…

CSS 中的内联元素、块级元素以及display的各个属性的特点

1. display:block 1.1 block元素会独占一行&#xff0c;多个block元素会各自新起一行。默认情况下&#xff0c;block元素宽度自动填满其父元素宽度 1.2 block元素可以设置width,height属性。块级元素即使设置了宽度,仍然是独占一行 1.3 block元素可以设置margin和padding属性…

window.print() 前端实现网页打印详解

前言 print作为浏览已经比较成熟的技术可以经常被用来打印页面的部分内容&#xff0c;我们可以在MDN上查看到相关的简单介绍。 一、print()方法 print() 方法用于打印当前窗口的内容。调用 print() 方法会产生一个打印预览弹框&#xff0c;让用户可以设置打印请求。最简单的打…

判断一个数的二进制形式是否只有一个1,是的话就输出

// 判断一个数的二进制形式是否只有一个1&#xff0c;是的话就输出#include "stdafx.h" #include <stdlib.h>int main(int argc, char* argv[]) {unsigned int n 0;char str[100] {0};do{if(n && (n & (n-1)) 0){printf("%d, %X\n", …

android- Auto Monitor Logcat

启动模拟器的时候弹出窗体&#xff1a; 它实在询问你是否显示logcat视图以便显示此工作空间中的程序信息。 因为如何程序错误&#xff0c;可以从logcat中看到错误的原因&#xff0c;建议选择yes。 单击确定&#xff0c;你会发现多了一个Logcat窗体。转载于:https://www.cnblogs…

C#2.0泛型

泛型是什么 一种类型占位符&#xff0c;或称之为类型参数。我们知道在一个方法中&#xff0c;一个变量的值可以作为参数&#xff0c;但其实这个变量的类型本身也可以作为参数。泛型允许我们在调用的时候再指定这个类型参数是什么。在.net中&#xff0c;泛型能够给我们带来的两…

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

1. 一些字面意思 “行高”是指两行文字间基线之间的距离。基线是在英文字母中用到的一个概念&#xff0c;我们刚学英语的时使用的那个英语本子每行有四条线&#xff0c;其中底部第二条线就是基线&#xff0c;是a,c,z,x等字母的底边线。下图的红色线即为基线 2. line-height与l…

echarts使用大总结

echarts图表x轴数据太多显示不全的问题 问题如图&#xff0c;x轴数据条数过多可能导致x轴显示不全&#xff0c;开始我使用下面方法 xAxis: {type: "category",min: min,max: max,data:time,axisLabel: {interval:num,//interval为x轴两相邻数据之间所包含数据条数&a…

宏定义中##和#的作用

From: http://blog.chinaunix.net/space.php?uid16135252&doblog&id2752917 内核中有很多的宏定义&#xff0c;在宏定义define中经常看到两个字符串##和#&#xff0c;这里把它的用法做一下说明&#xff1a; ##是一个连接符号&#xff0c;用于把参数连在一起 …

我对CSS vertical-align的一些理解与认识(一)

1. vertical-align一大堆乱七八糟的属性 有句俗语叫做“见多不怪”&#xff0c;我估摸着这些top,bottom属性大家都见过&#xff0c;没啥看头&#xff0c;没啥说头。老实讲&#xff0c;我看到这些养臭虫的属性也头疼&#xff0c;所以&#xff0c;忘了他们&#xff0c;我们说点有…

@Repository , @Service , @Controller 和 @Component

用Spring MVC时Controller注解的类将变成一个Spring MVC的控制器. 不用Spring MVC的情况下, 这四个注解没有区别. 根据注解的语义, 注解在类上面可以提高代码的可读性.Repository代表仓库. 一般注解在DAO实现类上, 别人看代码时, 就知道这个类是一个跟数据存储有关的类. Servic…

vue的token刷新处理

前言 以token处理登录的web系统&#xff0c;一般会有两个token&#xff1a;access-token和refresh-token。 node.js中&#xff0c;一般用jsonwebtoken这个模块。 access-token&#xff0c;是用户输入登录的账号密码&#xff0c;后台去db验证然后颁发的&#xff0c;它一般记录…

我对CSS vertical-align的一些理解与认识(二)

1. 我对不同浏览器解析vertical-align属性的理解 在上集中&#xff0c;在最后提供的实例中&#xff0c;vertical-align:middle实际上应该是与后面的文字是独立的&#xff0c;毫无关联&#xff0c;就是说vertical-align无论是什么&#xff0c;都不影响文字在box中的位置&#x…