深入浅出vertical-align和line-height


vertical-align是设置元素的垂直对齐方式,

   该属性定义行内元素的基线相对于该元素所在行的基线的垂直对齐。允许指定负长度值和百分比值。这会使元素降低而不是升高。在表格中,这个属性会设置单元格框中的单元格内容的对齐方式。

从网上查找关于vertical-align的资料

/* 关键值 */
vertical-align: baseline;    /*默认。元素放置在父元素的基线上*/
vertical-align: sub;         /*垂直对齐文本的下标*/
vertical-align: super;       /*垂直对齐文本的上标*/
vertical-align: text-top;    /*把元素的顶端与父元素字体的顶端对齐*/
vertical-align: text-bottom; /*把元素的底端与父元素字体的底端对齐。*/
vertical-align: middle;      /*把此元素放置在父元素的中部*/
vertical-align: top;         /*把元素的顶端与行中最高元素的顶端对齐*/
vertical-align: bottom;      /*把元素的顶端与行中最低的元素的顶端对齐*/

/* 长度值 */
vertical-align: 10em;
vertical-align: 4px;

/* 百分比值 */
vertical-align: 20%;

/* 全局值 */
vertical-align: inherit;    /*规定应该从父元素继承 vertical-align 属性的值*/
vertical-align: initial;    /*设置属性的初始值——浏览器的默认定义值*/ 

vertical-align: unset;
/*CSS 关键字 unset 是 关键字 initial 和 inherit的组合。 
如果有继承父级样式,则将该属性重新设置为继承的值,如果没有继承父级样式,则将该属性重新设置为初始值。
换句话说这个unset关键字会优先用inherit的样式,其次会应该用initial的样式。*/

上代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style type="text/css">
        div{
            background: blue;
        }   
    </style>
</head>
<body>
<div>
    <img src="images/02-key.png">
</div>
</body>
</html>

这个里面图片的显示正常,但是图片下面有一条空余地方

这个可以理解为vertical-align的布局方式,红色的是默认的布局,所以底下会有一部分空白

解决方法:

1、设置vertical-align的值,不使用baseline,使用bottom/middle/top都是可以。

2、我们知道vertical-align 的默认值是 baseline,它会和文字的基线对齐,我们直接去掉文字的高度也是可以了的,而文字的高度是由行高决定的,所以我们直接给div设置 line-height: 0; 也能解决问题。

3、说一下 line-height,它的默认值一般为1.2,当 line-height取值为数字或百分数时,它是基于当前字体尺寸来计算的,也就是font-size的大小,所以我们直接给div设置font-size: 0; 也是可以解决问题的。

4、我们最开始提到过,只有元素属于inline或是inline-block ,vertical-align属性才会起作用。所以我们直接让vertical-align属性失效也可以解决问题,那就直接给img 设置 display: block; 就可以了

总结

这次主要说了一些 vertical-align属性的基础的东西。 
但是还是有一些要注意的地方。

1、只有元素属于inline或是inline-block ,vertical-align属性才会起作用。 
2、vertical-align,取值是百分数值时,是相对于此标签继承的line-height值决定的。 
3、line-height,取值是百分数值时,是相对于当前的font-size值决定的。
 

4、文中提到的图片下方会有空隙,必须是HTML5文档声明才会有的,其他的文档声明没有空白,就是必须要有<!DOCTYPE html>这句才可以。

引用网址(https://blog.csdn.net/fe_dev/article/details/75948659)

下面来瞅瞅张鑫阳的博客关于vertical-align和line-height的关系

vertical-align,取值是百分数值时,是相对于此标签继承的line-height值决定的

{
  line-height: 30px;
  vertical-align: -10%;
}
实际上,等同于:

{
  line-height: 30px;
  vertical-align: -3px;    /* = 30px * -10% */  
}

大家一定要意识到这么一点:对于内联元素,vertical-align与line-height虽然看不见,但实际上「到处都是」!

在HTML5文档声明下,块状元素内部的内联元素的行为表现,就好像块状元素内部还有一个(更有可能两个-前后)看不见摸不着没有宽度没有实体的空白节点,这个假想又似乎存在的空白节点,我称之为“幽灵空白节点”,其实上面已经说了解决方案,我们可以让里面的文字做block 然后加上背景,看到背景是有高度的,这样就更好理解了

衍生产品  垂直居中

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

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

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style type="text/css">
        div{
            background: blue;
            line-height: 300px;
        }
        img
        {
            vertical-align: middle;
        }
    </style>
</head>
<body>
<div>
    <img src="images/02-key.png">
</div>
</body>
</html>

但是这个不是绝对居中了,我还用量了一下,图像整体下移了一点点


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

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

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

我特意把字符x使用大字号演示了下:
中线位置并不是字符内容的绝对居中位置

换句更简单的话说就是:middle中线位置(字符x的中心)并不是字符内容的绝对居中位置。两个位置的偏差就是图片近似居中的偏差。

嘛嘛,单纯的文字还是太苍白了,截个图示意下吧:
近似垂直居中演示

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

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

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

div { line-height: 240px; font-size: 0; }
img { vertical-align: middle; }

结果是:

处女座的你,是不是看过去舒服多啦!?

这种通过line-height定高,元素vertical-align:middle垂直居中的方法不仅适用于现代浏览器,连IE7浏览器也是支持的:

IE7浏览器也支持

不过和其他浏览器再使用上还是有些需要注意的地方,就是,HTML不能这样:

<div><img src="mm1.jpg"></div>

而是需要在图片标签结束处留下空格后者换行:

<div><img src="mm1.jpg"><!-- 这里要折行或空格 -->
</div>

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

.justify-fix { display: inline-block; width: 128px; }
<div style="text-align: justify;">
    <img src="img/mm1.jpg" width="128">
    <img src="img/mm1.jpg" width="128">
    <img src="img/mm1.jpg" width="128">
    <img src="img/mm1.jpg" width="128">
    <i class="justify-fix"></i>
    <i class="justify-fix"></i>
    <i class="justify-fix"></i>
</div>

为了节约空间,我就使用小图示意:

        

同样的,在白色背景下,似乎看上去效果还不赖,但是,如果给div容器加个背景色~~

        

会惊讶的发现,下面多了很大一块间隙(如下截图):
大大的空白间隙

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

        

结果会发现,上面巨大的空隙是由占位i元素上面和下面的间隙共同组成的。

下面问题来了:上面的间隙是如何产生的?下面的间隙是如何产生的?如果去除这些间隙呢?

很多时候,复杂问题是由简单问题组合而成的,实际上,这里的间隙现象的始作俑者和上面的简单现象一样,都是vertical-alignline-height搞基带来的不好的影响。

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

div { line-height: 0; }

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

        

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

⑤ inline-block和baseline
CSS2的可视化格式模型文档中有一么一段话:

The baseline of an ‘inline-block’ is the baseline of its last line box in the normal flow, unless it has either no in-flow line boxes or if its ‘overflow’ property has a computed value other than ‘visible’, in which case the baseline is the bottom margin edge.

英文看得眼睛大,于是我中文直译了下:

‘inline-block’的基线是正常流中最后一个line box的基线, 除非,这个line box里面既没有line boxes或者本身’overflow’属性的计算值而不是’visible’, 这种情况下基线是margin底边缘。

这段文档中出现了很多专有名词line boxline boxes等,这些是内联盒子模型中的概念,是CSS进阶必备知识。我在“浮动深入理解(一)”一文的中间穿插介绍了该模型。//zxx: 我现在后悔了,内联盒子模型当初应该直接独立成一篇文章,这样其他文章可以很干净地引用,所谓文章的模块化书写

如果大家没有足够精力去学习之,可以先看下面这张图:

由于上面的译文是直译的,理解起来还是有些拗口,我使用通俗的话描述就是:一个inline-block元素,如果里面没有inline内联元素,或者overflow不是visible,则该元素的基线就是其margin底边缘,否则,其基线就是元素里面最后一行内联元素的基线。

纳尼,还是没反应过来?

那我们看下面这个例子,应该就知道什么意思了。

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

.dib-baseline {
  display: inline-block; width: 150px; height: 150px;
  border: 1px solid #cad5eb; background-color: #f0f3f9;
}
<span class="dib-baseline"></span>
<span class="dib-baseline">x-baseline</span>

结果,科科:

 x-baseline

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

 

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

 x-baseline

知道框框2为何又下沉了一点吗?

因为字符实际占据的高度是由行高决定的,当行高变成0的时候,字符占据的高度也是0,此时,高度的起始位置就变成了字符content area的垂直中心位置,于是,文字就一半落在看看2的外面了。
犹抱琵琶半遮面

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

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

        x-baseline

大家是不是就可以明白原因所在啦!

额~居然还有小伙伴皱眉头,那我再用文字解释下:
现在行高line-height0, 则最后的x-baseline的垂直中线就和上面一列的图片对齐,而基线呢,就在中线下面差不多半个x的高度地方,而这个高度落差就是最后图片和容器的间隙高度值,因为前面的<i class="justify-fix">是个空元素,基线是自身的底部,哈哈,造业啊!
基线对齐造成的间隙

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

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

        xx-baseline

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

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

div { font-size: 0; }
        

使用其他vertical-align对齐方式,就是让两端对齐的列表元素vertical-align:top/bottom/...之类。

div { line-height: 0; }
.justify-fix { display: inline-block; width: 128px; vertical-align: top; }

最后的效果是:

        

恩恩,各种方法都完美解决了垂直间隙的问题,来,各个大大的赞!

https://www.zhangxinxu.com/wordpress/2015/08/css-deep-understand-vertical-align-and-line-height/  本文供大家参考,由于有些复杂现象对我这种小新不是很理解,仅此做个记录,以后慢慢啃






  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值