CSS水平垂直居中方法这么多,总有一款适合你

前言

感觉css开发中,含金量最高的地方就是布局,把元素摆放在特定的位置;而像设置元素宽高,文本对齐,内外边距,阴影渐变,字体与背景色, 内容溢出显示省略号等这些都是so easy的事情。让容器中的元素垂直水平居中,是日常开发一个高频场景。比面试中问到的BFC/IFC, 如何清除浮动要实用的多(笔者做前端开发的这些年,基本上没有用到过浮动)。因此决定把css实现水平垂直居中方式, 整理一下,以备不时之需。现在我们进入主题。

常见的水平垂直居中方法

为了减少文中的重复代码片段,我们先把每种水平垂直居中对齐的公共样式写一下,其中.base-box.base-item分别是容器和需要对齐元素的外观样式。有读者可能会对下面的css代码产生疑问,说你这种写法是Less/Sass才有的嵌套写法,不是原生css的写法。这里要说明一下,最新版的浏览器已经支持一些原来的Less/Sass才支持的语法,不了解的话请参考此文

css 复制代码
.base-box {
  width: 400px;
  height: 200px;
  background-color: greenyellow;

  &+& {
    margin-top: 10px;
  }

  .base-item {
    width: auto;
    height: 100px;
    background-color: red;
  }
}

方案一 flex布局

这种方案可以细分两个版本,一种是在flex容器上设置主轴和交叉轴水平垂直居中属性,另外一种是在flex项目上,设置自身的水平垂直居中属性。

html 复制代码
    <link rel="stylesheet" href="./base.css" />
    <style>
      .flex-center-1 {
        display: flex;
        justify-content: center;
        align-items: center;
      }

      .flex-center-2 {
        display: flex;
        justify-content: center;
        .item {
          align-self: center;
        }
      }
    </style>
    
    <div class="base-box flex-center-1">
      <div class="base-item"></div>
    </div>
    
    <div class="base-box flex-center-2">
      <div class="base-item item"></div>
    </div>

这种对齐方式应用最广, 因为对子元素的宽高没有限制,而且浏览器兼容性也比较好。

效果如下:

方案二 绝对/相对定位+transform方案

先将子元素设置为相对或绝对定位,再将子元素的位置设定为父容器的中心点(即top: 50%left: 50%),这会使子元素的左上角相对于父容器的中心进行定位。

为什么将子元素设置成相对或绝对定位,再设置top: 50%left: 50%,都能让子元素的左上角处于父容器的中心点。这是因为采用相对定位时,top和left设置为百分比,这个百分比是相对于父元素的宽高而言的。采用绝对定位时,由于给父元素设置了相对定位,这是子元素的top和left设置的百分比,也是根据父元素的宽高计算的。如下图所示:

所以这两种情形,都能使用同样的移动效果。接下来通过transform: translate(-50%, -50%)将子元素向左和向上平移自身宽高的一半(translate中的百分比是根据自身的宽高来计算的),这样就能使子元素的中心点与父容器的中心点重合,从而实现水平和垂直居中。

html 复制代码
    <link rel="stylesheet" href="./base.css" />
    <style>
      .transform-center-1 {
        position: relative;
        .item-1 {
          position: absolute;
          top: 50%;
          left: 50%;
          transform: translate(-50%, -50%);
        }
      }
      .transform-center-2 {
        .item-2 {
          position: relative;
          top: 50%;
          left: 50%;
          transform: translate(-50%, -50%);
        }
      }
    </style>
    
    <div class="base-box transform-center-1">
      <div class="base-item item-1"></div>
    </div>
    <div class="base-box transform-center-2">
      <div class="base-item item-2"></div>
    </div>

这种方式不需要预先知道子元素的具体尺寸,因此适用于未知宽高或者动态变化尺寸的元素居中问题。同时,由于transform不会影响布局流(不影响其他元素的位置),所以是一种性能较好的居中解决方案。

方案三 table-cell方案

当一个元素的 display 属性被设置为 table-cell 时,该元素将会表现出如同 <td> 单元格一样的行为特征,设置 vertical-align: middle 在具有 display: table-cell 的元素上,可以使该元素内的内容在垂直方向上居中对齐。水平居中,可以使用给父元素设置text-align:center属性, 子元素设置display:inline-block; 。在CSS中,给父元素添加 text-align: center; 属性意味着父元素内部的行内内容或行内级元素会被水平居中对齐。当子元素设置了 display: inline-block; 属性 ,子元素会变成行内块元素,它遵循行内元素的对齐规则,所以当父元素设置了 text-align: center; 时,子元素就会按照水平居中规则显示。

html 复制代码
    <link rel="stylesheet" href="./base.css" />
    <style>   
     .table-cell-box {
        display: table-cell;
        text-align:center;
        vertical-align: middle;
        .item {
          display: inline-block;
        }
      }
    </style>
    <div class="base-box table-cell-box">
      <div class="base-item item"></div>
    </div>

通过这样的方式,即使子元素内容大小未知,也可以实现内容在容器内的灵活居中对齐。这种方法尤其适用于兼容性要求较高的场景,在 Flexbox 或 Grid 布局还未普及之前的浏览器环境下是一种常用的居中解决方案。

方案四 table布局

这种方案很好理解,设置单元格中内容垂直居中,子元素就会表现为垂直居中,接着设置单元格内容水平居中,将子元素设为内联块元素,子元素在水平方向上就会居中。这样就实现了垂直水平居中。此种方案的缺点显而易见,dom层级过多,但优点是不需要关注子元素的尺寸。

html 复制代码
    <link rel="stylesheet" href="./base.css" />

    <style>
      .table-box {
        vertical-align: middle;
        text-align: center;
        .item {
          display: inline-block;
        }
      }
    </style>
    <table>
      <tr>
        <td class="base-box table-box">
          <div class="base-item item"></div>
        </td>
      </tr>
    </table>

方案五 Grid布局

CSS Grid布局是一种现代布局模式,它提供了一套强大的二维布局系统,使得在网页设计中更容易实现元素的复杂排列,包括轻松地实现容器内单个或多个项目的水平和垂直居中。这里的 .grid-box-1 是需要进行居中布局的容器,.item 是需要居中的子元素。通过 display: grid 将容器转换为网格容器,而 align-items: centerjustify-items: center 两个属性会让容器内的所有直接子元素都将自动地沿行轴(即水平方向)和列轴(即垂直方向)居中对齐。还有一种方式就是单独给子元素设置水平和垂直居中。

html 复制代码
    <link rel="stylesheet" href="./base.css" />
    <style>
      .grid-box-1 {
        display: grid;
        align-items: center;   /* 沿垂直方向(列轴)居中 */
        justify-items: center; /* 沿水平方向(行轴)居中 */
      }
      .grid-box-2 {
        display: grid;
        .item {
          justify-self: center; /* 单独控制水平居中 */
          align-self: center; /* 单独控制垂直居中 */
        }
      }
    </style>
    
    <div class="base-box grid-box-1">
      <div class="base-item item"></div>
    </div>
    
    <div class="base-box grid-box-2">
      <div class="base-item item"></div>
    </div>

grid布局和flex布局十分相像,无论子元素尺寸如何变化,都能让其保持在容器中心位置。但移动端浏览器对Grid布局的支持性不如flex布局那么好。

方案六 writing-mode

CSS的writing-mode属性主要用于改变文本的方向和布局流,可以与其它CSS属性组合使用,间接实现垂直居中效果。当父元素writing-mode设为垂直方向时,原本的水平方向属性(如text-align)将会影响子元素垂直方向的对齐。看起来的效果是子元素在父容器中垂直居中。接着在子元素中在放置一个后代元素.content,设置这个content为内联元素,在子元素中通过文本居中属性,让后代元素水平居中。从而实现后代元素水平垂直的效果。这种方式实现水平居中不太优雅,需要额外添加后代元素,层级较多,好处是可以不必知道后代元素的尺寸,让后代元素居中。

html 复制代码
    <link rel="stylesheet" href="./base.css" />
    <style>
      .writing-mode-box {
        /* 竖排从右到左 */
        writing-mode: vertical-lr;
        text-align: center;
        .item {
          display: inline-block;
          /* 默认的从左到右横排 */
          writing-mode: horizontal-tb;
          text-align: center;
          height: auto;
          width: 100%;
          .content {
            display: inline-block;
            text-align: left;
            background-color: green;
          }
        }
      }
    </style>
     <div class="base-box writing-mode-box">
      <div class="base-item item">
        <div class="content">1111</div>
      </div>
    </div>

方案七 绝对定位+margin:auto

父元素设置相对定位,子元素设置绝对定位,同时设置子元素的top,bottom,left,right位置偏移为0。这使得子元素的边缘与父元素四个方向的边缘相接触,形成一个覆盖整个父元素的盒子。当子元素设置了四个边缘位置偏移为0之后,其margin属性中的auto值就有了可以参考的上下文------即元素自身的尺寸与父元素之间的差距。在水平方向上,margin-leftmargin-right 同时设为 auto 时,浏览器会平均分配元素宽度之外的剩余空间,从而使元素水平居中。在垂直方向上,若元素具有确定高度且同时设置了 topbottom0margin-topmargin-bottomauto的话,根据CSS规范,上下边距值会被设置为相同的正值,能够将子元素推至上下边缘正中间,从而实现垂直居中。

html 复制代码
    <style>
     .absolute-margin-auto {
       position: relative;
       .item {
         position: absolute;
         left: 0;
         top: 0;
         bottom: 0;
         right: 0;
         margin: auto;
       }
     }
   </style>
   <div class="base-box absolute-margin-auto">
     <div class="base-item item"></div>
   </div>

这种对齐方式需要给子元素设置固定的宽高。因为margin: auto在水平或垂直方向上的居中对齐要求子元素的宽高不能为auto。适用范围不如前面三种居中对齐方式那么广泛。

方案八 绝对定位+负margin

此种方式和transform方式比较相似。不同的是transform方式是让浏览器自动计算水平和垂直方向上的具体偏移值,这种方式要自己计算水平垂直方向上的偏移值。 此外需要知道父容器的宽和高,自身也需要设置固定的宽高,使用起来限制比较大。

html 复制代码
    <link rel="stylesheet" href="./base.css" />
    <style>
      .absolute-negative-margin {
        position: relative;
        .item {
          position: absolute;
          left: 50%;
          top: 50%;
          margin-left: -100px;
          margin-top: -50px;
        }
      }
    </style>
    <div class="base-box absolute-negative-margin">
      <div class="base-item item"></div>
    </div>

方案九 绝对定位+calc

当知道容器的宽度和高度时,可以通过父相子绝定位,结合calc()计算出元素的正确偏移量来实现居中。这种方式是把绝对定位+负margin布局方式偏移设置两步合并成一步,此种方式需要知道子元素的尺寸,以及给父元素设置固定尺寸,使用起来有一定的限制性。

html 复制代码
    <link rel="stylesheet" href="./base.css" />

    <style>
      .absolute-calc-box {
        position: relative;
        .item {
          position: absolute;
          left: calc(50% - 100px); /* 减去的宽度为子元素自身宽度的一半 */
          top: calc(50% - 50px);   /* 减去的高度为子元素自身高度的一半 */
        }
      }
    </style>
    <div class="base-box absolute-calc-box">
      <div class="base-item item"></div>
    </div>

方案十 line-height方案

在CSS中,当父元素设置了固定的高度(height)和行高(line-height),并且这两个值相等时,就可以实现单行文本内容的垂直居中对齐。将子元素设置为内联块级元素。子元素的表现效果和单行文本一样,再给父容器设置文本水平居中,子元素就能水平居中。这种方法的局限性比较大,需要知道父元素的高度,还有只对单行内容有效。

html 复制代码
    <link rel="stylesheet" href="./base.css" />
    <style>
      .single-box {
        line-height: 200px;
        text-align: center;

        .item {
          display: inline-block;
          /* 显式设置子元素的行高与自身高度相等 */
          line-height: 100px;
        }
      }
    </style>
    
    <div class="base-box single-box">
      <div class="base-item item">11</div>
    </div>

方案十一 伪元素方案

当有多个行内块级元素(display: inline-block ),并且每个元素都设置了 vertical-align: middle 时,所有元素的垂直对齐是相对于它们所在行框(line box)的基线(baseline)进行的 ,如果各个元素的高度不同,它们各自的"中间"位置可能会有所差异,但都会尽量接近于行框的垂直中点,这个中点是基于行框内所有字体的 (x 字母高度)平均计算得出的。在实际应用中,通过在父元素中创建一个伪元素,并设置其 height: 100%display: inline-block ,这样它会占据父元素的整个高度。接着给每个子元素设置 vertical-align: middle,然后就可以通过 vertical-align: middle 将实际内容元素与这个伪元素垂直对齐,从而达到父容器内各个子元素垂直居中的效果。水平居中比较简单。这种方案可以实现单行多个不同高度的垂直居中。不需要知道每个子元素的尺寸。缺点就是需要额外创建一个伪元素,不如其它对齐方案优雅。

html 复制代码
    <link rel="stylesheet" href="./base.css" />
    <style>
      .single-box {
        text-align: center;
        &::before {
          content: "";
          width: 0;
          height: 100%;         
          display: inline-block;
          vertical-align: middle;
        }

        .item {
          display: inline-block;
          width: 50px;
          vertical-align: middle;
          
          &:nth-of-type(1) {
            height: 40px;
          }
          &:nth-of-type(2) {
            height: 100px;
          }
          &:nth-of-type(3) {
            height: 80px;
          }
        }
      }
    </style>
   
   <div class="base-box pseudo-box">
      <div class="base-item item">11</div>
      <div class="base-item item">22</div>
      <div class="base-item item">33</div>
   </div>

怎么选?

学习了这11种水平垂直居中方案,使用的时候该怎么选呢。从通用性,易用性,兼容性角度来讲,优先要考虑对子元素宽高没有限制的对齐方式,可按如下顺序选择flex > 相对/绝对定位+transform > table-cell > grid,write-modetable这两种方案不推荐使用,一个太偏门,一个不优雅。 中策可供选择的对齐方案是绝对定位+margin:auto > 绝对定位+calc > 绝对定位+负marginline-height伪元素对齐方案,可以作为单行内联块级元素对齐的备选方案。

最后

掌握了文章的水平垂直居中方案,如果你仅想单独实现水平或垂直居中效果,可以把这11个示例中的另一半用不到的居中内容移除。你们没有时间整理这些高频使用的知识点,我来帮你们整理,你只需收藏一下,需要用的时候直接复制示例中的代码片段。每个示例我都验证过效果了,经得起实践的考验。我所知道的css水平垂直居中对齐方案就是这11种,如果你还知道别的方案,欢迎补充。我们留言区见。

相关推荐
BBB努力学习程序设计1 分钟前
CSS3渐变:用代码描绘色彩的流动之美
前端·html
冰暮流星11 分钟前
css之动画
前端·css
jump68035 分钟前
axios
前端
进击的野人37 分钟前
CSS选择器与层叠机制
css·面试
spionbo38 分钟前
前端解构赋值避坑指南基础到高阶深度解析技巧
前端
用户40993225021242 分钟前
Vue响应式声明的API差异、底层原理与常见陷阱你都搞懂了吗
前端·ai编程·trae
开发者小天44 分钟前
React中的componentWillUnmount 使用
前端·javascript·vue.js·react.js
永远的个初学者1 小时前
图片优化 上传图片压缩 npm包支持vue(react)框架开源插件 支持在线与本地
前端·vue.js·react.js
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ1 小时前
npm i / npm install 卡死不动解决方法
前端·npm·node.js
Kratzdisteln1 小时前
【Cursor _RubicsCube Diary 1】Node.js;npm;Vite
前端·npm·node.js