CSS“奇淫巧技”之垂直居中

743 阅读4分钟

又是这个老生常谈的问题,请问你如何实现水平垂直居中?这个问题在前端开发者的实际工作中和面试中遇到过无数次,相信你也有自己的一套写法,但究竟哪套方案是更好的呢,本篇文章带你看看CSS实现垂直居中的一些“奇淫巧技”

引言

说起来啼笑皆非,2013年以前,垂直居中成了CSS领域中的传说。 垂直居中,一个及其常见的需求,一个看起来相当简单的需求;在实践中确实耗费心神,百般调试,尤其是涉及尺寸不固定的元素时;过了这么久,前端猿们琢磨出了各种各样的方法........我们一起来“踩坑”


子元素定宽定高

这种的比较简单,我们用如下方式就可以轻松的将子元素水平垂直居中:

.child{
      width: 200px;
      height: 100px;
      position: absolute;
      top: 50%;
      left: 50%;
      margin: -50px -100px;
      background-color: bisque;
  }

这是很早的一种垂直居中的方法,必须要给子元素固定的宽高,这段css代码是这样处理的:

  1. 把.child元素的左上角先放置在视口(或最近的具有相对定位的祖先元素)的正中心
  2. 利用负外边距将元素向上向左移动,移动的距离是自身宽高的一半

这其实就实现了把元素的正中心放置在视口的正中心,这段冗长的CSS代码还可以做下优化,利用强大的calc() 函数优化掉一行代码:

.child{
   width: 200px;
   height: 100px;
   position: absolute;
   top: calc(50% - 50px);
   left: calc(50% - 100px);
   /* margin: -50px -100px; */
   background-color: bisque;
}

效果如下图:

在实际的开发中,这种需求可能并不算多,更多的是不定宽高的元素水平垂直居中,那么这种方法就失去效果了.......


子元素不定宽高

  • 表格布局法

这是比较传统的一种布局方式,它需要用到一些冗余的html元素, 这里不做过多介绍

推荐指数:☆☆

.parent{
      display: table;
      margin: 100px auto;
      width: 400px;
      height: 300px;
      background-color: aquamarine;
    }
.child{
      display: table-cell;
      text-align: center;
      vertical-align: middle;
    }

  • 利用伪元素

个人看来这种的方式更像是一种hack手段。 推荐指数:☆☆

.parent{
      margin: 100px auto;
      width: 400px;
      height: 300px;
      background-color: aquamarine;
      text-align: center;
    }
    .parent::before{
      content: '';
      display: inline-block;
      height: 100%;
      vertical-align: middle;
    }
    .child{
      display: inline-block;
      vertical-align: middle;
    }

  • 使用translate()变形函数

当我们在translate()中使用百分比值时,是以这个元素自己的高度和宽度为基准进行换算和移动的,所以我们使用基于百分比的变形属性来对元素进行偏移,就不需要像定宽定高的元素居中那样把元素宽高写死了!

推荐指数:☆☆☆☆

.parent{
      position: relative;
      margin: 100px auto;
      width: 400px;
      height: 300px;
      background-color: aquamarine;
    }
.child{
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      background-color: bisque;
    }

我们看下效果:

现在我们已经完美实现水平垂直居中了,但用过这个方法的你一定遇见过一些坑,我们一起踩一下:

  • 有时候你可能不能使用绝对定位,因为它可能会影响你整体的布局
  • 如果你要居中的子元素高度比视口的高度还高,那它的顶部会被视口截掉,当然也有类似hack的手段去解决
  • 这种也是比较常见的,在某些浏览器中会导致元素的显示有些模糊,尤其在移动端比较常见。这个问题可以用transform-style:preserve-3d; 来修复,这种修复手段也相当于一种hack。

这个方法起源于2013年Stack Overflow的用户,他回答了“如何使用CSS3实现垂直居中”这个问题。


  • 基于Flexbox的解决方案

推荐指数:☆☆☆☆☆

flexbox是专门针对这类需求设计的,上面所说的一些方法可能在浏览器的支持程度上稍微好些,但现在浏览器对flexbox的支持度也是不错的。我们只需要少量的代码就可以实现:

  1. 给父元素设置display:flex;
  2. 给元素设置margin:auto;
.parent{
    display: flex;
    background-color: aquamarine;
}
.child{
    margin: auto;
    background-color: bisque;
}

完美~~~

当我们使用flexbox时,margin:auto;不仅仅是水平方向将元素居中,在垂直方向也是如此

使用flexbox还可以将文字水平垂直居中!一起来看下吧~~

<div class="txt">
  前端搬运工Elvis Yang
</div>
.txt {
  width: 300px;
  height: 100px;
  display: flex;
  align-items: center;
  justify-content: center;
}


本文至此就结束了,希望可以正在切图的你有所帮助,能选择到适合你的实现水平垂直居中的方法~~

参考书籍《CSS揭秘》