vertical-align:middle近似居中和完美居中

很多人想要垂直居中的时候,第一时间就想到了vertical-align:middle,用完之后,疑惑它怎么会无效呢?

——原来vertical-align 是有适用范围的限制的。

因为水平垂直居中直接就包括了垂直居中,本文直接给出水平垂直居中的例子,并说明其中垂直居中的原理。

首先说明vertical-align只能应用于两个情景:

  • 应用于inline/inline-block元素
  • 应用于table-cell元素(其实就是td元素)

而用vertical-align: middle;的效果是:

  • 应用于inline/inline-block元素:元素的中心线和父元素基线上方1/2 x-height处对齐
  • 应用于table-cell元素:单元格填充盒子 相对于 外面的表格行 居中对齐。

本文就不讲table-cell的例子了,因为它实质上是很简明直观的。

然后我们分类以例子来说明:

大小不固定的图片–水平垂直居中

近似居中

先给容器设置line-height维持一定的高度,然后设置图片vertical-align:middle

<style>
.box {
  line-height: 300px;
  text-align: center;
}
.box > img {
  vertical-align: middle;
}
</style>
<body>
  <div class="box">
    <img src="https://cloud.az22c.top/logo.jpg?imageMogr2/thumbnail/x100" alt="图片src要设置!!"/>
  </div>
</body>

而实际上这仍不是完美的垂直居中。因为我们知道,通过设置vertical-align: middle;,图片的中线的位置被确定为从行内基线往上1/2 x-height 的位置

(备注:在英文字体设计中,通常以小写字母"x"的高度作为其他小写字母高度的设计的基础。因此x-height被用于表示一款字体中的小写字母"x"的高度。)

(备注:文字处于的位置高度和line-height之间关系的计算非常麻烦,详见我另一篇文章深入理解文字高度和行高的设置。只需记住绝大多数情况下是:文字"x"的中心高度(即基线往上1/2 x-height处) 比line-height的中线高度要低。有些人称这种现象为"字符下沉")

二分之一 x-height

也就是说,假如现在给img后面添加一个"x"作为文字,图片所处的高度不会变,图片的中线位置就穿过文字"x"的中心,这时,图片的中线的位置实际上是比容器行内的中线位置要低的。所以,此乃近似垂直居中。

另外,这种垂直居中方法还要IE8及以上才能兼容。

备注:

如果在IE7里面使用这个方法的时候,HTML结构要调整一下,例如:

<div class="box">
  <img alt="图片src要设置!!"/><!-- 这里要换行或空格 -->
</div>

可以看做是在图片后面创建一个空白的文本节点。


如果我们进而想要完美居中,可以有两种办法:

  • font-size设为0
  • 添加辅助元素

完美居中–font-size设为0

完美居中:在"近似居中"的基础上,我们给.box加多一个font-size:0 即可。

.box {
  line-height: 300px;
  text-align: center;
  
  font-size: 0;
}
.box > img {
  vertical-align: middle;
}

如果读过深入理解文字高度和行高的设置 这篇文章的原理分析,我们会发现,如果设置字号为0,基线、x-height线等等线都合为一体(因为它们之间的距离为0嘛)。所以1/2 x-height 的位置也变成在行内最中间的那里,图片就完美居中了。

完美居中–添加辅助元素

完美居中:在"近似居中"的基础上,添加一个辅助元素使得其变成完美居中:

首先HTML结构中插入一个 i 元素;

然后CSS步骤有三:

  1. 辅助元素inline-block化
  2. 辅助元素宽度为0,高度为100%
  3. vertical-align:middle
<style>
  .box {
    line-height: 300px;
    text-align: center;
  }
  .box > img {
    vertical-align: middle;
  }
  i {
    display: inline-block;
    height: 100%;
    vertical-align: middle;
  }
</style>
<body>
  <div class="box">
    <img src="https://cloud.az22c.top/logo.jpg?imageMogr2/thumbnail/x100" alt="图片src要设置!!"/>
    <i></i>
  </div>
</body>

备注: 这个辅助元素也可以是伪元素,替代 i 元素即可:

.box:before {
    content:'';
    width: 0%;

    display:inline-block;
    vertical-align:middle;
    height:100%;
}

多行文字–水平垂直居中

近似居中

<style>
.box {
  line-height: 300px;
  text-align: center;
}
.box > .text {
  display: inline-block;
  vertical-align: middle;
  
  line-height: normal;
  text-align: left;
  max-width: 100%;
}
</style>
<body>
<p class="box">
<span class="text">一行文字<br>一行文字<br>一行文字</span><!-- 兼容IE7,这里要换行或空格 -->
</p>
</body>

我们把多行文字的display属性转变为inline-block,就能对它像对上文的img元素做一样的水平垂直居中操作。

总的来说近似居中的步骤有二:

  1. 把多行文字的display水平设置得和图片的一样,即inline-block;
  2. 一般来说,需要重置外部继承的text-align和line-height属性。

这种方法同样还要IE8及以上才能兼容。


如果我们进而想要完美居中,原理同上文的图片,可以有两种办法:

  • 父元素font-size设为0
  • 添加辅助元素

完美居中–font-size设为0(bad)

给父元素设置font-size为0后,由于是文本,会继承父元素的font-size为0,所以又要再重置这多行文字的font-size回正常。特别麻烦,所以对于文字来说,不推荐这种方法。

完美居中–添加辅助元素(good)

原理已经在上文解释过了:

<style>
.box {
  line-height: 300px;
  text-align: center;
}
.box > .text {
  display: inline-block;
  vertical-align: middle;
  
  line-height: normal;
  text-align: left;
  max-width: 100%;
}
i {
  display: inline-block;
  height: 100%;
  vertical-align: middle;
}
</style>
<body>
<p class="box">
<span class="text">一行文字<br>一行文字<br>一行文字</span>
<i></i>
</p>
</body>

后记:

关于line-height的一些补充:

首先文字高度和font-size只有间接的关系,详见 深入理解文字高度和行高的设置 中第一章的内容。

然后,line-height的计算是根据font-size的,详见 深入理解文字高度和行高的设置

然后,对于一个inline或者inline-block元素:

设置vertical-align为百分比的时候,是根据父元素的line-height来计算的。(补充,这个设置值也是为数不多的可以设置为负数的属性设置。)

设置vertical-align为其他值的时候,很多都和父元素的line-height有关系。

而如果你把上面的这些demo对于line-height的设置改为对于height的,vertical-align就无法发挥效果。(因为如果你只设置了height,line-height还是处于默认的状态,而vertical-align参考的还是line-height)

实际上,vertical-align和line-height有关系,和height没有关系。

文章目录
  1. 1. 大小不固定的图片–水平垂直居中
    1. 1.1. 近似居中
    2. 1.2. 完美居中–font-size设为0
    3. 1.3. 完美居中–添加辅助元素
  2. 2. 多行文字–水平垂直居中
    1. 2.1. 近似居中
    2. 2.2. 完美居中–font-size设为0(bad)
    3. 2.3. 完美居中–添加辅助元素(good)
  3. 3. 后记:
|