从头开始 — CSS — 垂直居中

作者: myWsq | 来源:发表于2018-03-20 22:25 被阅读23次

    事实上,每次面试前端必问的问题就是这个。及其常见的需求,看起来似乎非常简单,但是实现起来很费劲,尤其是涉及尺寸不固定的元素。

    本篇文章将介绍比较流行的几种方法。

    行内块

    <body>
        <div id="ghost"></div>
        <span>
            hello
        </span>
    </body>
    
     #ghost {
                display: inline-block;
                height: 20em;
                vertical-align: middle;
            }
    

    本质上是利用了内联元素的 vertical-align 属性,通过将此属性置为middle,同一行内的内联元素都将以设置这一属性的内联元素的基线对齐。

    基于inline-block特有的属性:拥有内联元素的特性同时可以定义宽高,我们可以设置一个ghost行内块用于定义高度,再让其他内联元素与其对齐,实现垂直居中。

    当然我们也可以将其它元素置为行内块,再设置宽度并添加text-align使其水平居中。

    总结一下,此方法太过hack。

    绝对定位

    子元素固定宽高

    <div id="main">
            <div id="child">
                hello
            </div>
    </div>
    
    #main {
                background-color: green;
                height: 20em;
                width: 20em;
                position: relative;
    }
    
    #child {
                position: absolute;
                background: yellow;
                top: 50%;
                left: 50%;
                height: 10em;
                width: 10em;
                margin-top: -5em;
                margin-left: -5em;
    }
    

    显然,这种方法的原理是:先利用绝对定位将这个元素的左上角放置与父元素的正中间,再利用负边距将它向左上移动它本身的一半。

    如果借助calc()函数可以说明得更加清楚:

    #child {
        position: absolute;
        top: calc(50%-5em);
        left: calc(50%-5em);
        height: 10em;
        width: 10em;
    }
    

    不固定宽高

    实际中大多数时候我们并不知道子元素的实际宽高。

    如果你属性translate()函数,你一定知道当它的参数为百分比时,它会按照元素本身的百分比值进行变换,我们可以通过这个方法彻底摆脱对尺寸的依赖!

    #child {
                position: absolute;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%);
    }
    

    看起来已经完美解决了,但是它还有以下的缺陷:

    1. 绝对定位会对整体的布局造成很强烈的影响。
    2. 如果居中的元素超过了视窗会被裁剪掉。
    3. 在某些浏览器中,元素可能会被放置在半个像素上造成模糊。

    视口居中

    如果我们不采用绝对定位,对子元素设置margin使其左上角置于父元素中点,再用translate重复上一种方法的操作,是否可以实现呢?

    答案是不可以,因为margin的百分比是以父元素的宽度为基准的,即便是top和bottom也是! 没错,很扯。

    如果仅仅想要垂直于视口,我们可以采用css中相对于视口的单位 vwvhvminvmax

    • 1vw 表示视口宽度的1%,同理1vh等于视口高度的1%
    • 当视口宽度小于高度时,1vmin=1vw,否则1vmin=1vh,另一种情况同理。
    #child {
                margin:50vh auto 0;
                transform: translateY(-50%);
    }
    

    它只能基于视口居中。

    Flexbox

    flex当然是未来的趋势,上面的一切都可以理解成为了照顾老旧的浏览器的猴戏(虽然translate和视口单位的兼容性也不怎么好)。

    <body>
        <div id="main">hello</div>
    </body>
    
    #main {
               margin: auto;
            }
     body {
                display: flex;  
            }
    

    啊,很难受。使用flexbox时,margin:auto不仅在水平方向上将元素居中,垂直方向上也是如此。

    如果你熟悉flex的话,其实还有多种实现方式。

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

    或者对子元素单独设置交叉轴对齐方式:

    body {
                display: flex;  
                justify-content: center;
            }
    #main {
                align-self:center;
    }
    

    相关文章

      网友评论

        本文标题:从头开始 — CSS — 垂直居中

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