平时遇到vertical-align
时候会有各类抓狂的时刻,调来调去虽然也弄好了可是内心面一直很虚,由于一直没有透彻理解过这个属性,搜索时候发现了一篇很棒的文章,算是半翻译吧,把这个属性好好总结一下。css
提及vertical-align
你们都知道他是用在对相邻的文字和内联元素上,好比常见的将一个图标和相邻的文字居中对齐。可是当你不了解他的机制时候常常会让你抓狂,所以咱们一次来攻克这个规则的玄机。前端
vertical-align
用来对齐内联级元素,也就是display
值为inline
、inline-block
或者inline-table
(这个一般不考虑了)的元素。inline
元素也就是包含文字的最基本的标签如span
等inline-block
,顾名思义就是表现为行内的块级元素,能够设置宽度、高度和间距边框等。布局
内联级元素以行的形式相邻排列在一块儿,一旦有更多的内联级元素超过当前行能容纳的长度,就会在其下面产生一个新行。也就是咱们常说的line box
(行框),行框包含其行内全部内容。不一样尺寸的内容意味着行框也有不一样的高度。下图就用红线标注了三个行框的top和bottom。字体
行框勾勒出了这些内容占据的区域,其中vertical-align
就负责对行框中的各个元素进行对齐。问题来了,这些元素都是相对于哪些线对齐呢?spa
垂直对齐最关键的参考线就是元素的基线baselines,在某些状况下元素的包含盒的顶端线tops和底端线bottoms也变得很重要。下面就分别看看各类类型元素的baselines、tops和bottoms。.net
如图所示,有三行不一样标线的文字。红线表明line-height
的顶端和底端;绿线表明文字字体的高度,这里须要注意的是其实文字内容区域实际占据的高度并不严格等于字体高度而是由font-size
和font-family
共同决定的,特殊状况就是宋体字体下,实际内容区域高度就等于字体高度。可是这点差距通常状况下也无伤大雅,咱们就假定用字体高度来表示内容区域高度便可;蓝线表明基线baseline,能够理解为字母x的底边缘线,就是比字体高度中心位置低大约1/2的x高度。翻译
左图的行高设置为同字体高度相同,所以红线和绿线重合了。中图行高设置为两倍字体高度,行间距分为上下两部分等分了一个字体高度,即相对于绿线分别向上向下半个字体高度。右图行高设置为字体高度的一半,即相对于绿线分别向下向上四分之一字体高度。3d
从左到右分别是包含流内in-flow
内容的inline-block
元素、包含流内in-flow
内容的inline-block
元素同时设置了overflow:hidden
和一个不含流内内容可是有高度的inline-block
元素。红线表面了inline-block
元素的外边距margin
边界,图中盒模型黄色是border
,浅绿是padding
,浅蓝是content
;蓝线表示inline-block
元素的baseline。code
能够得出,inline-block
元素外部边缘线就是margin-box
的顶端和底端边界,也就是图中的红线。基线的规则判断比较复杂,能够简单记为:若不包含内容或者overflow
属性不为visible
之外的值,则其基线就是底部边缘线,也就是margin-box
的底端边界。blog
上图用几根线很清晰的表现出了行框的结构。绿线表明的是行框中text box
,这里称做字框的的顶端和底端线。同时用灰色背景高亮了文字的区域。
行框顶线和其中最高的元素对齐,行框底线和其中最低元素对齐。
行框的基线在草案中并未做出精确的定义:
CSS 2.1 does not define the position of the line box's baseline. — the W3C Specs
这多是最让人困惑的地方了,他的意思就是行框的基线就位于能同时知足全部其余vertical-align
和最小化行框高度的位置。这样说仍是很抽象,可是有个可让其具象的方法,也就是像图中那样在行框的最前面加上一个x
字符,这个字符就是对齐了基线baseline
。
围绕着这个基线的绿线也就是字框,能够理解为行框中一个没有任何对齐方式的内联元素,其高度等于字体的高度(如前面说的同样,不考虑字体的因素了)。草案中把咱们这里用字符x
模拟的看不见字框称做strut
,张鑫旭大神在其博客中称为幽灵空白节点。
总结下,行框就是vertial-align
发挥做用的区域,他包括一个基线、字框、顶线和底线。每一个内联元素也有其本身的基线,顶线和底线。
用上图表示各类对齐方式的形式。
baseline
: 内联元素的基线正好位于行框基线上。sub
:内联元素的基线位置低于行框的基线。super
:内联元素的基线位置高于行框的基线。<percentage>
:内联元素的基线相对于行框基线移动相应于行高百分比的数值。<length>
:内联元素的基线相对于行框基线移动某个绝对数值。middle
:居中对齐能够着重讲一下,他的意思就是内联元素的顶线和底线的中线与行框的基线向上偏移二分之一个x-height
,能够近似理解为字符x
中间交叉点。text-top
: 内联元素顶线与行框的字框顶线对齐。text-bottom
: 内联元素底线与行框的字框底线对齐。top
: 内联元素顶线与行框顶线对齐。bottom
: 内联元素底线与行框底线对齐。图片和文字对齐是前端开发者最多见的场景了,虽然如今不少都用字体图标或者用一些组件不少状况下不须要考虑对齐了,可是当你本身写的时候仍是务必要搞清楚这个基本原理。下面看这个例子。
一个图标相邻有一行文字,若是让文字和图标居中对齐,大部分人会对图标使用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>
这是为什么呢?
画出辅助线来看一下:
很明显了,左图的文字是默认基线对齐的,以x
的中线位置分割带有ascender
的文字会偏上一些。
而右图对文字用span
标签包裹而后对整个文字内容区域也使用middle
,这样其基线位置相对于行框基线会稍微下沉一些,这样就与图标居中对齐了。
前面提过,行框基线的位置会被行内全部元素所影响,而大多对齐方式都是和行框基线有关的,所以假如行框基线发生了变化,整个布局就会出现变化。
举例说明:
text-botttom
对齐,右边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>
咱们再来思考下常常遇到的一个场景:
<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>
内联元素下面总会有一个间隙,就是由于幽灵空白节点在做怪,内联块的基线如今就是底边缘线和字框的基线对齐后,间隙就是字框基线下的descender
,为避免这种问题其实就是改变行框基线的位置便可,好比top
、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>
之后再遇见对齐的问题,只须要搞清楚两个问题就能够了: