写点什么

关于 vertical-align 你应该知道的一切

2021 年 3 月 18 日

关于 vertical-align 你应该知道的一切

前言


vertical-align,写过 CSS 的朋友们肯定都知道这个属性的作用,顾名思义,垂直对齐,主要目的用于将相邻的文本与元素对齐。MDN 中对它的定义如下:


一种简单的 CSS 属性,用来指定行内元素(inline)或表格单元格(table-cell)元素的垂直对齐方式。

我们对于它的直观定义是与 text-align:center 相类似,一个控制水平方向对齐方式,一个控制垂直方向对齐方式。但是在很多情况下,我们发现设置属性之后并没生效。接下来让我们步步深入学习,共同揭开 vertical-align 的神秘 “面纱” 吧。


首先我们先讲一下,要实现垂直居中,我们为什么选择 vertical-align 这样一个不起眼的 CSS 属性。

  • float:只能对齐它们的顶部,而且可能导致布局塌陷,需要手动清除

  • position:absolute:会使元素脱离文档流,以致于它们不能影响周围的元素

  • 手动添加内外边距的方法:需要父元素高度固定

  • transform:translateY:属于 CSS3 新特性,对 IE8、IE9 有一些兼容性的问题


使用 vertical-align 你能在不同场景下去进行灵活细微的元素对齐工作,并且它有很好的的兼容性,详情如下图所示:


前置准备


在认识 vertical-align 属性之前,首先要了解几个基本的概念。


  • 基线:书写英语字母时,字母 X 底部所在的位置,可以了解下《字母’x’在 CSS 世界中的角色和故事》(https://www.zhangxinxu.com/wordpress/2015/06/about-letter-x-of-css/)

  • 行高(line-height):两行文字基线之间的距离

  • 内联盒子,更深入的理解可以参考《CSS 盒子模型》(https://segmentfault.com/a/1190000014692461)


  • content area:围绕文字看不见的 Box,其大小与 font-size 有关

  • inline boxes:不会成块显示,而是并排显示在一行的 boxes ,如 span、 a、 em 等标签以及匿名 inline boxes(即不含把标签的裸露的文字)

  • line boxes:由一个一个的 inline boxes 组成,一行即为一个 line box

  • containing box:外层盒子模型,包含了其他的 boxes

  • 起作用的前提:元素为 inline 水平元素或  table-cell  元素,包括  span、 img、 input、 button、 td  以及通过 display 改变了显示水平为 inline 水平或者 table-cell 的元素。这也意味着,默认情况下,div 、p  等元素设置 vertical-align 无效


值得注意的是:例如 float 和 position: absolute,一旦设置了这两个属性之一,元素的 display 值被忽略,强制当成 block 方式处理,因此,vertical-align 也就失去了作用。


vertical-align 属性值


除 Inherit 继承 之外,vertical-align 的属性值可以归为以下 4 类


  • 线类,如  baseline、top、middle、bottom;

    我们可以把每一个行框盒子的后面想象有一个看不见的节点 x(该节点继承了 line-height ),因为默认对齐方式为基线对齐,所以 .text 就是和这个字母 x 的下边缘对齐。

    在实际应用中我们经常会遇到下图这种情况,你可能会容易的解决这种无法对齐的问题,但是你知道是什么原因导致他们这个样子吗?

  • baseline 为 vertical-align 的默认值,其意思是指基线对齐


<ul class="box">  <li>文本</li>  <li></li></ul><style>  .li {    font-size: 20px;    width: 160px;    height: 160px;    display: inline-block;    border: 1px solid #ccc;  }</style>
复制代码


这里就涉及到了 inline-block 基线的定义,inline-block  的基线是正常流中最后一个(行盒子) line box 的基线,但是,如果这个 line box 里面没有 inline boxes 或者其 overflow 属性值不是 visible,那么其基线就是 margin bottom 的边缘。


如上图所示,第一个元素基线是子元素”文本“的基线,而第二个是盒子的底边缘,默认基线对齐,两个元素基线位置不一致,所有会产生上图现象,知道了原因,我们只需设置元素的 vertical-align 属性为  top/bottom/middle  就可以轻松对齐了。


  • top 与 bottom

    对于内联元素,指的是元素的顶部(底部)和当前行框盒子的顶部(底部)对齐;即与 line-box 的顶部(底部)对齐。

    对于 table-cell 元素,指的是元素的顶 padding 边缘和表格行的顶部对齐。

    基本效果如下图:


  • middle 这个属性值用得比较多。

    对于内联元素指的是元素的垂直中心点与行框盒子基线往上 1/2x-height 处对齐,简单点说就是字母 X 的中心位置对齐;对于 table-cell 元素,指的是单元格填充盒子相对于外面的表格行居中对齐。

  • 文本类


text-top,指的是盒子的顶部和父级内容区域的顶部对齐,即与 content-area 顶部对齐。text-bottom,指的是盒子的底部和父级内容区域的底部对齐,即与 content-area 底部部对齐。


例子如下:


<div class="box">  <span class="f12">12px</span>  <span class="f16">16px</span>  <span class="f20">20px</span>  <img src="./panda.jpg"/></div><style>  .box {    font-size: 16px;  }  img {    vertical-align: text-top;    width: 100px;    height: 100px;  }  .f12 {    font-size: 12px;  }  .f16 {    font-size: 16px;  }  .f20 {    font-size: 20px;  }</style>
复制代码

content-area 即围绕文字看不见的 box,其大小与 font-size 有关,可以看成是鼠标选中文字后高亮的背景色区域,上面的例子中,由于父元素字体设置的是 16px ,所以图片的 vertical-align 设置 text-top 的时候,就可以看成是跟子元素为 16px 元素的内容区域顶部对齐,它与 line-height 无关


  • 上标下标类


如 sub、super;这两个属性用的比较少。


  • super 属性效果相当于 html 标签 <sup></sup> 的效果

  • sub 属性效果 相当于 html 标签 <sub></sub> 的效果

  • 数值百分比类,如 10px、1em、5%


之所以数值和百分比写在一起主要是他们有以下共性:都带数字、都支持负值、行为表现一致


  • vertical-align 支持数值的特性,兼容性也非常好,但大部分开发人员却不知道 vertical-align 支持数值。对于数值,我们要知道的是:1、正值表示由基线往上偏移,负值表示由基线往下偏移。2、百分比则是基于 line-height 来计算的


需要注意的是:除了 top 与 bottom 是使元素相对于整行垂直对齐外,其他属性值都是相对于父元素。所以,在开发时,我们只需要关注当前元素和父级,两元素前后并没有直接影响


vertical-align 与 line-height 之间的基友关系


说到 vertical-align 就要讲到它与 line-height 之间密切的关系,从上面我们都知道百分比类型是根据 line-height  来计算的。但事实是 对于内联元素,vertical-align 与 line-height 虽然看不见,但实际上「到处都是」。其实我们很多时候发现设置 vertical-align 属性无效,这很有可能就是 line-height 的原因了,下面我们来看两个典型的例子。


  • Demo 1:任意一个块级元素,里面若有图片,则块级元素高度基本上都要比图片的高度高

<div class="box">  <img  src="./panda.jpg" /></div><style>  .box {    width: 300px;    border: 1px solid #ddd;  }  img {    width: 100px;    height: 100px;  }</style>
复制代码


产生这种现象的原因:空白节点、line-height 和  vertical-align 属性;图片后放置空白节点 X,会发现图片的基线是元素底部,与“空白节点”的基线对齐,那解决这种问题有以下几个方法:


(1)将图片设置为 display:block (利用 vertical-align 的生效前提)

(2)将 vertical-align 设置为 top,bottom,或者 middle 等值(利用属性值的表现行为)

(3)将 line-height 设置为 0 (利用 line-height 为 0 时,基线上移)

(4)将 font-size 设置为 0  (如果 line-height 的值为相对值)

(5)将 img 设置浮动或者绝对定位 (如果布局允许的话)


  • Demo 2:近似垂直居中

<div class="box">  <span class="son"></span>  x</div><style>  .box {    width: 300px;    height: 150px;    line-height: 150px;    font-size: 20px;    border: 1px solid #ddd;    position: relative;  }  //  绘制父元素的垂直中心线  .box::after  {    content: "";    position: absolute;    display: block;    width: 100%;    height: 1px;    background-color: red;    top: 0;    bottom: 0;    margin: auto;    left: 0;  }  .son  {    display: inline-block;    width: 100px;    height: 100px;    vertical-align: middle;    background-color: purple;    position: relative;  }  .son::after {    content: "";    position: absolute;    display: block;    width: 100%;    height: 1px;    background-color: #317ffd;    top: 0;    bottom: 0;    margin: auto;    left: 0;  }</style>
复制代码



如图所示(为了更明显我使用了色块来标识),当子元素(图片)设置了 vertical-align:middle,并不是绝对居中,而只能说是近似居中。子元素的垂直中心线与父级元素基线的位置往上二分之一 X 高度(X 的中心) 所在线对齐,通俗一点讲,就是图中红线表示父元素的垂直中心线,蓝线表示子元素的垂直中心线,可以明显的看到 蓝线 与 X 的中心保持一致,但较红线偏低。如果绝对居中的话,两条线应该完全重合。


为什么会产生这种现象呢?主要原因在于文字具有下沉特性,从而导致蓝线无法绝对与红线对齐。当文字大小足够小时,我们可以忽略。从而近似的实现居中效果。但是文字越大,影响就越明显。


那对于这样的问题我们要怎么解决呢?以下提供几种思路:


1、设置后面的 “空白节点 X ” 的垂直对齐方式也是  vertical-align:middle,然而,既然称之为 “空白节点” 就表示不会受非继承特性的属性影响,所以,根本没法设置  vertical-align:middle,除非你自己创建一个显示的内联元素或者伪元素。

2、“空白节点” 可以受具有继承特性的 CSS 属性影响,于是,我们可以通过其他东西来做调整,让字符的中线和字符内容中心线在一起,或者说在一个位置上就可以了。设置父元素 font-size:0 , 因此此时 content area 高度是 0,各种乱七八糟的线都在高度为 0 的这条线上,绝对中心线和中线重合。效果如下:


这种通过 line-height 定高,元素 vertical-align:middle 垂直居中的方法不仅适用于现代浏览器,连 IE 浏览器也是支持的,但是这里只有在 IE7 中需要注意的是图片后面需要换行或者空格,经验证这个不是由于标签闭合引起的,可能只是一个 IE7 的 bug 吧。比较幸运的是,现在很多网站的兼容都是基于 IE9,所以可以忽略这个问题啦。


<div>  <img src="xxx.jpg">  <!-- 这里要折行或空格 --></div>
复制代码


总结


本文讲解了 vertical-align 的基本属性以及各种表现,同时对一些实际应用中 vertical-align 无效现象做了简单的分析阐述,并为解决此类问题提供了思路。



头图:Unsplash

作者:润瑞

原文:https://mp.weixin.qq.com/s/vk6qCqTf3B4PSIKQGQoMEA

原文:关于 vertical-align 你应该知道的一切

来源:政采云前端团队 - 微信公众号 [ID:Zoo-Team]

转载:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


2021 年 3 月 18 日 14:16928

评论 1 条评论

发布
用户头像
` .li { ` 应该没有那个点……
2021 年 04 月 06 日 11:42
回复
没有更多了
发现更多内容

快来!我从源码中学习到了一招Dubbo的骚操作!

why技术

源码 面试 dubbo 动态代理

支付公司如何赚钱?支付网关如何设计?

诸葛小猿

微信 支付宝 聚合支付 第三方支付 支付网关

week6

Geek_2e7dd7

架构师训练营 - 第六周 - 学习总结

韩挺

redis系列之——一致性hash算法

诸葛小猿

redis 一致性hash redis集群

【计算机网络】你需要知道的链路层知识

烫烫烫个喵啊

计算机网络 链路层 交换机

练习 6-1

闷骚程序员

Elasticsearch从入门到放弃:再聊搜索

Jackey

elasticsearch

疫情年逆风翻盘

Kerwin

程序员

Markdown工具Typora结合gitee码云图床自动上传云端图片

Flychen

Typora markdown gitee

SpringBoot代码生成器

Kerwin

Java 开源

程序员的时间管理

Kerwin

程序员

数据加工

阡陌r

日记一则

progyoung

java 后端博客系统文章系统——No4

猿灯塔

架构师训练营 - 第六周 - 作业

韩挺

nginx在重定向时端口出错的问题

烫烫烫个喵啊

nginx

图解Windows Server 2008 R2安装

JackWangGeek

windows-server

没内鬼,来点干货!volatile和synchronized

Kerwin

Java volatile synchronized

有朋自远方来 不亦说乎,请多关照哈

InfoQ_353bc6b96230

ServerlessDays China:无服务器的未来

Michael Yuan

云计算 Serverless 容器 虚拟机 webassembly

第六周作业

赵龙

ARTS - Week 5

Khirye

ARTS 打卡计划

因为 Django ORM update,我今天差点「从删库到跑路」

AlwaysBeta

数据库 django 编程 程序员

设计模式总篇:从为什么需要原则到实际落地(附知识图谱)

Kerwin

Java 设计模式

6 个珍藏已久 IDEA 小技巧,这一波全部分享给你!

楼下小黑哥

Java IDEA

week6 学习总结

Geek_2e7dd7

Mybatis执行流程浅析(附深度文章推荐&面试题集锦)

Kerwin

Java mybatis

没内鬼,来点干货!SQL优化和诊断

Kerwin

MySQL

Hello!GitHub 好用好玩值得收藏的开源项目集合~

Kerwin

开源

SharePoint 部署架构

JackWangGeek

架构 BI SharePoint

4月17日 HarmonyOS 开发者日·上海站

4月17日 HarmonyOS 开发者日·上海站

关于 vertical-align 你应该知道的一切-InfoQ