zoukankan      html  css  js  c++  java
  • css进阶 04-如何让一个元素水平垂直居中?

    04-如何让一个元素水平垂直居中?

    #前言

    老板的手机收到一个红包,为什么红包没居中?

    如何让一个子元素在父容器里水平垂直居中?这个问题必考,在实战开发中,也应用得非常多。

    你也许能顺手写出好几种实现方法。但大部分人的写法不够规范,经不起千锤百炼。换句话说:这些人也就面试的时候夸夸其谈,但真的上战场的时候,他们不敢这么写,也不知道怎么写最靠谱。

    这篇文章中,我们来列出几种常见的写法,最终你会明白,哪种写法是最优雅的。

    当然,我还会拿出实际应用中的真实场景来举例,让你感受一下标准垂直居中的魅力。

    #如何让一个行内元素(文字、图片等)水平垂直居中

    行内元素的居中问题比较简单。

    #行内元素水平居中

    给父容器设置:

        text-align: center;
    
    
     

    #行内元素垂直居中

    让文字的行高 等于 盒子的高度,可以让单行文本垂直居中。比如:

        .father {
            height: 20px;
            line-height: 20px;
        }
    
     

    #如何让一个块级元素水平垂直居中

    这一段是本文的核心。如何让一个块级的子元素在父容器里水平垂直居中?有好几种写法。我们一起来看看。

    #margin: auto 的问题

    在 CSS 中对元素进行水平居中是非常简单的:如果它是一个行内元素,就对它的父容器应用 text-align: center;如果它是一个块级元素,就对它自身应用 margin: auto或者 margin: 0 auto

    在这里,margin: auto相当于margin: auto auto auto automargin: 0 auto相当于margin: 0 auto 0 auto,四个值分别对应上右下左。其计算值取决于剩余空间。

    但是,如果要对一个元素垂直居中,margin: auto就行不通了。

    比如下面这段代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            .father{
                height: 500px;
                background: pink;
            }
            .son {
                width: 300px;
                height: 200px;
                background: red;
    
                margin: auto;
            }
        </style>
    </head>
    <body>
        <div class="father">
            <div class="son"></div>
        </div>
        <script></script>
    </body>
    </html>
    
    
     

    上面的代码中,父元素和子元素都是定宽高的,即便在这种情况下,我给子元素设置 margin: auto,子元素依然没有垂直居中。

    那还有没有比较好的通用的做法呢?

    #方式一:绝对定位 + margin(需要指定子元素的宽高,不推荐)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
            .father{
                position: relative;
                min-height: 500px;
                background: pink;
            }
            .son {
                position: absolute;
                width: 200px;
                height: 100px;
                background: red;
                top: 50%;
                left: 50%;
                margin-top: -50px;
                margin-left: -100px;
            }
        </style>
    </head>
    <body>
        <div class="father">
            <div class="son">子元素的内容</div>
        </div>
        <script></script>
    </body>
    </html>
    
    
     

    代码解释:我们先让子元素的左上角居中,然后向上移动宽度的一半(50px),就达到了垂直居中的效果;水平居中的原理类似。

    不足之处:要求指定子元素的宽高,才能写出 margin-top 和 margin-left 的属性值。

    但是,在通常情况下,对那些需要居中的元素来说,其宽高往往是由其内容来决定的,不建议固定宽高。

    #方式二:绝对定位 + translate(无需指定子元素的宽高,推荐)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
            .father{
                position: relative;
                min-height: 500px;
                background: pink;
            }
            .son {
                position: absolute;
                background: red;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%);
            }
        </style>
    </head>
    <body>
        <div class="father">
            <div class="son">子元素的内容</div>
        </div>
        <script></script>
    </body>
    </html>
    
     

    这种写法,在没有指定子元素宽高的情况下,也能让其在父容器中垂直居中。因为 translate() 函数中使用百分比值时,是以这个元素自身的宽度和高度为基准进行换算和移动的(动态计算宽高)。

    #方式3:flex 布局(待改进)

    将父容器设置为 Flex 布局,再给父容器加个属性justify-content: center,这样的话,子元素就能水平居中了;再给父容器加个属性 align-items: center,这样的话,子元素就能垂直居中了。

    代码举例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
            .father{
                display: flex;
                justify-content: center;
                align-items: center;
                min-height: 100vh;
                background: pink;
            }
            .son {
                background: red;
            }
        </style>
    </head>
    <body>
        <div class="father">
            <div class="son">子元素的内容</div>
        </div>
        <script></script>
    </body>
    </html>
    
    
     

    上面这种写法,不足之处在于:给父容器设置属性justify-content: centeralign-items: center之后,导致父容器里的所有子元素们都垂直居中了(如果父容器里有多个子元素的话)。可我明明想让指定的某个子元素居中,要怎么改进呢?

    #方式4: flex 布局 + margin: auto(推荐)

    我们只需写两行声明即可:先给父容器设置 display: flex,再给指定的子元素设置我们再熟悉不过的 margin: auto,即可让这个指定的子元素在剩余空间里,水平垂直居中。大功告成。

    代码举例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
            .father{
                display: flex;
                min-height: 100vh;
                background: pink;
            }
            .son {
                margin: auto;
                background: red;
            }
        </style>
    </head>
    <body>
        <div class="father">
            <div class="son">子元素的内容,想水平垂直居中</div>
            <div class="son2">这个元素不想水平垂直居中</div>
        </div>
        <script></script>
    </body>
    </html>
    
     

    请注意,当我们给父容器使用 Flex 布局 时,子元素的margin: auto不仅能让其在水平方向上居中,垂直方向上也是居中的。

    参考文章:探秘 flex 上下文中神奇的自动 margin

    #垂直居中的典型应用场景:红包幕帘/弹窗

    #问题引入

    就拿“弹窗”这一点来说,现在大家的弹窗都是各种样式、各种布局满天飞。不过进公司后,新人在第一次写弹窗之前,都会问一个问题:“弹窗这么通用的东西,没有一个规范吗?”说完之后,又默默写自己的有个性的弹窗去了。

    建议大家在写弹窗的时候,无论如何,一定要严格采用水平居中、垂直居中的写法。

    千万不要用 margin-top 这种距离屏幕顶部的距离来计算弹窗的位置,太搓了。不要让领导觉得:“你们写了这么久的前端代码,连个弹窗都搞不定?”

    #移动端,红包幕帘/弹窗 居中的规范写法(非常标准)

    移动端场景,这里提供一个 红包幕帘/弹窗 的居中写法。注意,是严格居中,非常标准。为什么是移动端?你有见过PC网页端给你送红包的么?

    在实战开发中,下面的这段代码,可以直接拿去用。注释详细,贴心无比。

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="UTF-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <title>Document</title>
            <style>
                /* 整个弹窗组件 */
                .component_popup {
                    position: fixed;
                    top: 0;
                    bottom: 0;
                    left: 0;
                    right: 0;
                    z-index: 100;
                }
    
                /* 遮罩背景 */
                .popup_mask {
                    position: fixed;
                    top: 0;
                    bottom: 0;
                    left: 0;
                    right: 0;
                    background: rgba(0, 0, 0, 0.7);
                }
    
                /* 弹窗区域(内容 + close):严格居中 */
                .popup_content {
                    position: absolute;
                    top: 50%;
                    left: 50%;
                    transform: translate(-50%, -50%);
                }
    
                /* 弹窗的内容部分 */
                .content_box {
                    width: 15.45rem;
                    height: 19.32rem;
                    background: url(http://img.smyhvae.com/20191010_1500_red-packet.png) no-repeat;
                    background-size: 15.45rem 19.32rem;
                }
    
                /* 弹窗的close图标 */
                .content_close {
                    width: 1.25em;
                    height: 1.25em;
                    background: url(http://img.smyhvae.com/20191010_1500_close.png) no-repeat;
                    background-size: 1.25rem 1.25rem;
                    margin: 0 auto;
                    margin-top: 0.5rem;
                }
            </style>
        </head>
        <body>
            <div class="content">默认文档流中的页面主体</div>
    
            <div class="component_popup">
                <div class="popup_mask"></div>
                <div class="popup_content">
                    <div class="content_box"></div>
                    <div class="content_close"></div>
                </div>
            </div>
        </body>
    </html>
    
    
     

    实现效果:

    补充:

    1、如果你的页面中,有很多弹窗,建议将弹窗封装成一个抽象组件。

    2、任何弹窗,都需要解决“滚动穿透”的问题,本文篇幅有限,请自行查阅。

    #最后一段

    有些实现方式虽然简单,但必须要经得起千锤百炼。我们要做到敬畏每一行代码,不能浮于表面。团队开发,要的不是个性,而是标准和规范。

    #参考链接

  • 相关阅读:
    HTML元素解释
    Java命名规范
    HDU 1058 Humble Numbers(DP,数)
    HDU 2845 Beans(DP,最大不连续和)
    HDU 2830 Matrix Swapping II (DP,最大全1矩阵)
    HDU 2870 Largest Submatrix(DP)
    HDU 1421 搬寝室(DP)
    HDU 2844 Coins (组合背包)
    HDU 2577 How to Type(模拟)
    HDU 2159 FATE(二维完全背包)
  • 原文地址:https://www.cnblogs.com/yzy521/p/14132781.html
Copyright © 2011-2022 走看看