Heim > Web-Frontend > HTML-Tutorial > Vertical-Align: 你需要知道的所有事【译】_html/css_WEB-ITnose

Vertical-Align: 你需要知道的所有事【译】_html/css_WEB-ITnose

WBOY
Freigeben: 2016-06-24 11:16:30
Original
943 Leute haben es durchsucht

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 的行为 ,不留下历史问题。我最终通过W3C的 CSS 规范 和试验一些例子得到了结果——这篇文章。

使用vertical-align的要求

vertical-align 用来调整 inline 级元素。这些元素的 display 属性为:

  • inline
  • inline-block
  • inline-table(本文不涉及)

inline元素基本上是文本的包裹标签。

inline-block元素正如它们的名字:住在行内的块元素。他们可以有一个width和height(也可能由它内部内容撑开),以及padding、border和margin。

inline元素逐个从左到右地被放置在一行内。一旦有更多的元素加入,使当前行无法放下,一个新的行就会在下方产生。所有这些行有所谓的 line box ,其中包含所有的内容。不同尺寸的内容意味着不同高度的line box。在下图中,line box的顶部和底部是红色线表示的:

line box描绘出了我正在试验的区域。在这些line box中,属性 vertical-align 是负责调整单个元素的。 所以,元素对齐跟什么相关?

关于baseline和外边缘

垂直对齐最重要的关注点是要对其元素的baseline。在某些情况下,元素的包围盒的顶部和底部的边缘也变得很重要。让我们来看看每种类型的元素baseline和外边缘在哪里:

inline元素

在这里你看到三行的文本相邻排布。行高的顶部和底部是由红线表示的,字体的高度是由绿线来表示的,而baseline是由蓝线表示的。在左边,文本具有一个与字体大小相同的行高,绿色和红线在上下都重叠了。在中间,行高(line-height)是字体大小的两倍大。在右边,行高是字体大小(font-size)的一半。

inline元素的外边缘跟自己line-height的顶部和底部边缘对齐,如果line-height小于font-size的话也不会改变。所以,在上面的图中的行的外边界是红线。

inline元素的baseline字符底部所坐的线,就是图中的蓝线。粗略地说,baseline是在font-size中间下面的一个地方,看看W3C规范的 详细定义 。

inline-block元素

从左到右,你看到的是一个拥有 流 内容(一个“c”)的inline-block元素,一个拥有流内容且 overflow: hidden; 的inline-block元素和一个没有流内容的inline-block元素(但内容区域有一个高度)。margin的边界由红线表示,以及黄色的border,绿色的padding和蓝色的内容区域,蓝线是每个inline-block元素的baseline。

inline-block元素的外边缘是其 margin-box 的顶部和底部边缘,即图中的红线。

inline-block的baseline取决于元素是否具有流内容:

  • 在流内容的情况下,inline-block元素的baseline是正常流的最后一个内容元素的baseline(左边的例子)。对于这最后一个元素,它的baseline位置由它自己的规则决定。
  • 在流内容,但具有overflow:hidden的情况下,baseline是margin-box的底边缘(中间的例子),也相当于inline-block元素的底边缘。
  • 如果没有流内容,则跟上一个一样,baseline位于margin-box的底边缘(右边的例子)。

line box

你已经看过了这张图上面的设置,这一次,我画出了line box的text box的顶部和底部边缘(绿线,下文也是)以及baseline(蓝线)。我还给该区域的文本元素添加了一个灰色的背景来强调他们。

该line box具有一个与该行最顶的元素的顶部边缘对齐的 顶部边缘 和一个与该行最底的元素的底部边缘对齐的 底部边缘 ,即是上面图中的红色线所表示的盒子。

line box的baseline是可变的:

CSS 2.1并没有定义line box的baseline. —- W3C规范

这可能是使用vertical-align时最令人困惑的部分。意思是,baseline的位置要在满足所有其他条件,如vertical-align设置和最小化line box的高度的前提下来决定,是方程中的一个自由参数。

由于line box的baseline是不可见的,无法直观感知。但是,你可以很容易地让它变得可见。通过在行的开头加一个字符,比如上图中的字母“×”。如果这个字符没有以任何方式进行对齐,则默认情况下其底部将坐在baseline上。

在其baseline的基础上,line box有一个称为 text box 的东西。该text box可以简单地被认为是line box中一个没有任何对齐的inlne元素。它的高度等于它的父元素的font-size。因此,text box只包裹住line box中的无格式文本,由上图中的绿线表示。因为这个text box位置基于baseline,所以它会随baseline移动。(注:此text box在W3C规范中称为 strut )

唉,这是最难的部分。现在,我们拥有了分析原理的所有前提条件,让我们迅速总结最重要的事实:

  • 有一个区域称为 line box ,这是要对齐的区域。它有一个 baseline ,一个 text box 和一个 顶部 和 底部边缘 。
  • 有 inline级元素 。这些是要被对齐的对象。他们有一个 baseline 和一个 顶部 和 底部边缘 。

vertical-align的取值

从上面的列表总结出来的使用 vertical-align 的要点中,我设置了几种关系样例。

将元素的baseline与line box的baseline对齐

  • baseline:该元素的baseline恰好与line box的baseline重合。
  • sub:该元素的baseline偏移到line box的baseline下方。
  • super:该元素的baseline偏移到line box的baseline上方。
  • :该元素的baseline以line-height高度乘以百分比的距离相对于line box的baseline偏移。
  • :该元素的baseline以绝对长度相对于line box的baseline偏移。

将元素的外边缘与line box的baseline对齐

  • middle:元素的顶部和底部边缘的中点与line box的baseline加上1/2小写字母x高度的位置对齐。

将元素的外边缘与line box的text box对齐

这2种情况也可以以相对于line box的baseline对齐的方式展现出来,因为text box的位置是由baseline确定的。

  • text-top:该元素的顶部边缘与line box的text box顶部边缘对齐。
  • text-bottom:该元素的底部边缘与line box的text box的底部边缘对齐。

将元素的外边缘与line box的外边缘对齐

  • top:元素的顶部边缘与line box的顶部边缘对齐。
  • bottom:该元素的底部边缘与line box的底部边缘对齐。

正式的定义 可以在W3C规范中找到。

为什么vertical-align以这种规则表现

我们现在可以在特定情况下来研究一下垂直对齐,特别是有可能会出错的情况。

居中一个图标

下面这个问题曾经烦扰了我:我想把图标与旁边的一行文本垂直居中对齐,只是给图标设置 vertical-align: middle; 似乎并没有如设想的一样居中。看看底下这个例子:

<!-- left mark-up --><spanclass="icon middle"></span>Centered? <!-- right mark-up --><spanclass="icon middle"></span><spanclass="middle">Centered!</span> <styletype="text/css">  .icon  { display: inline-block;            /* size, color, etc. */ }   .middle{ vertical-align: middle; }</style>
Nach dem Login kopieren

下面的图还是上面的例子,但我画了一些之前提到过的辅助线:

这揭示了我们的问题。左边的x和Centered?没有设置对齐属性,所以它坐在baseline上。重要的是,用 vertical-align: middle; 对齐灰色方块(即图标)后,我们把它的中点与line box的baseline加上x高度的一半处对齐了(图中黄线),然而由于Centered?中部并不在黄线上,所以就显得高于灰色方块(图标)。

在右边,我们进一步把文字中点也对齐了,这使得文本的baseline略微往line box的baseline下方偏移了一点。最终得到了完美的结果。

line box baseline的移动

这里有一个使用 vertical-align 常见的盲点:line box baseline的位置会被行内所有元素所影响。让我们假设这种情况,一个元素以使得line box baseline必须移动的方式进行对齐。由于大多数垂直对齐方式(除了顶部和底部)与baseline相关,这会导致该行中的所有其他元素移动。

一些例子:

  • 如果有一个很高的元素占据了整行的高度,事实上它也决定了整行高度,那么 vertical-align 对它就没有效果,上下都没有空间让它移动,所以line box的baseline为了满足对齐关系必须移动。在下图中,短方块设置了 vertical-align: baseline; ,左例中高方块的垂直对齐方式是 text-bottom ,而在右边中是 text-top 。你可以看到baseline与短方块始终在一起。

<!-- left mark-up --><spanclass="tall-box text-bottom"></span><spanclass="short-box"></span> <!-- right mark-up --><spanclass="tall-box text-top"></span><spanclass="short-box"></span><styletype="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>
Nach dem Login kopieren

当用 vertical-align 的其他值来对齐高方块时也有相似的表现。

  • 然而甚至设置 vertical-align 为 bottom (左图)和 top (右图)也会使baseline移动。这十分奇怪,因为这应该与baseline并无关系。

<!-- left mark-up --><spanclass="tall-box bottom"></span><spanclass="short-box"></span> <!-- right mark-up --><spanclass="tall-box top"></span><spanclass="short-box"></span> <styletype="text/css">  .tall-box,  .short-box{ display: inline-block;              /* size, color, etc. */ }   .bottom    { vertical-align: bottom; }  .top      { vertical-align: top; }</style>
Nach dem Login kopieren

  • 将一行内两个较大的元素垂直对齐会使得baseline移动来同时满足两个的对齐方式,并且也会调整line box的高度(左图)。再添加一个元素,如果没有因为其对齐方式而超越原有line box的边缘,则不影响line box的高度和baseline的位置(中图)。如果它超出了原来line box的边缘,line box的高度和baseline会再次调整,在这种情况下,我们的前两个方块往下挪了(右图)。

<!-- left mark-up --><spanclass="tall-box text-bottom"></span><spanclass="tall-box text-top"></span> <!-- mark-up in the middle --><spanclass="tall-box text-bottom"></span><spanclass="tall-box text-top"></span><spanclass="tall-box middle"></span> <!-- right mark-up --><spanclass="tall-box text-bottom"></span><spanclass="tall-box text-top"></span><spanclass="tall-box text-100up"></span> <styletype="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>
Nach dem Login kopieren

inline级元素底部的间隙

这是在试图垂直对齐 li 元素时很常见的情况。

<ul>  <liclass="box"></li>  <liclass="box"></li>  <liclass="box"></li></ul> <styletype="text/css">  .box{ display: inline-block;        /* size, color, etc. */ }</style>
Nach dem Login kopieren

正如你所看到的, li 元素坐在baseline上,而baseline下面是留给下标的空间,这导致了空白间隙。解决的办法很简单:将baseline上移一点。例如用 vertical-align: middle; 来对齐 li 元素。

<ul>  <liclass="box middle"></li>  <liclass="box middle"></li>  <liclass="box middle"></li></ul> <styletype="text/css">  .box    { display: inline-block;            /* size, color, etc. */ }   .middle{ vertical-align: middle; }</style>
Nach dem Login kopieren

这种情况不会发生在具有文本内容的inline-block中,因为 内容已经使baseline往上移动了 。

inline级元素之间的水平间隙破坏布局

这主要是inline级元素本身的一个问题,但因为vertical-align的需要它们,所以还是知道比较好。

你在前一个例子的 li 中已经看到了这个间隙,它来自于你的html中inline元素之间的空白符号(空格、回车、换行)。html中多个连续的空白符号会在显示时被合并为一个空格,也就是图中的间隙。如果我们想把两个inline元素水平放置并给它们设置 width: 50% ,就无法跟额外的那个空格放在同一行,所以就会换行破坏布局(左图)。为了消除这个间隙,我们需要去除空白符号,比如使用HTMl注释(右图)。

<!-- left mark-up --><divclass="half">50% wide</div><divclass="half">50% wide... and in next line</div> <!-- right mark-up -->  <divclass="half">50% wide</div><!----><divclass="half">50% wide</div> <styletype="text/css">  .half{    display: inline-block;    width: 50%;  }</style>
Nach dem Login kopieren

vertical-align真相大白

就是这样,当你知道规则那就不复杂了。所以如果 vertical-align 并没有如预期发挥作用,仔细思考下面两点,就能得到结果:

  • line box的baseline和顶部及底部边缘在哪里?
  • inline级元素的baseline和顶部及底部边缘在哪里?

源于 Warrior!博客

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage