转载

把简单做好也不简单-css水平垂直居中

44年前我们把人送上月球,但在CSS中我们仍然不能很好实现水平垂直居中。

水平垂直居中有相同点也有不同点,接下来讨论常见的方式。

如无特殊说明,以下示例html均为:

<div class="md-warp">
  <spanclass="md-main"></span>
</div>

基础样式为:

.md-warp{
  width: 400px;
  height: 300px;
  max-width: 100%;
  border: 1px solid #000;
}
.md-main{
  display: block;
  width: 100px;
  height: 100px;
  background: #f00;
}

水平居中

margin法

需要满足三个条件:

  • 元素定宽
  • 元素为块级元素或行内元素设置 display:block
  • 元素的 margin-leftmargin-right 都必须设置为auto
    三个条件缺一不可。

demo:

.md-main{
  margin: 0 auto;
}

定位法

需要满足三个条件:

  • 元素定宽
  • 元素绝对定位,并设置 left:50%
  • 元素负左边距 margin-left 为宽度的一半

demo1:

.md-warp{
  position: relative;
}
.md-main{
  position: absolute;
  left: 50%;
  margin-left: -50px;
}

有些时候我们的元素宽度可能不是固定的,不用担心,我们依然可以使用定位法实现水平居中,此时需要用到css3中的 transform 属性中的 translate ,可以使元素移动时相对于自身的宽度和高度。

需要注意,这种方法需要IE9+才可以实现。

demo2

.md-warp{
  position: relative;
}
// 注意此时md-main不设置width为100px
.md-main{
  position: absolute;
  left: 50%;
  -webkit-transform: translate(-50%,0);
  -ms-transform: translate(-50%,0);
  -o-transform: translate(-50%,0);
  transform: translate(-50%,0);
}

不定宽

文字水平居中

对于单行文字来说,直接使用 text-align: center 即可。

多行文字可以看作一个块级元素参考margin法和定位法。

垂直居中

定位法

和水平居中类似,只是把 left:50% 换成了 top:50% ,负边距和 transform 属性进行对应更改即可。

优点:能在各浏览器下工作,结构简单明了,不需增加额外的标签。

demo1:

.md-warp{
  position: relative;
}
.md-main{
  position: absolute;
  /* 核心 */
  top: 50%;
  margin-top: -50px;
}

运用css3中的clac()属性能简化部分代码:

.md-warp{
  position: relative;
}
.md-main{
  position: absolute;
  /* 核心 */
  top: calc(50% - 50px);
}

demo2

.md-warp{
  position: relative;
}
.md-main{
  position: absolute;
  top: 50%;
  // 注意此时md-main不设置height为100px
  -webkit-transform: translate(0,-50%);
  -ms-transform: translate(0,-50%);
  -o-transform: translate(0,-50%);
  transform: translate(0,-50%);
}

不定高

单行文本垂直居中

需要满足两个条件:

  • 元素内容是单行,并且其高度是固定不变的。
  • 将其 line-height 设置成和 height 的值一样
<div><span>这是一段文字</span></div>
div{
  width: 400px;
  height: 300px;
  border: 1px solid #000;
}
span{
  line-height: 300px;
}

这是一段文字

视窗单位的解决办法(垂直居中)

如果想避免使用绝对定位,我们仍然可以利用 translate() 方法,其值刚好是元宽度和高度的一半。但是,我们如何不使用top和left将元素从top和left移动50%的偏移量呢?

首先想到的是给margin属性一个百分数,像这样:

.md-main{
  margin: 50% auto 0;
  transform: translateY(-50%);
}

效果如下所示:

我们发现并没有出现预想的结果,这是因为 margin 的百分比计算是相对于父容器的 width 来计算的,甚至包括 margin-topmargin-bottom

我们如果仍然想让元素在视窗中居中,还是有救的。CSS3定义了一种新的单位,称为相对视窗长度单位。

以下摘自w3cplus

vw 是相对于视窗的宽度。与你预期刚好相反, 1vw 相当于视窗宽度的 1% ,而不是 100%
vw 相似的是, 1vh 相当于视窗高度的 1%
如果视窗的宽度小于高度, 1vmin 等于 1vw ,反之,如果视窗宽度大于高度, 1vmin 等于 1vh

如果视窗的宽度大于高度, 1vmax 等于 1vw ,反之,如果视窗宽度小于高度, 1vmax 等于 1vh

在上个示例的基础上,我们需要给 margin 设置 vh 单位:

.md-warp{
  position: relative;
}
.md-main{
  position: absolute;
  margin: 50vh auto 0;
  transform: translateY(-50%);
}

注意:这种方法最大的局限是只能适用于元素在 视窗 中垂直居中,如果是在局部的某个地方就无能为力了。

Flexbox的解决方案

如果不考虑浏览器的兼容性,Flexbox无疑是最好的解决方案,因为它的出现就是为了解决这样的问题。

完成这项工作只需要两个样式,在需要水平垂直居中的父元素上设置 display:flex 和在水平垂直居中的元素上设置 margin:auto

.md-warp{
  display:flex;
}
.md-main{
  margin: auto;
}

Flexbox的实现文本的水平垂直居中同样很简单。

.md-warp{
  display:flex;
}
.md-main{
  display: flex;
  align-items: center;
  justify-content: center;
  margin: auto;
}

我是字啊

结语

  • 绝对定位通常不是一个很好的选择,因为它对整体的布局影响相当的大。
  • 在一些浏览器中,可能会导致元素出现略微的模糊,那是因为元素有可能被放置在半个像素位置上。我们可以通过 transform-style:preserve-3d 来解决,但这是一个Hack手段,不能保证它不会过时。

以上各种方法稍加组合即可同时实现水平和垂直居中,这些就是平时用到较多的一些居中的方法,希望大家看完之后有收获:)

原文  http://xdlrt.github.io/2016/12/15/2016-03-20/
正文到此结束
Loading...