美文网首页让前端飞前端开发
CSS中优雅地实现垂直水平居中

CSS中优雅地实现垂直水平居中

作者: 番茄沙司a | 来源:发表于2018-11-15 21:22 被阅读2次

    前言

    在CSS中对元素进行水平居中是非常简单的。

    块级元素水平居中:对其自身设置 margin:0 auto
    这里上下的外边距随便设置,不一定是0,左右要自适应即可。
    行内元素水平居中:对其父元素设置 text-align: center

    然而对一个元素进行垂直居中,就令人头皮发麻,原因是:

    • 它是极其常见的需求
    • 理论上,实现十分简单
    • 实践中,往往充满陷阱,当涉及尺寸不固定的元素时尤其如此。

    下面就来探索一下垂直居中的解决方案。

    行内元素垂直居中:设置 line-heightheight 一样高。

    垂直水平居中的解决方案

    结构代码如下所示:

    <main>
        <h1>Am I centered yet?</h1>
        <p>Look, I'm centered.</p>
    </main>
    

    1. 基于绝对定位的解决方案

    利用绝对定位 + margin 反向偏移

    早期的垂直居中方法,要求元素具有固定宽和高。

       main {
           position: absolute;
           top: 50%;
           left: 50%;
           margin-top: -3em;/* (height + padding)/2 */
           marigin-left:-9em;/* (width + padding)/2 */
           width: 18em;
           height: 6em;
       }
    

    实现过程:

    1. 把该元素左上角放置在视口的正中心
    2. 将元素的正中心放置在视口的正中心 - 利用负外边距把它向左、向上移动(移动距离相当于它自身宽高的一半)

    利用绝对定位 + margin:auto

    main {
      position: absolute;
      margin: auto;/*注意不要遗漏margin自适应*/
      bottom: 0;
      top: 0;
      left: 0;
      right: 0;
    }
    

    实现原理:利用css定位规则,让css根据定位计算margin值,用 CSS hack 的方式实现居中。

    居中块的尺寸需要可控,因为css计算margin时也需要参考尺寸值,由于四周为0,所以自动计算的尺寸是与父容器一样的。无论是设置width、height 或者是 max-height、max-width,都是让尺寸不会扩大到与父级一样。

    优化:借助强大的calc()函数

       main {
           position: absolute;
           top: calc(50% - 3em);
           left: calc(50% - 9em);
           width: 18em;
           height: 6em;
       }
    

    局限性:要求显式设置宽高

    那么能不能找到一个属性的百分比值以元素自身的宽高作为解析基准。

    优化:CSS变形属性

    使用场景:主要是针对不定宽高(即宽高为百分比的情况),定宽高的话可以用负的margin值来做到。

    这正是我们所需要的,只要换用基于百分比的CSS变形来对元素进行偏移,就可以解除对固定尺寸的依赖。

       main {
           position: absolute;
           top: 50%;
           left: 50%;
           width: 50%; /*注意这里的宽高都为百分比*/
           height: 30%;
           transform: translate(-50%, -50%);
       }
    

    局限性:

    • 有时不能选用绝对定位,因为它对整个布局的影响太过强烈
    • 如果需要居中的元素已经在高度上超过了视口,那么顶部将会被裁减。
    • 在某些浏览器中,这个方法可能会导致元素的显示有一些模糊,因为元素可能被放置在半个像素上。这个问题可以用transform-style:preserve-3d来修复,是一种hack手段。

    2. 基于视口单位的解决方案

    CSS3定义了一套新的单位,称为视口相关的长度单位。

    • vm是与视口宽度相关的。1vm表示视口宽度的1%,而不是100%。
    • 与vm类似,1vh表示视口高度的1%
    • 当视口宽度小于高度时,1vmin等于1vm,否则等于1vh
    • 当视口宽度大于高度时,1vmax等于1vm,否则等于1vh

    例子中,适用于外边距的是vh单位:

    main {
        width: 18em;
        padding: 1em 1.5em;
        margin: 50vh auto 0;
        transform: translateY(-50%)
    }
    

    3. 基于Flexbox 的解决方案(最佳方案)

    body {
        display: flex;
        min-height: 100vh;
        margin: 0;
    }
    
    main {
        margin: auto;
    }
    

    步骤:

    • 先给这个待居中的父元素设置display:flex
    • 再给元素自身设置margin:auto

    Flexbox还可以将匿名容器(即没有被标签包裹的文本节点)垂直居中

    main {
        display: flex;
        justify-content: center;
        align-items: center;
        width: 18em;
        height: 10em;
    }
    

    4. 利用table 实现垂直水平居中

    例:

    <div class="vertical center">
        <div class="box-container">
            <span class="box">miamia</span>
        </div>
    </div>
    

    实现:

    .vertical {
        width: 100%;
        height: 100%;
        display: table;
    }
    .vertical.center {
        text-align: center;
    }
    
    .vertical .box-container {
        display: table-cell;
        vertical-align: middle;
    }
    
    .vertical .box-container .box {
        vertical-align: middle;
    }
    

    优点:适用性很强,没有兼容性问题
    缺点:会增加冗余的HTML结构。

    总结

    CSS3已经对垂直水平居中做了很大的改良,根据CSS3的计划,在未来,只需要下面一行代码即可实现:

    align-self:center;
    

    这听起来多么令人振奋!

    相关文章

      网友评论

        本文标题:CSS中优雅地实现垂直水平居中

        本文链接:https://www.haomeiwen.com/subject/wduufqtx.html