【译】关于vertical-align你应知道的一切
原文地址:Vertical-Align: All You Need To Know
通常我们需要垂直对齐并排的元素。
CSS提供了一些可实现的方法:有时我用浮动float来解决,有时用position: absolute来解决,有时甚至是“肮脏”地手动添加的margin或padding。
我真的不喜欢这些解决方案。float只对齐元素的顶部,且需要手动清除浮动。绝对定位的元素脱离文档流,所以他们不再影响周围的元素。而用修补性的margin或padding打破了最细微变化的东西。
但这里还有一个选择:vertical-align。我认为它值得我们更多地信任和使用。在技术上,使用vertical-align
的布局是一种hack,因为vertical-align
不是为这个目的(垂直对齐布局)发明的。它的存在,是用以对齐并排在一起的文本和元素。尽管如此,你还是可以在不同的上下文中,使用vertical-align
灵活而精确地对齐相邻元素。元素的大小不必是已知的。元素留在文档流中,所以周围的其他元素可以会根据这个元素受到的改变而做出反应。这使得vertical-align
成为一个有价值的选择。
vertical-align
的特殊性
但是,vertical-align
有时候很操蛋,它会令你抓狂,似乎它在使用中有一些神秘的规则。例如,你可能改变了元素的vertical-align
,但没有出现你想要的效果,但行中的其他元素却被改变了!这时我就很想跑到黑暗的角落里挠墙,撕扯我的头发。
不幸的是,大部分关于vertical-align
的文章资源都有点浅,特别是关于使用vertical-align
来布局的。他们经常误解vertical-align
,试图用它垂直对齐一个容器内的所有元素。他们给vertical-align
做基本的介绍,并解释如何在非常简单的情况下对齐元素,却不解释棘手的部分。
所以,我给自己设定了目标,希望一次说清垂直对齐的所有行为。我最终通过W3C的CSS规范和一些实例总结得出本文。
所以,让我们来理清vertical-align
的
游戏规则。
使用vertical-align
的条件
vertical-align
是用来对齐内联级元素的。
设置为以下display属性的元素,它们都被认为属于内联级元素。
inline,
inline-block or
inline-table (本文中不涉及此种情况)
inline内联元素基本上是包裹文本的标签。
inline-block内联块元素则如它们的名字所示:拥有内联特性的块元素。他们可以有width和height(可能是由自己的内容定义),以及padding、border和margin。
内联级元素彼此紧挨着放在一行中。一旦有更多的元素被放置到当前行中,一个新的行将会在它下面创建。所有这些行有所谓的“行框”,行框中包含所有的内容。不同大小的内容意味着不同高度的行框。在下面的插图中,行框的顶部和底部都是用红线表示的。
行框(line box)勾勒出我们正在设计的区域(下文会详细介绍“行框”的概念)。在行框中,元素的vertical-align
属性是负责垂直对齐的。那么,到底元素垂直对齐的参照物是什么?
参照物:父元素的基线和外边缘
vertical-align与元素
的基线息息相关。在某些情况下,元素的行框的顶部和底部边缘也变得很重要。让我们看看元素的基线和行框的外观:
·内联元素
此处,你可以看到三行并排的文本。行框的顶部和底部边缘用红线表示,字体的高度由绿线表示,基线由一条蓝线表示。在左边,有一个line-height设置为与字体font-size大小相同高度的文本,绿线和红线重叠在一条线上。在中间,line-height是字体的两倍大。在右边,line-height是字体大小的一半大。
内联元素(display:inline)的外边缘与其行高的顶部和底部边缘对齐,行高可以小于字体的高度。所以,行框就是上面的图中的红线。
内联元素的基线是字符放置的位置线(字母x底部所在的水平线),即图中的蓝线。粗略地说,基线是在字体1/2高度的下面的某个地方。感兴趣的可以看看W3C规范的详细定义。
·内联块元素
从左到右,你可以看到:在左边,是一个内联块元素包含了一个流内内容(一个“C”);在中间,一个内联块元素包含了一个流内内容(也是一个“c”),元素属性有overflow: hidden;在右边,一个内联块元素包含了一个流外内容(但内容区域有一个高度)。(译者注:流内的元素必须是普通文档流(normal flow)中的元素,流外的元素必须是浮动或绝对定位的元素以及根元素。)margin的边界是由红线表示,border是橘黄色的,padding是绿色的和内容区域是蓝色的。每个内联块元素的基线为一条蓝色线。
内联块元素的外边缘是其margin框的顶部和底部边缘,即图中的红线。
内联块元素的基线取决它包含的内容是否在文档流中:
- 在流内内容的情况下,内联块元素的基线是正常流中最后一个内容元素的基线(左边的例子)。对于这最后一个元素,它的基线是根据它自己的规则找到的。
- 在流内内容但内联块元素有overflow:hidden属性的情况下,基线是内联块元素margin框的底部边缘(例如在中间)。
- 在流外内容的情况下,基线是内联块元素margin框的底部边缘(例如在右边)。
·行框
你已经看到了上面的设定。这一次,我将在行框里的文本框顶部和底部画上绿线,以及基线(蓝色)。我还用灰色背景强调了该区域的文本元素。
该行框的顶部边缘对齐该行中最顶部元素的顶部边缘,底部边缘对齐该行中的最底部元素的底部边缘。如上图中红线所表示的盒子。
·行框的基线是可变的:
当使用vertical-align
时,基线放置在哪里可能是最令人疑惑的部分。它需要满足vertical-align
的值和行框的高度等所有条件。基线的位置犹如是方程中的一个自由参数。
行框的基线是看不见的,但你可以使它很容易看到。只要在文本行的开头添加一个字符,像我增加了一个“X”的字母。如果这个字符不以任何方式对齐,它将默认地坐在基线上。
围绕着行框的基线的部分(绿线),我们可以称其为文本框。文本框可以简单地被认为是行框内的内联元素,没有任何对齐。文本框的高度等于它的父元素的字体大小。因此,文本框只围住了行框内的无格式文本。由于这个文本框是绑在基线上的,当基线移动时它将移动。(注:此文本框在W3C规范中称为“strut(支柱)”)
好了,以上是最难的部分。现在,让我们迅速总结一下上面的重点:
- 有一个称为行框的区域。这是垂直对齐发生的区域。它有一个基线,一个文本框和一个顶部和底部边缘。
- 有一些称为内联级元素的元素。它们都是会对齐的对象。他们有一个基线和一个顶部和底部边缘。
vertical-align
的值
它的值分为以下几种对齐方式:
1)将元素的基线,参照父元素的基线对齐
baseline:元素的基线与父元素的基线对齐。
sub:元素的基线偏移到父元素的基线之下。
sup:元素的基线偏移到父元素的基线之上。
<percentage>:元素的基线相对于父元素的基线偏移了一个百分比(该百分比是对比元素自身的line-height计算得出)。
<length>:元素的基线相对于父元素的基线偏移了一个绝对长度。
2)将元素的中心点,参照父元素的基线对齐
middle:将元素的顶部和底部之间的中心点,对齐父元素的基线之上x-height的1/2之处(x-height为字母x的字符高度)。
3)将元素的外边缘,参照父元素的文本框对齐
text-top:将元素的顶部边缘,对齐到父元素的文本框的顶部边缘。
text-bottom:将元素的底部边缘,对齐到父元素的文本框的底部边缘。
4)将元素的外边缘,参照父元素行框的外边缘对齐
top:元素的顶部边缘对齐到父元素的顶部边缘。
bottom:元素的底部边缘对齐到父元素的底部边缘。
当然更正式的定义可以参考W3C规范
为什么vertical-align
会这样呈现?
我们现在可以仔细看看以下几种使用vertical-align有问题的情况:
1)垂直居中一个图标
我们经常遇到这样的需求,我有一个图标,我想将它垂直居中于一行文本。只给图标设置vertical-align: middle似乎并没有出现令人满意的效果。看一看这个例子:
- <!-- left mark-up -->
- <span class="icon middle"></span>
- Centered?
- <!-- right mark-up -->
- <span class="icon middle"></span>
- <span class="middle">Centered!</span>
- <style type="text/css">
- .icon { display: inline-block;
- /* size, color, etc. */ }
- .middle { vertical-align: middle; }
- </style>
我们画了辅助线方便理解(上文中我们知道每种颜色的线代表什么)
这样我们的答案更清晰了:在左边,文本并没有设置居中对齐,它位于基线上。原因是我们把图标设置了vertical-align: middle,但文本并没有设置垂直居中。所以,文本站在了基线上面,而图标的中点对齐到父元素的基线之上1/2 x-height的位置。
在右边,我们让图标和文字都设置了vertical-align: middle。文本的基线和图标的中点都对齐到父元素的基线之上1/2 x-height的位置。
2)行框基线的移动
这是一个常见的陷阱,当使用vertical-align:行框的基线位置会被其内部的所有元素影响。如果一个容器内的元素是按以下其中一种方式排列的,那么它的行框的基线必须移动。
一些例子:
如果一行中有一个高个的元素占据了整行的高度,那么vertical-align对它没有影响。它的顶部和底部没有空间让它移动。为了满足行框基线的对齐方式,行框的基线必须移动。矮个元素设置了vertical-align: baseline。在左边,高个元素设置了vertical-align: text-bottom。在右边,高个元素设置了vertical-align: text-top。你可以看到右边的基线跳起来了。
- <!-- left mark-up -->
- <span class="tall-box text-bottom"></span>
- <span class="short-box"></span>
- <!-- right mark-up -->
- <span class="tall-box text-top"></span>
- <span class="short-box"></span>
- <style type="text/css">
- .tall-box,
- .short-box { display: inline-block;
- /* size, color, etc. */ }
- .text-bottom { vertical-align: text-bottom; }
- .text-top { vertical-align: text-top; }
- </style>
当高个元素设置为其他的值时,也有同样的效果出现。
即使设置vertical-align
为 bottom
(左) 和 top
(右),基线也会移动。
- <!-- left mark-up -->
- <span class="tall-box bottom"></span>
- <span class="short-box"></span>
- <!-- right mark-up -->
- <span class="tall-box top"></span>
- <span class="short-box"></span>
- <style type="text/css">
- .tall-box,
- .short-box { display: inline-block;
- /* size, color, etc. */ }
- .bottom { vertical-align: bottom; }
- .top { vertical-align: top; }
- </style>
(左)将两个元素放在一行中并设置vertical-align
,它们会使得行框的基线移动到符合它俩的对齐规则之处,然后行框的高度也会随之调整。(中)添加第三个元素,不超越行框的边缘,既不影响行框的高度,也不影响基线的位置。(右)添加第三个元素,如果它超出了行框的边缘,行框的高度和基线调整。在这种情况下,我们的前两个元素也会跟着发生变化。
- <!-- left mark-up -->
- <span class="tall-box text-bottom"></span>
- <span class="tall-box text-top"></span>
- <!-- mark-up in the middle -->
- <span class="tall-box text-bottom"></span>
- <span class="tall-box text-top"></span>
- <span class="tall-box middle"></span>
- <!-- right mark-up -->
- <span class="tall-box text-bottom"></span>
- <span class="tall-box text-top"></span>
- <span class="tall-box text-100up"></span>
- <style type="text/css">
- .tall-box { display: inline-block;
- /* size, color, etc. */ }
- .middle { vertical-align: middle; }
- .text-top { vertical-align: text-top; }
- .text-bottom { vertical-align: text-bottom; }
- .text-100up { vertical-align: 100%; }
- </style>
3)内联级元素底部的小间隙
看一看以下情况。这很常见,如果你尝试垂直对齐列表中的元素。
- <ul>
- <li class="box"></li>
- <li class="box"></li>
- <li class="box"></li>
- </ul>
- <style type="text/css">
- .box { display: inline-block;
- /* size, color, etc. */ }
- </style>
正如你所看到的,列表项坐在基线上。下面的一点空间,是文本的基线以下预留的depth(在W3C规范中,一个字体的基线以上称为characteristic height,基线以下称为depth)。想要去掉这个depth空隙,有解决的办法吗?只要移动基线的位置就可以,例如通过设置列表项目vertical-align: middle
- <ul>
- <li class="box middle"></li>
- <li class="box middle"></li>
- <li class="box middle"></li>
- </ul>
- <style type="text/css">
- .box { display: inline-block;
- /* size, color, etc. */ }
- .middle { vertical-align: middle; }
- </style>
这种情况不会发生在含有文本内容的内联块元素中,因为内容已经将基线移动了。
4)内联级元素之间的空隙打破了布局
这主要是内联级元素本身的问题。但因为他们常使用垂直对齐,我们应该了解清楚这个问题。
在上面的示例中,我们可以看列表项之间的间隙。该间隙来自于在你的内联元素标签之间的空格white-space。在内联元素之间的所有空格都被折叠成一个空间。例如,如果我们想并排放置两个内联元素,并给他们width:50%,这时就没有足够的空间放置两个宽50%元的素和一个间隙。因此,它们会被分成两行破坏了布局(左)。为了消除间隙,我们需要想办法消除空格white-space,例如用HTML注释(右)。
- <!-- left mark-up -->
- <div class="half">50% wide</div>
- <div class="half">50% wide... and in next line</div>
- <!-- right mark-up -->
- <div class="half">50% wide</div><!--
- --><div class="half">50% wide</div>
- <style type="text/css">
- .half { display: inline-block;
- width: 50%; }
- </style>
写在最后的话
以上就是关于vertical-align的揭秘。一旦你知道了规则,它就不会很复杂了。如果垂直对齐没有表现出你要的效果,只需要问以下问题:
行框的基线以及顶部和底部边缘在哪里?
内联级元素的基线和顶部和底部边缘在哪里?
这将是解决问题的方案。
【译】关于vertical-align你应知道的一切的更多相关文章
- What is Vertical Align?
https://css-tricks.com/what-is-vertical-align/ ************************************************* CSS ...
- 浏览器兼容CSS代码:按钮文字垂直居中(input button text vertical align)
经过测试的浏览器:IE6, IE7, IE8, IE9, Firefox, Chrome, Safiri, Maxthon 按钮的HTML代码: <input id="btn_comm ...
- 【译】前端开发者都应知道的 jQuery 小技巧
回到顶部按钮 通过使用 jQuery 中的 animate 和 scrollTop 方法,你无需插件便可创建一个简单地回到顶部动画: // Back to top $('a.top').click(f ...
- 关于Vertical Align的理解
1:vertical-align 翻译就是垂直-对齐... 2:关于line-height的点 2.1:如果一个标签没有定义height属性,那么其最终表现的高度一定是由line-height起作用. ...
- 前端知识点回顾之重点篇——CSS中vertical align属性
来源:https://www.cnblogs.com/shuiyi/p/5597187.html 行框的概念 红色(line-height)为行框的顶部和底部,绿色(font-size)为字体的高度, ...
- 【转】10条你不可不知的css规则
10条你不可不知的css规则 Posted on 2006-12-20 10:33 雨中太阳 阅读(343) 评论(1) 编辑 收藏 :[译]10条你不可不知的css规则正文: Published D ...
- 一些你需要知道的Python代码技巧
被人工智能捧红的 Python 已是一种发展完善且非常多样化的语言,其中肯定有一些你尚未发现的功能.本文或许能够让你学到一些新技巧. Python 是世界上最流行.热门的编程语言之一,原因很多,比 ...
- HighCharts/Highstock使用小结,使用汉化及中文帮助文档
此文档是本人在开发过程图形报表时使用HighCharts所遇到的问题及解决方案 .最后附上有HighCharts中文帮助文档 HighCharts 版本:Highcharts-3.0.1 Hi ...
- 关于img底部空白
<img>元素底部为何有空白? 问题: 最近听网课遇到这样一个问题,先po出代码如下: <!--html--> <div class="top"> ...
随机推荐
- JS 四舍五入有小数点
后台传值 先整数化 var a = parseInt(10); var b = parseInt(3); var c = (a / b).toFixed(3)*100; 除之后进行小数点截取后三位再* ...
- 一种利用ADO连接池操作MySQL的解决方案(VC++)
VC++连接MySQL数据库 常用的方式有三种:ADO.mysql++,mysql API ; 本文只讲述ADO的连接方式. 为什么要使用连接池? 对于简单的数据库应用,完全可以先创建一个常连接(此连 ...
- C++判断回文
判断一个字符串是否为回文,如“goddog”. 代码: #include <iostream> #include <string> #include <stdio.h&g ...
- RabbitMQ理论部分
概念 queue 队列 exchange 交换机 bind 绑定 channel 通道 一个发送消息流程包含上述四个概念.消息经过channel传递给exc ...
- NDK 链接第三方静态库的方法
将NDK编译的第三方静态拷贝到JNI目录下,在Android.mk中添加如下代码 以openssl静态库(libcrypto-static.a)为例 第一种链接方法:LOCAL_LDFLAGS := ...
- Scrum立会报告+燃尽图(十月十一日总第二次):需求分析
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2191 Scrum立会master:张俊余 一.小组介绍 组长:付佳 组员 ...
- 第39次Scrum会议(12/5)【欢迎来怼】
一.小组信息 队名:欢迎来怼小组成员队长:田继平成员:李圆圆,葛美义,王伟东,姜珊,邵朔,阚博文 小组照片 二.开会信息 时间:2017/12/5 11:35~11:57,总计22min.地点:东北师 ...
- Daily Scrum (2015/10/28)
昨天DEV们完成了一部分代码风格的修整.今晚在与其他组进行交流时我们发现我们的代码是需要在服务器上运行的,而且服务器是需要配置的,而且据说需要花一些时间.所以在编写代码之前PM提出我们应该先把服务器搭 ...
- python接口测试之requests库(一)
一.requests库的安装 requests库作为第三方库,需要安装 cmd模式下,运行pip install requests 二.在学习如何发送请求之前,我们先来了解一下requests库,查看 ...
- Chapter 6 面向对象基础
面向对象=对象+类+继承+通信,如果一个软件系统采用这些概念来建立模型并给予实现,那么它就是面向对象的.面向对象的软件工程方法是面向对象方法在软件工程领域的全面运用涉及到从面向对象分析.面向对象设计. ...