开始学习前端以来,在CSS相关知识当中困扰我最多的就是Vertical-Align这个属性。在stackoverflow上查找相关问题的时候看到了这篇文章,因而将它翻译出来,做为本身的一次学习笔记吧。css
在遇到将元素在垂直方向上对齐的需求时,CSS提供了多种方法,有时候我用float
解决,有时候我使用position:absolute
解决,还有时候采用的方法是手动调整margin
和padding
。
其实我并不喜欢这些解决方法,float
会让元素的顶端对齐并且须要手动清楚浮动。绝对定位让元素脱离了正常流,这样这些元素就不会再影响到周围的元素。在元素的padding
和margin
固定的状况下,一点小的改变也颇有可能对布局形成影响。
接下来登场的就是本文的主角了:Vertical-align
。一般来讲使用这个属性进行布局是一种hack行为,由于它原本并非被用于这个目的。它用在文本和与文本相邻元素的垂直方向上的对齐问题。然而,你也可使用Vertical-align
在不一样的上下文中对元素进行灵活的,细粒度的排布。元素的尺寸无需知晓,元素任然处于正常流当中,所以元素的变化会影响到周围的元素,这使得Vertical-align
是很是有价值的排布方案的选择。html
Vertical-align
有时候会变的面目狰狞。它彷佛有一些谜同样的规则。举例来讲,有时候你改变了Vertical-align
的值,可是该元素垂直方向上没有发生改变反而别的元素改变了位置。
一些资料在谈到Vertical-align
这个问题的时候深刻程度不够,特别是当人们想使用这个属性布局的时候。这些资料更多的将精力集中在了一个误区上,就是尝试将元素内的一切都垂直对齐。他们给出了一下在简单状况下的例子来解释Vertical-align
这个属性而忽略了一些复杂奇怪的方面。前端
Vertical-align
被用于垂直对齐inline
元素,也就是display
值为inline
和inline-block
的元素。inline-table
的元素不在本文的讨论范围内。inline
元素基本上值得就是文本inline-block
元素就像它的名字同样,同时具有inline
元素和block
元素的特色,这样的元素有padding,margin,border,width,height
。其中高度有多是由元素的内容决定的。inline
元素一个挨着一个的摆放在行内,当行内元素太多的状况下,一个新行会被建立出来,这些行也叫作line--box
。它将行内的全部内容都包裹了起来。根据行内内容的不一样,line-box
的尺寸也会不一样,在接下来的图里面,红线表明了line-box
的上下边界
在这些line-box
内,Vertical-align
属性负责对齐一些独立的元素。那么,这些元素是要和谁对齐呢?ide
对于垂直对齐这个知识点来讲最重要的就是涉及元素的baseline。有时候元素的盒模型的上下边界也会变的很重要。下面上图
如图所示有三行文字。行高的上下边界是红线。文字的上下边界是绿色的线,蓝色的线就是baseline了,左边文字的高度与行高是一致的,所以绿线和红线重合了,中间的行高是文字大小的两倍,而在右边,行高是文字大小的二分之一。
行内元素的外边缘在行高的上边缘和下边缘这个范围内对齐,若是行高小于文字的高度也无所谓。关于baseline的定义仍是直接给出标准的连接布局
从左到右的三幅图片都是inline-block
元素,不一样的是,左面包含着没有脱离正常流的内容c,中间的除了没有脱离正常流的内容之外还加了overflow:hidden
,右面的没有内容可是内容区还有高度。红线表明了margin-box
的边界。黄色表明的是border,绿色的是padding,蓝色的是content,蓝色的线表明的仍是baseline。inline-block
元素的外边缘就是margin-box
的边缘。inline-block
元素的baseline的位置要看该元素有没有处于正常流以内的内容。
(1)在有处于正常流内容的状况下,inline-block
元素的baseline就是最后一个做为内容存在的元素的baseline,这个元素的baseline的肯定就要根据他自身来肯定了。
(2)在overflow属性不为visible的状况下,baseline就是margin-box的下边界了。
(3)第三种状况下baseline仍是margin-box的下边界。学习
关于line-box的图上面已经给过了,此次我将文字部分高亮显示。line-box的上边界与最高元素的上边界对齐,下边界与最低元素的下边界对齐。
W3C标准中并无定义line-box的baseline的位置。这一点很让人困惑,baseline的位置须要知足vertical-align属性的值以及让line-box的高度最小等条件,是一个很灵活的参数。
line-box的baseline是不可见的,可是能够很轻松的将它可视化出来,在行的开头添加一个字母,好比'x',这个字母的下边界默认就是baseline的位置。围绕着baseline在line-box中造成了文字盒。文字盒能够被认为是没有和任何元素对齐的line-box中的inline元素,它的告诉与它的父元素的font-size的值相同。所以,文字盒仅仅包含非格式化的line-box的文本,文字盒的边界由绿线来表示。由于文字盒是紧挨着baseline的,因此baseline的位置发生变化的话,文字盒的位置也会跟着改变(这里所说的文字盒在标准中被叫作strut)。
总结起来的话有如下两点:spa
有关Vertical-align各个取值的说明读者仍是上MDN看吧。也能够看看天镶大神的博客上的文章.net
我想将一个icon与文字对齐仅仅使icon的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>
下面给出上图的辅助线版本
缘由就是左面的文字根本就没有发生对齐行为,它仍是对齐于line-box的baseline。而vertical-align对齐的点是baseline加上半个x的距离(half of the x-height)。所以文字的最高点超过了icon的高度。
而右面的例子,文字与icon都对齐于一个中点,文字的baseline稍微下移,位于line-box的baseline的下方。结果是很好的达到了icon与文字对齐的效果。3d
这是一个Vertical-align的坑,line-box中的全部元素都会影响到baseline的位置。假设,一个元素按某种方式垂直对齐了,可是这种对齐方式会引发baseline的移动,又由于大部分的垂直对齐方式(除了top和bottom)和baseline有关,所以这个元素的垂直方向对齐的行为会引发该line-box内其余元素位置的调整。
下面仍是一些例子
<!-- 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设置为其余值,也能看到相似的行为
甚至将vertical-align设置为bottom或者是top也会让baseline发生移动。这很奇怪,由于这时候应该就没baseline什么事儿了。
<!-- 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>
将两个更大的元素放在一个line里面,而且设置vertical-align的值让line-box的baseline移动。在知足vertical-align数值对齐的条件下,line-box的高度会自我调整,如左面的图。再增长第三个元素,第三个元素若是由于其vertical-align的设置不会超过line-box的边缘的话,它是不会影响到line-box的高度和baseline的位置的,若是它会超过line-box的边缘,那么line-box的高度和baseline的位置也会进行调整。在第二种状况下,另外两个元素的位置发生了下移。
<!-- 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>
下面给出一个例子,若是尝试将li元素在垂直方向上进行对齐的话在,这个现象很是常见。
<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>
正如你所见,li元素是对齐baseline的,baseline的下方会给字母的一部分留出空间,所以会产生一个空隙。解决方案就是改变line-box的baseline的位置,好比将这些li这是为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>
inline元素之间的空隙形成布局效果与理想状态发生误差
这主要是由于inline元素自己的缘由,可是由于若是要让vertical-align的值产生做用的话,inline元素是必备要求,所以了解一点也不错嘛
这个空隙来源于inline元素之间的空格,全部的inline元素之间的空白都会变成一个空格。若是你想让inline元素在水平上紧挨着,设置它们的宽度是不行的。由于之间存在空隙,因此行的宽度不够放下两个inline元素。一行会被破坏为两行。解决方案以下图的右侧
<!-- 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属性不起做用,那么问问本身: