CSS vertical-align的深入理解(二)之text-top篇

这篇文章发布于 2010年06月12日,星期六,23:32,归类于 css相关。 阅读 92807 次, 今日 5 次

补充于2018-01-01:当时写这篇文章也是变研究变整理的,因此,有不少想法其实是不成熟的。要想更准确深入了解vertical-align相关知识,可以去我的著作《CSS世界》中寻找答案。

一、上集内容简单提要

上集内容“我对CSS vertical-align的一些理解与认识(一)”要追溯到差不多一个月以前了,主要是了解了下vertical-align的一些属性,并简单讲述了自己对vertical-align属性的一些理解。vertical-align是个相当复杂与精深的属性,所理解的一些内容多少会有不准确之处,例如之前我认为inline属性的元素对vertical-align属性是不感冒的,但是在同行的提醒下,我自己一测试,发现完全不是之前自己所想的,就算是很单纯的inline水平的元素都支持vertical-align属性的。所以自己有必要对vertical-align的认识重新梳理,整理成文。本集内容主要讲讲我对在一般情况下vertical-align其作用的理解,以及vertical-align相关的对齐问题,以及浮动为何可以破坏vertical-align属性。

二、我对不同浏览器解析vertical-align属性的理解

在上集中,在最后提供的实例中,vertical-align:middle实际上应该是与后面的文字是独立的,毫无关联,就是说vertical-align无论是什么,都不影响文字在box中的位置(IE6/7对vertical-align理解与现代浏览器有差异)。但是在实际情况下,行高可能会小于inline-block或是类似于inline-block属性的元素的content area的高度,此时vertical-align对文字的影响似乎是显而易见的,那么这种影响是如果实现的呢?这就是本段的重点。

1. 我对vertical-align文字对齐相关属性的理解

vertical-align属性可以说是CSS中兼容性最糟糕的属性之一了。比如说与文字相关的vertical-align属性,vertical-align:text-topvertical-align:text-bottom属性,这两个属性的解释IE浏览器(IE6-8)和现代浏览器是不一样的两个派别。到底哪种表现是正确的,这是不能随便做定论的。无论实现的机制如何,若能实现类似的效果表现,其实都可以说是正确的。在一般的使用条件下,例如小图标+文字,vertical-align:text-top这类文字对齐类属性在不同浏览器下的差异是较小的,这很难让我们去思考与理解这些差异在什么地方。但是,如果我们将测试的元素进行简化与放大,那么差异显而易见,也更利于我们思考其中的原因所在。

IE家族和现代浏览器解释Text相关vertical-align属性的两大阵营

我们可以参见下面的测试代码,一窥IE家族和现代浏览器下text相关vertical-align的差异表现:
<div style="line-height:200px; border:1px solid #34538b;">
    <span style="font-size:60px; border:1px solid #a0b3d6; vertical-align:text-top;">大大的文字</span>后面是静止的文字。
</div>

line-height作为唯一的高度来源,且远远大于content area高度的时候(只与字体大小相关),此时我们可以喝直观的看到不同浏览器下的表现。上面代码很简单,一个行高200像素的div,里面有一个带有vertical-align:top属性的字体大60像素的inline水平的行内元素,边框只是便于观看识别留下的。

在展示不同浏览器下的表现之前,您可以先按照自己的理解想想会是什么样的表现。

说实话,以我之前纯粹的所谓想象经验式的理解,应该是后面的文字与大号文字的顶部对齐,事实是如何呢?看下面的IE阵营和现代浏览器阵营下的表现截图:

IE7浏览器下vertical-align:text-top属性截图

IE8下vertical-align:text-top表现截图

对比IE7浏览器和IE8浏览器下的表现我们可以看到,就文字的垂直对齐方面,两者是一样的,这也很符合自己以往对vertical-align:text-top的形象化的了解,也就是文字顶部对齐,看IE浏览器下就是文字顶部对齐的,后面的文字的顶部就与前面大号文字的顶部的文字对齐。所不同的就是IE8浏览器的外部div的高度被撑开了27像素,差不多是1/2个文字大小的高度。下面看看两个代表性的现代浏览器下的样式表现(Firefox3.6&Chrome5):

Firefox3.6下vertical-align:text-top表现截图

Chrome5下的vertical-align:top效果图

经过我的仔细对比,Firefox3.6下的页面表现欲Chrome5浏览器下的是一模一样的,不仅如此,还与Opera浏览器也是表现一致。于是,就单纯从页面表现上来看,出现了两个阵营,不太和谐的IE阵营以及高度一致的现代浏览器阵营。但是究竟孰是孰非呢?这需要慢慢说来!

就表象而言

似乎可能好像IE浏览器下的表现符合我之前对vertical-align:text-top似是而非的理解,文字顶部对齐。看那,IE浏览器下,无论是IE6还是IE7或是IE8都是这样子的。相比之下,现代浏览器下的样式表现有些令人费解。OK,要追寻问题的解决最好的方法就是寻找他的根源,去需找它的定义,而不要根据一些表象而去臆测。
text-top
    aligns the top of the box with the top of the parent element’s font

翻译过来就是:让当前box的顶部与父元素的文字的顶部对齐

所以我们只要恰准了box的顶部以及父元素文字的顶部,就可以知道这类表现是怎么回事,哪种表现更加符合其本身的定义。

当前box的顶部
在本实例中,当前box是包裹着“大大的文字”的这5个文字的span标签,那么这个标签的顶部在哪里呢?按照我对inline box模型的理解,这个标签的顶部应该是在——见下图标注:

span元素的顶部

上图中蓝色的参考线就是这个span box的顶部。如果您了解line box模型,这个不难理解。line box中重要的几个概念是:content area,inline box(以及匿名inline box),以及由inline boxes组成的line box。

  1. 其中content area可以理解为内容实体,也就是图片中的文字,我们设置span标签的border属性或是background属性,所看到的围绕文字的边框以及背景色的区域就是指的content area,这个东西仅仅与文字的大小相关,其作用仅仅是显示内容而已,很多重要的工作都不是content area来执行的。content area图片示例
  2. 每个inline属性的标签外部都有一个inline box,这个inline box是看不见的,这个看不见的inline box扮演者重要的角色,此box与CSS中的line-height属性相互配合构成了元素高度堆叠的基础。以我的理解,inline box的高度纯粹就是有元素的line-height或是继承的line-height值决定的。例如本实例中,父divline-height200像素,自然,含“大大的文字”的span标签所在的inline box的高度就是200像素,换句话说,这个含有vertical-align:text-top属性的span标签的实际高度是200像素
  3. 本实例中有一段文字“后面是静止的文字”外部并未直接包裹任何标签,但是这段连续的文字外部也包裹了一个看不见的inline box(称之为匿名inline box),其本质以及一些表现与inline box几乎无异。也能占据200像素的高度。
  4. span标签外部不可见的inline box以及文字所在的匿名inline box共同组成了line box,line box也是不可见的,每行文字有且仅一个line box,line box的高度有其内部的一系列的inline boxes高度共同决定,由内部的inline boxes的上下最大绝对差值决定的。例如本实例红,在现代浏览器下,外部div的高度之所以会被撑开,是内部两个inline boxes共同作用的结果。

所以结合上面的简单分析,本实例中含有vertical-align:tetx-top属性的span标签实际的box区域应该如下图半透明绿色区域:

span标签实际占据的区域

父标签的文字顶部
具体什么是“父元素的字体”我也不是很清楚,这是个很虚的概念,我甚至怀疑这本身就是个抽象出来的概念,例如一个div中两个inline水平的标签,一个vertical-align:text-top另外一个vertical-align:text-bottom,那么哪个才是这里的“父元素的字体”呢?我更加倾向于将这个“父元素的字体”解释为,假设父标签中有个很单纯的文字,指无标签,无嵌套的文字,所有属性纯粹继承的文字(即使这个文字根本不存在),那么这个文字就是这里所指的“父元素的字体”。

zxx://难以搜到相关资料,上述观点都是自己推测的,仅供参考

在本实例中,正好“后面是静止的文字。”这段文字字符是纯粹的文字,属性完全继承的文字,则“父元素字体的顶部”就可以认为是这段文字的顶部了。

所以,综上所述,实际占据200像素的span标签要与后面的“纯粹文字”顶部对齐,没有办法,这个span标签只好下移,下移的距离为92像素,这个92像素时如何来的呢?很简单:后面的文字实际也占据200像素的高度,其中本身文字大小16像素,也就是文字的content area占据16像素的高度,如果span标签与文字垂直中线对齐,则下移为100像素,但是由于是顶线对齐,于是要少掉1/2个文字高度,也就是8像素,于是span标签下移了92像素。

具体实现参见下面的Flash动画演示,点击“下一步”按钮查看演示与说明,如果无法显示可以点击这里直接浏览

IE浏览器的解释

像Firefox,Chrome,Opera浏览器被称为modern browser(现代浏览器),也被称为标准浏览器。这类浏览器对于CSS的渲染都是比较符合W3C标准的,但是IE浏览器,有点孤芳自赏之感,走了很多自己的路,于是在CSS的解释与渲染上,很多与标准浏览器之间是有差异的。其中对vertical-align的解释就是其中之一。本文之前所有的讲解都是针对的现代浏览器。

虽然IE8对不少vertical-align属性的解释与现代浏览器一致,但是有些还是走的其老套路。例如这里的vertical-align:text-top属性。由于IE浏览器对vertical-align:text-top的解释与标准有差异,所以我也无法准确说出其样式表现的机制是什么。按照我自己未经证实的一些推测,IE浏览器(IE6-IE8)似乎将当前元素的顶部理解为了当前元素文字的顶部(也就是inline box模型中的content area的顶部,而不是inline box的顶部),于是vertical-align:text-top就是两段文字之间的对齐,span文字的顶部与后面裸文字的顶部对齐。如果我们不仔细思考vertical-align的定义,可能就会觉得IE浏览器的实现似乎更合理,更容易理解。

IE8下vertical-align:text-top表现截图

IE8浏览器的UI表现欲IE6/7还是有一点差异的,差异在于父元素的高度。IE8浏览器的父元素高度被撑开了,而IE6/7这里反而不撑开了(⊙﹏⊙b汗),IE8下高度为227像素,这多出来的27像素是60像素的文字下移与后面文字顶部对齐的距离。这与现代浏览器下的父标签撑开表现是有些类似的,IE8浏览器可以说是有改进的,但是在理解父元素的顶部上似乎与现代浏览器有偏差,不知在IE9浏览器下会是怎样的一个表现。一起拭目以待。

附上本文的这个很简单的demo:狠狠地点击我

内容真多,已经连续写了好几个晚上了,不得已,还得分篇叙述……资质尚浅,理解上可能有错误,欢迎指正,不甚感谢!

未完,待续……

(本篇完)

分享到:

赞助商推荐(我也要赞助)

想学到点真东西? ×
如果你有1~3年前端开发经验,不妨 ×
想高薪入职阿里? ×
想要免费一对一编程辅导? ×


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

  1. 阿力说道:

    愚以为,ie6-78对vertical-algin:text-top的解析更准确也更合理,对于一个inline来说,它是不支持宽高的(也就是给设置宽高是不起作用的),所以这时候的span就应该是和content area的顶部对齐,而标准浏览器在上述例子中是把后面 的文字这样的inline看成是支持宽高的inline block,所在才会使得左边的文件下移

    • ziyu说道:

      不,主要是虽然它不支持宽高,但是inline元素形成的行内框的高度又是由line-height决定的,你说的和这个不是一回事,说的是“让当前box的顶部与父元素的文字的顶部对齐”,而不是当前box的内容区域顶部与父元素的文字的顶部对齐

  2. netgare说道:

    float浮动会破坏vertical-align的属性,详见https://developer.mozilla.org/zh-CN/docs/CSS/float 里边有详细说明,float以后,及时display为行内元素,计算值仍为block元素,所以是不会起作用的

  3. hunter说道:

    分析的很好,之前第一遍看书没怎么理解,尤其是一些像行内框、内容区、em框、行框、行高之间的关系,现在结合博主的例子再看看书感觉茅塞顿开

  4. 嘎嘎说道:

    看了楼主自编自画的个人介绍 哈哈 有意思,楼主是个性情中人啊,可惜离上海太远,没机会一起钓鱼

  5. 嘎嘎说道:

    文章写的很好,条理清晰,简单易懂,w3c讲是父元素字体的顶端对齐,就是父元素字体的顶端真是个百感交集的位置。不知道从何找起啊。

  6. 林奕缤说道:

    float会破坏vertical-align的文章是哪个呀

  7. 雄东说道:

    首先感谢博主,精彩的博文。以下我关于line-height的观点(不一定正确)
    1.line-height并似乎不是由line内最高的inline元素决定的,行高的定义似乎也不是两条baseline的距离,
    而是四条线中间夹着的三个距离之和。因为topline到middleline和baseline到bottomline的距离可能不一样。
    比如两个inline-block元素,一个撑高了topline到middleline的距离,另一个撑高了baseline到bottomline的距离。
    2.图片撑高了line-height图片的边界会碰到top或bottom。但是文本的inline或inline-block撑高的line-height却不会碰到top或bottom。意思top和bottom对文本敬而远之。
    3.两条相邻的line,上一条的bottom与下一条的top重合,火狐浏览器和IE浏览器的到了第三行,的三行的topline和第二行的bottomline却并不重合。(我不确定,这是bug还是我观点错误)

  8. 杨dd说道:

    博主,就是这个浮动如何影响该属性啊?怎么没有后文了?

  9. 自命菜菜说道:

    大神,flash三大浏览器都看不了啦。

  10. 刘丹妮说道:

    顶!

  11. 银狐说道:

    怎么没有讲浮动对vertical-align的影响呢

  12. yaoganjili说道:

    vertical-align是按照行高对齐的。

  13. yaoganjili说道:

    根本原因line-height具有继承性

  14. superchangme说道:

    完美的解释,下移92似乎还不是很理解,是否说是其他空白文字撑开了呢

  15. alian说道:

    赞下flash,vertical-align:bottom似乎也是一样的

  16. web工作说道:

    给前边的标签加上display:inline-block;这样ie和现代标准浏览器就一样了

  17. 古德God说道:

    赞!flash里表达的理论很赞

  18. playboyanta123说道:

    你的文章写得都很不错,我都是咬文嚼字的看的,虽然有些官方术语没看懂,但是还是能理解很大一部分,我都了得都转载了啊,留了你的链接,以后我要看的时候可以再仔细看,也想把你的想法推广给更多的同行!

  19. JacksonGL说道:

    很详细的解释,flash动画很赞

  20. hqh说道:

    刚刚遇到vertical-align的问题,折腾半天,细看博主的文章之后,终于解决了,膜拜楼主,

    不过vertical-align还是理解有些模糊,但其实这些不仅仅单纯是这个属性的问题,而是涉及到其他东西
    比如 line-height 、inline-box的概念等等,这些东西没搞清、或者说那些巨头没统一,我们这些百姓是永远搞不清楚的,要实际应用是必须死很多脑细胞的

  21. 飞天追梦说道:

    博主说的很对,我认真学习了css权威指南第四版(最新版本貌似还没有)Basic Visual Formatting一章后,也觉得你说的和规范很一致,能把父容器div的高度算的如此准确,钻的很深啊。
    不过自己做实验还有点问题解决不了,如下的代码中div的高度是怎么精确算出来的呢(在标准浏览器中如火狐中为65px,根据我的经验,火狐中line-height值貌似是字体的1.14倍):

    There is a em and a spanf

    如果有时间,请帮忙解惑,谢谢。

  22. x说道:

    那应该 IE 的才是对的啊。。。目前截至 IE 10 Consumer Preview 对该属性的处理一直和 IE 8 的几乎一样哦。。。

  23. otarim说道:

    博主太有才了,不过这个属性真的很啃爹。。

  24. x说道:

    well, render, not s…

  25. x说道:

    As I know, IE 9 and 10 also renders the vertical-align attribute like the IE 8 mentioned above…

  26. sswhsz说道:

    而如果我们知道 基线和文字底线的距离是 1/7 文字高度,在谷歌浏览器下,checkbox的大小是 13*13像素,所以对于缺省checkbox 按照基线对齐的情况,

    对于大小17px的字体,基线以下2px,基线以上15px,13px的复选框底线和文字基线对齐,是刚好可以对齐的字体大小,其他更小的字体,文字就会偏下,更大的字体,文字会偏上。

    对于vertical-align:middle的情况,是按照checkbox中线和小写字母x的中线对齐,
    对于英文字母来说吗,是比较理想的情况,但对于汉字的中线,和英文字母x的中线有2/7个文字高度的偏离,所以不管多大的字体,都会显得中文文字偏上。

  27. sswhsz说道:

    你好!最近被vertical-align属性弄得头昏脑胀,看了你的博文,豁然开朗。

    另外,关于文字基线、中线的准确位置,经过反复的试验和计算,在谷歌浏览器下
    文字基线距离文字底部 1/7 的字体高度,
    文字中线距离文字基线 1.5/7 的字体高度,
    也就是说,小写字母x的高度是 3/7 字体高度, 小写字母x的中部(文字的中线)距离文字底部2.5/7 高度。

    按照这个比例,在谷歌浏览器下, 各种vertical-align时 就可以把理论计算的高度和 父元素被撑开的高度进行验证了。

  28. NLF说道:

    华丽的动画.

  29. 小鸟一只说道:

    还是看动画直观。
    呵呵。看文字让人直接晕。

  30. 康康说道:

    冒昧的问一下,那个 “后面是静止的文字” 这些文字是16px的定义么?好像没有看到body之类的定义。。。

  31. afc163说道:

    很详细的文章,留个言以后慢慢看。