我对CSS vertical-align的一些理解与认识(一)

这篇文章发布于 2010年05月14日,星期五,23:20,归类于 CSS相关。 阅读 531725 次, 今日 31 次 53 条评论

 

补充于2018-05-07

此文差不多是8年前写的,当时自己还很年轻,很多细节其实并没有想清楚,所以本文内容仅供参考。更准确更成熟的阐述,可以参考我的著作《CSS世界》,有非常系统的深入讲解。

一、关于今天,本文,及其他

今天是个特殊的日子,因为今天是汶川地震两周年的日子,我很悲鸣;今天又是国际护士节,看到微博上护士照横流,我很欣慰。

一段放松的YY后,进入正题。上个月21号,有位同行留言想让我讲讲vertical-align属性,我其实对vertical-align属性也是略知皮毛,要说岂敢谈“讲解”,就说说我对vertical-align属性的一些理解吧,纯属个人见解,若有不准确之处还望见谅。还有,vertical-align属性牵扯到的知识实在是太多了,不是一篇文章就可以讲清楚的,这里我就只挑几个典型或是重要的地方说一说。

在开始之前,希望对下面的知识有所了解,inline box模型,inline/inline-block/block属性。

//zxx: 关于inline box模型,我在这篇文章的“浮动的’破坏性’”部分做了专门的介绍。

二、vertical-align一大堆乱七八糟的属性

vertical-align指的是什么意思呢?我window+D清屏,双击打开有道桌面词典,输入vertical,再输入align,“哦~~~~”,我脑袋一晃,原来是“垂直的”+“对齐”的意思,就是垂直对齐嘛!

意思先放一边,我看先看看vertical-align支持哪些属性,我比较喜欢轻巧的Dreamweaver,看看他的提示属性又哪些:

vertical-align属性支持的一些属性值 张鑫旭-鑫空间-鑫生活

有句俗语叫做“见多不怪”,我估摸着这些top, bottom属性大家都见过,没啥看头,没啥说头。老实讲,我看到这些养臭虫的属性也头疼,所以,忘了他们,我们说点有意思的。vertical-align属性与数值。见下面的表:

描述
数值 上下的高度值,支持负值
百分值 – % 上下的高度值,百分大小相对于”line-height”属性
baseline 默认。元素放置在父元素的基线上。
sub 下标对齐
super 上标对齐
top 把元素的顶端与行中最高元素的顶端对齐
text-top 把元素的顶端与父元素字体的顶端对齐
middle 父元素中线对齐
bottom 把元素的顶端与行中最低的元素的顶端对齐。
text-bottom 父元素文字底部对齐
inherit 继承父元素
描述
长度 通过距离升高(正值)或降低(负值)元素。'0cm'等同于'baseline'
百分值 – % 通过距离(相对于1line-height1值的百分大小)升高(正值)或降低(负值)元素。'0%'等同于'baseline'
baseline 默认。元素的基线与父元素的基线对齐。
sub 降低元素的基线到父元素合适的下标位置。
super 升高元素的基线到父元素合适的上标位置。
top 把对齐的子元素的顶端与line box顶端对齐。
text-top 把元素的顶端与父元素内容区域的顶端对齐。
middle 元素的中垂点与 父元素的基线加1/2父元素中字母x的高度 对齐。
bottom 把对齐的子元素的底端与line box底端对齐。
text-bottom 把元素的底端与父元素内容区域的底端对齐。
inherit 采用父元素相关属性的相同的指定值。

1. 首先关于数值,见下面的示例:

.test{vertical-align:-2px;}

我的理解为,元素相对于基线向下偏移两像素,这个常常用来修复单选框/复选框与12像素文字大小不对齐的问题。这个没有什么好说的。

2. 再者关于百分数值,百分值与数值,以我的眼光看去,代表了不同的思想,以及心态。前者代表着灵活,自由与开放,后者有严谨,精确,安稳之意。CSS中支持百分值的属性还不少,例如width/height, line-height, font-size,这里的vertical-align属性也是其一。提到百分值,必然牵扯到相对于那个属性(或值),例如宽度百分比都是相对于父块状元素的宽度值的,font-size的百分值是相对于向外的第一含有font-size属性的层的font-size大小而言的,而这里的vertical-align,有些不拘一格,是相对于此标签继承的line-height值决定的。例如,如下示例代码:

.test{vertical-align:-10%;}

假设这里的.test的标签继承的行高是20px,则这里的vertical-align:-10%所代表的实际值是:-10% * 20 = 2(像素)。不过事情没有这么简单,CSS中的line-height是个非常精深的属性,建议您看看我之前写的这篇文章:css行高line-height的一些深入理解及应用,所以遇到像IE6/IE7这样吃三鹿奶粉长大的浏览器肯定会出点篓子的。什么篓子呢,就是“IE6/IE7浏览器下的vertical-align的百分比值不支持小数line-height。”您可以看看我处理的以小数值line-height继承的vertical-align百分比显示对比图[参展对象:IE6(观众扔鸡蛋)和Firefox3.6(美女送鲜花)]:

IE6/IE7浏览器下的vertical-align的百分比值不支持小数line-height 张鑫旭-鑫空间-鑫生活

如果您现在使用的就是IE6或是IE7或是IE6/7内核的浏览器,同时相对这个bug有所见识,您可以狠狠地点击这里:IE6/7 vertical-align百分值与line-height小数值bug

要是您不想见到让您生气的IE下的糟糕表现,您可以狠狠地点击这里:非小数line-height修复demo

3. 最后关于其他属性,像是bottom,middle等,我是懒得说什么了,为何?可以看看下面这张兼容性表:

兼容性(vertical-align)
Internet Explorer Firefox Safari Opera Chrome
5.5 6.0 7.0 8.0 1.0 1.5 2.0 3.0 3.5 1.3 2.0 3.1 4.0 9.2 9.5 10.0 2.0
Buggy Buggy Buggy Buggy Buggy Buggy Buggy Buggy Buggy Buggy Buggy Buggy Buggy Full Full Full Buggy

这是老外前辈整出的vertical-align兼容性表,虽然我不清楚Opera浏览器一栏的full是个什么意思,但是”buggy”知道,就是臭虫成群,bug成堆的意思,我想,做过简单研究的都会注意到不同浏览器下的差异确实明显。

不过vertical-align的这些属性值也不是一无是处,有些属性,例如text-bottommiddle有时会用来修正一些样式表现或是实现特定布局。这个后面再说~~不过有一点知识有必要补一补就是,baseline,middle,top,bottom到底指什么,看下面这张图,我是找了张图ps了好一会儿:

英语本子的各条线 张鑫旭-鑫空间-鑫生活

我们刚学英语的时使用的那个英语本子每行有四条线,其中底部第二条线就是基线,是a,c,z,x等字母的底边线。下图的红色线即为基线。

三、为什么我的vertical-align属性不起作用?

知道了vertical-align是垂直对齐的意思,不少经验尚浅的同行会试着使用这个属性实现一些垂直方向上的对齐效果,会发现有时候可以,有时候又不起作用,不知道为什么?不急,慢慢来。

我们知道display也有很多属性值,其中以inline/inline-block/block三个最常见,这代表了页面上三种不同水平的元素。我常常会以液态/固液混合态/固态加以形象化思考,对应于现实中的事物就是:牛奶/果冻/坚果。

我们都知道,每个人都有不同的嗜好,有的人喜欢吃甜食,有的人喜欢吃辣的东西,有的人不喜欢吃芹菜,有的人不喜欢吃羊肉等等。CSS中的有些元素也是这样,他们有的只对牛奶感兴趣,有的只喜欢吃坚果和果冻,而讨厌牛奶。而vertical-align呢,是个比较挑食的家伙,它只喜欢吃果冻,从小吃果冻长大,没有了果冻,它就会闹脾气,对你不理不睬。我称之为“果冻依赖型元素”,又称之为“inline-block依赖型元素”,也就是说,只有一个元素属于inline-block(table-cell也可以理解为inline-block水平)水平,只有一个元素属于inline或是inline-blocktable-cell也可以理解为inline-block水平)水平,其身上的vertical-align属性才会起作用。所以,类似下面的代码就不会起作用:

span{vertical-align:middle;}
div{vertical-align:middle;}

所谓inline-block水平的元素,就是既可以“吸”又可以“咬”的元素,既可以与inline水平元素混排,又能设置高宽属性的元素。哪些元素呢,例如图片,按钮,单复选框,单行/多行文本框等HTML控件,只有这些元素默认情况下会对vertical-align属性起作用。

虽然vertical-align属性只会在inline-block水平的元素上期作用,但是其影响到的元素涉及到inline属性的元素,这里千万记住,inline水平元素受vertical-align属性而位置改变等不是因为其对vertical-align属性敏感或起作用,而是受制于整个line box的变化而不得不变化的,这个后面会较为深入的分析。

zxx://最近较忙,下面内容写于14日

四、vertical-align属性是如何起作用的?

这里,我使用vertical-align:middle属性作为例子,讲讲我对vertical-align是如何起作用的理解。

CSS参考手册上说vertical-align:middle是将当前元素放在父元素的中间,大致一读,似乎是那么回事,但是细细一想,不知道具体指什么,概念模糊。我们从简单的开始,一步一步探究生效的原理。

1. 一些简单的例子

这里先列举几个简单的例子,方便对vertical-align:middle有了初步的直观的认识。例子内容如下,创建一个inline-block属性的元素,此元素的高度和宽度均为4像素,为了对比效果明显,我使用黑白二色,背景黑色,此4像素*4像素的元素为白色,vertical-align属性依次为middlebottomtext-bottom,当然,文字是必须的,否则何见对齐呢!整个实例的HTML代码都是一致的,唯一不同的就是一段vertical-align属性,测试环境均是Firefox3.6浏览器,HTML代码如下:

<span class="box">
    <span class="dot"></span>
    我是一段卡哇伊的文字。
</span>

实例一:默认属性(也就是baseline)
参见如下的CSS代码:

.box{background:black; color:white; padding-left:20px;}
.dot{display:inline-block; width:4px; height:4px; background:white;}
结果如下图:

默认vertical-align baseline效果 张鑫旭-鑫空间-鑫生活

实例二:bottom
参见如下的CSS代码:

.box{background:black; color:white; padding-left:20px;}
.dot{display:inline-block; width:4px; height:4px; background:white; vertical-align:bottom;}

结果如下图:
bottom属性的vertical-align效果 张鑫旭-鑫空间-鑫生活

实例三:text-bottom
参见如下的CSS代码:

.box{background:black; color:white; padding-left:20px;}
.dot{display:inline-block; width:4px; height:4px; background:white; vertical-align:text-bottom;}

结果如下图:
text-bottom属性的vertical-align效果 张鑫旭-鑫空间-鑫生活

对比vertical-align:bottomvertical-align:text-bottom,他们的表现似乎一样,实际上呢,这里的表现一致只是一个巧合而已,此话怎讲?要显示其差异很简单,添加一个line-height值,您就会看到不一样的地方了。

实例四:line-height:10px + vertical-align:bottom
参见如下的CSS代码:

.box{background:black; color:white; padding-left:20px; line-height:10px;}
.dot{display:inline-block; width:4px; height:4px; background:white; vertical-align:bottom;}

结果如下截图:
line-height减小后的效果 张鑫旭-鑫空间-鑫生活

而如果vertical-align的属性值是text-bottom呢?

实例五:line-height:10px + vertical-align:text-bottom
参见如下的CSS代码:

.box{background:black; color:white; padding-left:20px; line-height:10px;}
.dot{display:inline-block; width:4px; height:4px; background:white; vertical-align:text-bottom;}

结果如下图:
line-height减小后的效果

可以看到,vertical-align:text-bottom声明的那个小方点的位置没有随着line-height的改变而改变,还是与文字的底部对齐。如果您细看关于text-bottom以及bottom属性的定义,您可以找到其表现的原因:text-bottom是与父标签的文字底部对齐,在这里也就是后面的“我是一个卡哇伊的文字”这段文字对齐,而bottom是相对于父标签的底部对齐,而如果您熟悉line box模型且对高度的本质有所了解,那么您就会明白为什么line-height会改变标签的bottom的位置了。这点的了解有助于理解下面vertical-align:middle生效的过程及原理。

实例六:middle
参见如下的CSS代码:

.box{background:black; color:white; padding-left:20px;}
.dot{display:inline-block; width:4px; height:4px; background:white; vertical-align:middle;}

结果如下图所示:
vertical-align:middle的显示结果 张鑫旭-鑫空间-鑫生活

2. 复杂点的例子

如果说上面的例子只是热身的话,那么现在就要开始进入实战了。在这里的实例中,我们添加一个新的元素,就是图片,我们通过观察不同属性下图片的样式表现来理解vertical-align:middle等相关属性是怎么一回事,是怎样产生页面表现的。

为了方便大家理解,同时也是为了自己加深对vertical-align的理解,我特地做了个简易的vertical-align属性实验面板,见下图:

vertical-align实验面板页面截图 张鑫旭-鑫空间-鑫生活

vertical-align实验面板页面地址可访问,您可以狠狠地点击这里:vertical-align属性测试面板页面

通过修改,行高以及对应元素的vertical-align属性,您会在页面上直接看到效果,同时修改文字大小的页面表现也有助于您对inline box模型的理解。由于IE6/7对inline box的解释不完善,同时对vertical-align的认识也是一坨香喷喷的鸟屎,所以请不要再IE6/7下使用此面板,会对您产生误导的,IE8,Firefox,最新的Opera浏览器,chrome。Safari浏览器都是上佳的选择。关于IE6/7的解释问题会在下集介绍。

这里说点我的认识吧:vertical-align:middle属性的表现与否,仅仅与其父标签有关,至于我们通常看到的与后面的文字垂直居中显示那都是假象!这就是我的认识,当然,我也可以为我的理解提供强有力的证据,我们来看vertical-align属性实验面板。

当我们将图片vertical-align:middle属性改为其他的时候,例如top,或是bottom的时候,您会发现,图片位置上移或是下移了,且居边了,但是文字在那里却纹丝不动,显然,vertical-align的本质上是个独立的个体,与后面的inline水平的元素是不存在直接的关系的。两者没有必然的联系,这是一个需要认识清楚的重要的东西。

vertical-align与inline水平元素无必然关系 张鑫旭-鑫空间-鑫生活

五、下集预告

下集看点:

  1. 解析vertical-align一般的行为表现
  2. vertical-align相关对齐问题分析及解决
  3. 浮动为何可以破坏vertical-align属性

(本篇完)

分享到:


发表评论(目前53 条评论)

  1. cp说道:

    鑫哥,实例四:line-height:10px + vertical-align:bottom,就是这个实例,我去反复验证了一下结果是左边小方框是没有上移,但是如果我把ling-height:10px的值改为更大的值,结果是,左边的小方框会往下移,鑫哥,你可以去验证一下

  2. 串串说道:

    大佬,下集预告在哪呀?烦请指一下路

  3. boseny说道:

    太详细了,受教了!

  4. 为什么我的vertical-align属性不起作用?说道:

    楼主我安装你的说明 没有起效果啊 你说 vertical-align挑食 要是 inline-block
    checkbo 元素
    1:说要加 display: inline-block;
    2: vertical-align: middle;
    没有作用。
    反而是
    直接 vertical-align: -webkit-baseline-middle;对齐了 label 是我理解错了?

  5. levinit说道:

    vertical-align对inline-block无效吧
    > CSS 的属性 vertical-align 用来指定行内元素(inline)或表格单元格(table-cell)元素的垂直对齐方式。

    > 适用元素 inline-level and table-cell elements. It also applies to ::first-letter and ::first-line.
    https://developer.mozilla.org/zh-CN/docs/Web/CSS/vertical-align

    • levinit说道:

      vertical-align用在文本和与文本相邻的元素的在垂直方向上的对齐方式。 我自己理解有偏差:D

  6. zty说道:

    关于verticle-align:middle;的那个…我和你测试的不一样啊 我的不在中间,而是在相对偏下的位置,怎么回事呢?

    • levinit说道:

      设置为middle也不一定是真正的对齐,不同风格的字体常有不同的排版标准,设置为middle值其实是将该元素的中垂点与其父元素基线高度+父元素中小写字母x的高度的一半的值的位置对齐。

  7. 杨小侨说道:

    在例子中HTML的结构是

    我是一段卡哇伊的文字。

    加上
    .box{background:black; color:white; padding-left:20px; line-height:10px;}
    .dot{display:inline-block; width:4px; height:4px; background:white; vertical-align:bottom;}
    的样式。。
    没人发现line-height对box根本就没有影响吗?chrome浏览器下。发现inline元素的line-height不可以设置比文字小啊?没效果的啊??

    • 杨小侨说道:

      不好意思。知道了。是我理解错误了。。但是。。这个例子。。我测试的时候真的没看到任何改变。不管是不是加了line-height。正方形相对于字体都是不移动的。

      • 匿名用户说道:

        我把line-height的值改大了些,就看到效果了。

        • cp说道:

          是的line-heigth:10px.是不会有啥变化的,我也去测试了很久,结果也是这样,但是如果你把这个值改为大一点的,你会看见正方形会往下移

  8. jhon说道:

    可以的,受教了

  9. jiejei说道:

    是这样

  10. young说道:

    受益匪浅

  11. 阿牛说道:

    下集呢?期待啊

  12. 易松坤说道:

    也有人说两个同等级同行元素高度小的中线会对齐高度大的中线 而且我试了一下 改变大元素的高度(始终保持比小的元素高),高度小的元素位置会改变 会随着高度大的高度改变而改变

  13. 行内元素span说道:

    .box{background:black; color:white; padding-left:20px; line-height:10px;} 行内元素span可以设置line-height?

  14. Frank说道:

    广告居然是直接手动加的!!牛批!

  15. 妈拉个巴说道:

    div嵌套div,怎么实现里面div中的内容相对于外部大div水平和垂直居中呢?

    • Document

      父子元素 进行定位 子元素margin:auto;top:0;left:0;bottom:0;right:0;

      父元素display:table-cell;vertical-align:middle; 子元素变成一个内联元素display:inline-block

      父元素 flex布局 justify-content:center align-items:center子元素就会居中

      对父元素定位,对子元素绝对定位,子元素left:50%,top:50%;margin-left:-子元素一般的宽度;margin-top:-子元素一半的高度px;

      今天刚刚学习的,希望对你有帮助

  16. 在路上……说道:

    多半用于图片居中,刚入行的,起初不知道这个方法,还与别人争论align:absmiddle……今天遇到,用浮动和定位,vertical-align: middle;起了作用,但是图片根本不在居中,这是为什么?

  17. 窥天者说道:

    说了一堆,我就没明白什么是垂直对齐

  18. LikeDege说道:

    “只有一个元素属于inline或是inline-block(table-cell也可以理解为inline-block水平)水平,其身上的vertical-align属性才会起作用”,为什么说是“只有一个”,几个inline-block排成一行,不也会起作用吗?求解

  19. PageYe说道:

    您好,希望补充一下,“middle 元素的中垂点与 父元素的基线加1/2父元素中字母x的高度 对齐。”这句话应该加上“大写的”X

  20. 怎么实现上下左右都居中?说道:

    学长,你好。最近在写网页时,遇到问题,对于菜鸟的我,解决许久还是没成。就是怎么让一个层里面的图片在那个设置了宽高的里面上下左右都居中。。而且这段代码我要重复用,且每次src的图片大小可能都不一样。。但是需要就是不管传进来什么大小的图片,只要比小,都能上下左右都居中?谢谢了~~
    代码如下:

    ……………………

  21. huifi说道:

    “我常常会以液态/固液混合态/固态加以形象化思考,对应于现实中的事物就是:牛奶/果冻/坚果。”
    我感觉应该是:牛奶/果冻/冰块

  22. fy说道:

    校友的这篇文章很有帮助!

    看xinxu的博客让我这个门外行学了不少东西!

  23. 爱慕啼说道:

    张老师,你的页面是不是设置了什么机关,无法使用F12开发者工具

  24. Leooonard说道:

    对元素使用vertical-align是否会破坏line-box模型? 即去掉该元素后, 剩余元素重新计算line-box.

  25. 公交候车亭说道:

    博主,有些图片怎么显示不了呢?

  26. 玉慕瑕说道:

    后面几期的呢?就两篇么?

  27. ifishing说道:

    文中有几处笔误:
    1>bottom 把元素的顶端与行中最低的元素的顶端对齐。
    显然是错误的。
    2>而bottom是相对于父标签的底部对齐,而如果您熟悉line box模型且对高度的本质有所了解,那么您就会明白为什么line-height会改变标签的bottom的位置了。
    错误之处:bottom是把元素相对于元素所在line box的bottom line对齐,也就是行中最低的元素的底端对齐。

  28. reyhappen说道:

    告诉你基线baseline是啥,你打开ps,输入文字,在编辑状态下文字下面不是有根横线么,那就是基线。

  29. lianghaijun说道:

    [p][span style=”
    vertical-align: -30px;
    “]abc[/span][span]def[/span][/p]

  30. lianghaijun说道:

    abcdef

    两个都是 inline , 没有inline-block

  31. ithinc说道:

    middle父元素中线对齐的解释是错误的,middle在table-cell和inline元素中的含义不同。

  32. River说道:

    full的意思,也许是完美。我猜的。。。。

  33. 肉山说道:

    建议写的精简干练些,毕竟是技术文章。除了这个之外还是挺好的。两年前也有人写过这个:http://www.mikkolee.com/13 《大家都对vertical-align的各说各话》

  34. 番茄说道:

    不知楼主看过《css权威指南》没,
    你这篇文章中有几处错误,尤其是vertical-align只能用于inline-block元素这一说法…
    前提错了,后面的分析就有问题了。
    这里涉及几个重要的概念,”行内框”,“行框”,“基线”,vertical-align:middle的时候有个“0.5ex”。

    • 张 鑫旭说道:

      这我知道的,像display:table-cell属性,也支持vertical-align属性,但是文中我也说了,display:table-cell可以看成是inline-block属性的元素。确实,我这方面的认识还有待于进一步加强。

  35. vapour说道:

    学习了,讲得很好。