css实现居中的几种方式

164 阅读7分钟

在实现居中之前我们肯定要先看一下当前元素的display属性,是块级元素还是内联元素,因为块级元素和内联元素的水平居中方式是不一样的,下面我们就按照这两类进行元素分类,按照水平居中和垂直居中来进行介绍。

  1. 水平居中

    1)内联元素,也包括文本

    • text-align: center;

    2) 块级元素

    • 设置margin: 0 auto;
    • 绝对定位:position: absolute; left: 50%; 设置外边距margin-left回退
    • 绝对定位:position: absolute; left: 50%; 设置transform回退
    • 弹性布局:flex; align-items: center;
  2. 垂直居中

    1)内联元素(display: inline-block):vertical-align: middle;

    2)单行文本:line-height = height;

    3)块级元素

    • 父元素display: table; 子元素display: table-cell; verticle-align: middle;
    • 绝对定位:position: absolute; top: 50%; 设置外边距margin-top回退
    • 绝对定位:position: absolute; top: 50%; 设置transform回退
    • 弹性布局:flex; justify-content: center;

水平居中

text-align

tetx-align属性指定块级元素中的内联元素(包括display: inline-block;)的对齐方式。只要设置了该属性值,那么里面的内联元素就会水平对齐,而且这个属性还可以级联,在父元素上使用text-align,其下的所有的块级子元素(包括:display: inline-block;)都具有该属性。

让内联元素水平居中

<div class='test-wrap'>
  <!-- 居中布局 -->
  <span class="inline-box">这是一行单行文本</span>
</div>
.test-wrap {
  text-align: center;
  .inline-box {
    border: 1px solid lightgreen;
  }
}

效果如下:

文本内容水平居中

<div class='test-wrap'>
  这是一段很长很长的文本
</div>
.test-wrap {
  text-align: center;
}

margin

margin这个主要是用来控制块级元素水平居中的。因为块级元素默认是占满一整行的,如果该块级元素不设置宽度的话,那么width: auto;但是在浏览器中的表现是占满一整行的,其实也就是100%。如果该元素有指定宽度。那么设置 margin:0 auto; 就意味着水平方向上的外边距都是auto, 浏览器上的表现就是左右外边距是一样的,也就是水平居中了。

<div class='test-wrap'>
  <!-- 居中布局 -->
  <div class="inline-box">
    这是一段块级元素内的文本内容
  </div>
</div>
.test-wrap {
  .inline-box {
    border: 1px solid lightgreen;
    width: 100px;
    height: 100px;
    margin: 0 auto;
  }
}

绝对定位

绝对定位实现水平居中的原理很简单,因为绝对定位是脱离文档流的,其实就是根据父元素,让子元素定位在那个水平居中的位置。 绝对定位实现水平居中的方式是一样的,只是最后回退的时候采用的方式不同

position + margin

<div class='test-wrap'>
  <!-- 居中布局 -->
  <div class="inline-box">
    这是一段块级元素内的文本内容
  </div>
</div>
.test-wrap {
  position: relative;
  .inline-box {
    border: 1px solid lightgreen;
    width: 100px;
    height: 100px;
    position: absolute;
    left: 50%;
    margin-left: -50px;
  }
}

效果如下: 这种方式必须知道元素的宽度

position + transform

<div class='test-wrap'>
  <!-- 居中布局 -->
  <div class="inline-box">
    这是一段块级元素内的文本内容
  </div>
</div>
.test-wrap {
  position: relative;
  .inline-box {
    border: 1px solid lightgreen;
    width: 100px;
    height: 100px;
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
  }
}

效果如下: 这种方式元素的宽度是不是固定值都不影响

弹性布局

弹性布局是最简单的实现水平居中的方式,也是最适合用来做居中的布局了,而且现在基本上主流浏览器都能支持flex属性了,如果项目对浏览器有特殊要求,不支持flex布局的,我们可以针对性地进行兼容处理。而且对于内联元素也可以使用flex布局进行水平居中(display: inline-flex;)

<div class='test-wrap'>
  <!-- 居中布局 -->
  <div class="inline-box">
    这是一段块级元素内的文本内容
  </div>
</div>
.test-wrap {
  display: flex;
  justify-content: center;
  .inline-box {
    border: 1px solid lightgreen;
    width: 100px;
    height: 100px;
  }
}

效果如下:

垂直居中

vertical-align

vertical-align属性定义行内元素的基线相对于该元素所在行的基线的垂直对齐。

其中行内元素的基线并不是固定不变的。主要分为以下几种情况:

  • 在文本类的内联元素中,基线就是字符x的下边缘位置
  • 在img元素中基线就是下边缘
  • 在inline-block元素中,也分为两种情况:
    • 如果该元素中有内联元素,基线就是最后一行内联元素的基线
    • 如果该元素内没有内联元素或者overflow不是visible,其基线就是margin的下边缘

vertical-align是针对行内元素的基线相对于该元素所在行的基线的垂直对齐,因此要想实现元素在父元素中垂直对齐,该元素必须是行内元素,否则就不生效。具体实现过程如下: 在父元素中添加一个文本x, 方便看出父元素的基线

<div class='test-wrap'>
  <!-- 居中布局 -->
  x<span class="inline-box">我是内联元素文本内容</span>
</div>
.test-wrap {
  width: 400px;
  height: 500px;
  background-color: aliceblue;
  .inline-box {
    border: 1px solid lightgreen;
    vertical-align: middle;
    display: inline-block;
    width: 200px;
    height: 100px;
    line-height: 100px;
  }
}

效果如下: image.png

此时行内元素确实是和x(基线)垂直对齐,但是我们想要的效果是行内元素在父元素中垂直对齐,因此需要在父元素中设置一个line-height = height。这样x就是在父元素中垂直对齐,行内元素也就在父元素中垂直居中啦。

<div class='test-wrap'>
  <!-- 居中布局 -->
  x<span class="inline-box">我是内联元素文本内容</span>
</div>
.test-wrap {
  width: 400px;
  height: 500px;
  background-color: aliceblue;
  line-height: 500px;
  .inline-box {
    border: 1px solid lightgreen;
    vertical-align: middle;
    display: inline-block;
    width: 200px;
    height: 100px;
    line-height: 100px;
  }
}

效果如下: image.png

line-height

line-height设置垂直居中只针对单行文本垂直居中于父容器,其他的情况都不使用。这个属性我们用的很多,但是从来都没有去考虑它的原理。之所以单行文本可以这样使用是因为line-height: 表示两个文本基线之间的距离,也等于文本的高度+上间距+下间距。行高-字体的大小得到的差值就是被平均分成两部分作为文本的间距。当行高和容器的高度相等就能实现垂直居中了

<span class="inline-box">我是内联元素文本内容</span>
.inline-box {
  border: 1px solid lightgreen;
  display: inline-block;
  width: 200px;
  height: 100px;
  line-height: 100px;
}

效果如下 image.png

table布局

display:table-cell;会使元素表现的类似一个表格中的单元格td,利用这个特性可以实现文字的垂直居中效果。

<div class='test-wrap'>
  <!-- 居中布局 -->
  <span class="inline-box">我是内联元素文本内容</span>
</div>
.test-wrap {
  width: 400px;
  height: 500px;
  background-color: aliceblue;
  display: table;
  .inline-box {
    border: 1px solid lightgreen;
    display: table-cell;
  }
}

效果如下: image.png

只要设置了display: table-cell属性它的vertical-align舒心默认就是middle, 所以这个属性设不设置都无所谓。

让行内元素或块级元素在父容器中垂直居中

<div class='test-wrap'>
  <!-- 居中布局 -->
  <span class="inline-box">我是内联元素文本内容</span>
</div>
.test-wrap {
  width: 400px;
  height: 500px;
  background-color: aliceblue;
  display: table-cell;
  .inline-box {
    border: 1px solid lightgreen;
  }
}

效果如下: image.png

这种方式可以实现垂直居中,但是有个问题就是容器元素必须是display: table-cell;否则就不生效。但是很多时候我们的容器元素就是一个块级元素,必须单独占一行,那么这种方式就不行了。

绝对定位

绝对定位实现垂直居中的方式和实现水平居中的原理是一样的,只是最后定位的时候位置不一样而已。

position + margin

<div class='test-wrap'>
  <!-- 居中布局 -->
  <div class="inline-box">我是内联元素文本内容</div>
</div>
.test-wrap {
  width: 400px;
  height: 500px;
  background-color: aliceblue;
  position: relative;
  .inline-box {
    height: 100px;
    border: 1px solid lightgreen;
    position: absolute;
    top: 50%;
    margin-top: -50px;
  }
}

position + transform

<div class='test-wrap'>
  <!-- 居中布局 -->
  <div class="inline-box">我是内联元素文本内容</div>
</div>
.test-wrap {
  width: 400px;
  height: 500px;
  background-color: aliceblue;
  position: relative;
  .inline-box {
    height: 100px;
    border: 1px solid lightgreen;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
  }
}

弹性布局

弹性布局用来实现这种居中布局非常简单。

<div class='test-wrap'>
  <!-- 居中布局 -->
  <div class="inline-box">我是内联元素文本内容</div>
</div>
.test-wrap {
  width: 400px;
  height: 500px;
  background-color: aliceblue;
  display: flex;
  align-items: center;
  .inline-box {
    height: 100px;
    border: 1px solid lightgreen;
  }
}

小结

在实现这种居中布局的时候,还是首选弹性布局的方式,因为弹性布局的诞生就是用来实现布局的。其他的布局方式或多或少地在某些场景都会存在些问题。