# 水平居中

# 1. 使用 inline-block 或者 inline 和 text-align 实现

需要居中的元素为常规流中 inline / inline-block 元素, 可以简单理解为是行内元素。

.parent {
  text-align: center;
}
.child {
  display: inline-block;
  /* or */
  /* display: inline; */
}

优点:兼容性好; 不足:需要同时设置子元素和父元素

# 2. 使用 margin:0 auto 来实现

子元素需要是定宽块状元素, 设置子元素的宽度之后设置 margin 自动。IE6 下需在父元素上设置 text-align: center。

.wrapper {
  /* IE 6 下设置即可 */
  text-align: center;
}
.child {
  width: 200px;
  margin: 0 auto;
}

优点:兼容性好 缺点: 需要指定宽度

# 3. 使用 table 实现

不定宽块状元素

.child {
  display: table;
  margin: 0 auto;
}

优点: 只需要对自身进行设置 不足: IE6,7 需要调整结构

# 4. 使用绝对定位实现

  1. 不定宽块状元素 absolute + translate
.parent {
  position: relative;
}
/*或者使用 margin-left 的负值为盒子宽度的一半也可以实现,不过这样就必须知道盒子的宽度,但兼容性好*/
.child {
  position: absolute;
  left: 50%;
  transform: translate(-50%);
  /* transform: translateX(-50%); */
}

不足:兼容性差,IE9 及以上可用

  1. 定宽元素。 absolute + margin
.wrapper {
  width: 80%;
  height: 500px;
  background: #888;

  position: relative;
}
.center {
  width: 500px;
  position: absolute;
  left: 50%;
  margin-left: -250px;

  background-color: orange;
}
<div class="wrapper">
  <div class="center">
    如果元素 position: absolute; 那么 0)设置父元素 position: relative 1)为元素设置宽度,2)偏移量设置为
    50%,3)偏移方向外边距设置为元素宽度一半乘以-1
  </div>
</div>
div {
  position: relative; /* 相对定位或绝对定位均可 */
  width: 500px;
  height: 300px;
  top: 50%;
  left: 50%;
  margin: -150px 0 0 -250px; /* 外边距为自身宽高的一半 */
  background-color: pink; /* 方便看效果 */
}
  1. 定宽元素。 absolute + margin
    1. 为元素设置宽度
    2. 设置左右偏移量都为 0
    3. 设置左右外边距都为 auto
body {
  background: #ddd;
  position: relative;
}
.content {
  width: 800px;

  position: absolute;
  margin: 0 auto;
  left: 0;
  right: 0;

  background-color: purple;
}
<div class="content">
  aaaaaa aaaaaa a a a a a a a a
</div>
  1. 定宽元素。 relative + margin
.wrapper {
  width: 80%;
  height: 500px;
  background: #888;
}
.center {
  width: 500px;
  position: relative;
  left: 50%;
  margin-left: -250px;

  background-color: orange;
}
<div class="wrapper">
  <div class="center">
    如果元素positon: relative。 那么 1)为元素设置宽度,2)偏移量设置为 50%,3)偏移方向外边距设置为元素宽度一半乘以-1
  </div>
</div>

# 5. 实用 flex 布局实现

实际使用时应考虑兼容性

/*第一种方法*/
.parent {
  display: flex;
  justify-content: center;
}
/*第二种方法*/
.parent {
  display: flex;
}
.child {
  margin: 0 auto;
}

缺点:兼容性差,如果进行大面积的布局可能会影响效率

# 6. 定宽浮动元素 relative + margin-left

  1. 为元素设置宽度
  2. position: relative;
  3. 浮动方向偏移量(left 或者 right)设置为 50%
  4. 浮动方向上的 margin 设置为元素宽度一半乘以-1
<div class="content">
  aaaaaa aaaaaa a a a a a a a a
</div>
body {
  background: #ddd;
}
.content {
  width: 500px; /* 1 */
  float: left;

  position: relative; /* 2 */
  left: 50%; /* 3 */
  margin-left: -250px; /* 4 */

  background-color: purple;
}

# 垂直居中

  • absolute + 负 margin
  • absolute + translate
  • flex
  • table-cell + vertical-align

# 1. 绝对定位和负边距 margin

这种方式比较好理解,兼容性也很好,缺点是需要知道子元素的宽高。 定高:marginposition + margin(负值)

/* 定高方案1 */
.center {
  height: 100px;
  margin: 50px 0;
}
/* 定高方案2 */
.center {
  height: 100px;
  position: absolute;
  top: 50%;
  margin-top: -25px;
}

# 2. 绝对定位和 0

这种方法兼容性也很好,缺点是需要知道子元素的宽高

.box4 span {
  width: 50%;
  height: 50%;
  background: #000;
  overflow: auto;
  margin: auto;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
}

# 3. vertical-align

vertical-align 称之为 "inline-block 依赖型元素",也就是说,只有一个元素属于 inline 或是 inline-block(table-cell 也可以理解为 inline-block 水平)水平,其身上的 vertical-align 属性才会起作用。

在使用 vertical-align 的时候,由于对齐的基线是用行高的基线作为标记,故需要设置 line-height 或设置 display:table-cell;

/*第一种方法*/
.parent {
  display: table-cell;
  vertical-align: middle;
  height: 20px;
}
/*第二种方法*/
.parent {
  display: inline-block;
  vertical-align: middle;
  line-height: 20px;
}

其实跟上面的一样,IFC + vertical-align:middle

/* 设置 inline-block 则会在外层产生 IFC,高度设为 100% 撑开 wrap 的高度 */
.wrap::before {
  content: '';
  height: 100%;
  display: inline-block;
  vertical-align: middle;
}
.wrap {
  text-align: center;
}
.center {
  display: inline-block;
  vertical-align: middle;
}

# 4. 实用绝对定位

  1. 使用绝对定位和 translate 移动(位移)的方式 (不需要知道元素的宽高)。使用 css3 新增的 transform,transform 的 translate 属性也可以设置百分比,其是相对于自身的宽和高,所以可以讲 translate 设置为-50%,就可以做到居中了。

这种方法兼容性依赖 translate2d 的兼容性。

.parent {
  position: relative;
}
.child {
  position: absolute;
  top: 50%;
  transform: translate(0, -50%);
}
  1. 使用绝对定位和 calc 具体计算出偏移量(需要知道元素的宽高)。这种方法兼容性依赖 calc 的兼容性,缺点是需要知道子元素的宽高。
.center {
  width: 18em;
  height: 10em;
  position: absolute;
  top: calc(50% - 5em);
  left: calc(50% - 9em);
}
<div class="center">
  要求原生有固定的宽高。<br />
  position: absolute;<br />
  top 为 calc(50% 剪 一半高) <br />
  left 为 calc(50% 剪 一半宽)
</div>
  1. 使用绝对定位和负 margin 具体计算出边距的值 (需要知道宽高)。已知高度的块级子元素,采用绝对定位和负边距
.center {
  width: 18em;
  height: 10em;
  position: absolute;
  top: 50%;
  left: 50%;
  margin-left: -9rem;
  margin-top: -5rem;
}
<div class="center">
  要求原生有固定的宽高。<br />
  position: absolute;<br />
  top和left 为 50%;<br />
  margin上为高的一半<br />
  margin左为宽的一半<br />
</div>
.container {
  position: relative;
}
.vertical {
  height: 300px; /*子元素高度*/
  position: absolute;
  top: 50%; /*父元素高度50%*/
  margin-top: -150px; /*自身高度一半*/
}

# 5. 实用 flex 实现

目前在移动端已经完全可以使用 flex 了,PC 端需要看自己业务的兼容性情况.

  1. 直接使用 flex 的两个属性水平、垂直居中一步到位
.parent {
  display: flex;
  /* 水平居中 */
  justify-content: center;
  /* 垂直居中 */
  align-items: center;
}
  1. 父元素 flex 定位,子元素定宽并设置 margin auto
.wrapper {
  width: 1000px;
  height: 600px;
  background: #999;

  display: flex;
}
.center {
  width: 18em;
  height: 10em;
  text-align: center;
  background-color: orange;
  color: #fff;

  margin: auto;
}
<div class="wrapper">
  <div class="center">
    使用flex居中<br />
    父元素 display: flex; <br />
    居中块: margin: auto;
  </div>
</div>

# 6. 使用 translate 和 vh 单位整个窗口垂直居中

    .wrapper {
      overflow: hidden;
      width: 100%
      height: 500px;
      background: #999;
    }

    .center {
      width: 18em;
      height: 10em;
      text-align: center;
      background-color: orange;
      color: #fff;
      margin: 50vh auto;
      transform: translateY(-50%);
    }
<div class="wrapper">
  <div class="center">
    基于视口的垂直居中<br />
    不要求原生有固定的宽高。<br />
    但是这种居中是在整个页面窗口内居中,不是基于父元素<br />
  </div>
</div>

# 7. 单行文本

  1. line-height 设置成和 height 值
.vertical {
  height: 100px;
  line-height: 100px;
}
  1. 需要居中元素为单行文本,为包含文本的元素设置大于font-sizeline-height
<p class="text">center text</p>
.text {
  line-height: 200px;
}
  1. vertical-align

需要是 inline-block 之类的元素

/* 把此元素放置在父元素的中部 */
vertical-align: middle;

# 8. 未知高度的块级父子元素居中,模拟表格布局

兼容性也还不错. 缺点:IE67 不兼容,父级 overflow:hidden 失效

.container {
  display: table;
}
.content {
  display: table-cell;
  vertical-align: middle;
}

# 9. display:-webkit-box

.box9 {
  display: -webkit-box;
  -webkit-box-pack: center;
  -webkit-box-align: center;
  -webkit-box-orient: vertical;
  text-align: center;
}

# 10. display:-webkit-box + div 块清除浮动

.floater {
  float: left;
  height: 50%;
  margin-bottom: -120px;
}
.content {
  clear: both;
  height: 240px;
  position: relative;
}
<div class="floater"></div>
<div class="content">Content here</div>

# 11. writing-mode

简单来说 writing-mode 可以改变文字的显示方向,比如可以通过 writing-mode 让文字的显示变为垂直方向

<div class="div1">水平方向</div>
<div class="div2">垂直方向</div>
.div2 {
  writing-mode: vertical-lr;
}

显示效果如下:

水平方向
垂
直
方
向

更神奇的是所有水平方向上的 css 属性,都会变为垂直方向上的属性,比如text-align,通过writing-modetext-align就可以做到水平和垂直方向的居中了,只不过要稍微麻烦一点

<div class="wp">
  <div class="wp-inner">
    <div class="box">123123</div>
  </div>
</div>
/* 此处引用上面的公共代码 */ /* 此处引用上面的公共代码 */
/* 定位代码 */
.wp {
  writing-mode: vertical-lr;
  text-align: center;
}
.wp-inner {
  writing-mode: horizontal-tb;
  display: inline-block;
  text-align: center;
  width: 100%;
}
.box {
  display: inline-block;
  margin: auto;
  text-align: left;
}

这种方法实现起来和理解起来都稍微有些复杂

# 12. grid

css 新出的网格布局,由于兼容性不太好,一直没太关注,通过 grid 也可以实现水平垂直居中

<div class="wp">
  <div class="box">123123</div>
</div>
.wp {
  display: grid;
}
.box {
  align-self: center;
  justify-self: center;
}

代码量也很少,但兼容性不如 flex,不推荐使用

# 总结

下面对比下各个方式的优缺点,肯定又双叒叕该有同学说回字的写法了,简单总结下

  • PC 端有兼容性要求,宽高固定,推荐 absolute + 负 margin
  • PC 端有兼容要求,宽高不固定,推荐 css-table
  • PC 端无兼容性要求,推荐 flex
  • 移动端推荐使用 flex

**小贴士:**关于 flex 的兼容性决方案,请看这里《移动端 flex 布局实战 (opens new window)

方法 居中元素定宽高固定 PC 兼容性 移动端兼容性
absolute + 负 margin ie6+, chrome4+, firefox2+ 安卓 2.3+, iOS6+
absolute + margin auto ie6+, chrome4+, firefox2+ 安卓 2.3+, iOS6+
absolute + calc ie9+, chrome19+, firefox4+ 安卓 4.4+, iOS6+
absolute + transform ie9+, chrome4+, firefox3.5+ 安卓 3+, iOS6+
writing-mode ie6+, chrome4+, firefox3.5+ 安卓 2.3+, iOS5.1+
line-height ie6+, chrome4+, firefox2+ 安卓 2.3+, iOS6+
table ie6+, chrome4+, firefox2+ 安卓 2.3+, iOS6+
css-table ie8+, chrome4+, firefox2+ 安卓 2.3+, iOS6+
flex ie10+, chrome4+, firefox2+ 安卓 2.3+, iOS6+
grid ie10+, chrome57+, firefox52+ 安卓 6+, iOS10.3+

# 水平垂直居中

# 1. 利用 vertical-align,text-align,inline-block 实现

.parent {
  display: table-cell;
  vertical-align: middle;
  text-align: center;
}
.child {
  display: inline-block;
}

# 2. 利用绝对定位实现

.parent {
  position: relative;
}
.child {
  position: absolute;
  top: 50%;
  left: 50%;
  /* child 元素 x y 均移动 50% */
  transform: translate(-50%, -50%);
}
# 让绝对定位的 div 居中
div {
  position: absolute;
  width: 300px;
  height: 300px;
  margin: auto;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background-color: pink; /* 方便看效果 */
}

# 3. 利用 flex 实现

.parent {
  display: flex;
  justify-content: center;
  align-items: center;
}