盒子水平垂直居中浅析

176 阅读3分钟

前言

本文主要总结实际开发过程中用到的一些实现盒子水平垂直居中的方法,对于不常用的一些冷门方法不做过多赘述,主要也是方便后续开发中可以直接拿来使用。

水平垂直居中示例

1. 通过position属性的relative和absolute实现水平垂直居中。
position 属性规定元素的定位类型为:
static
默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。
fixed
生成固定定位的元素,相对于浏览器窗口进行定位。元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。
relative
生成相对定位的元素,相对于其正常位置进行定位。"left:20" 会向元素的left位置添加20 像素。
示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>水平垂直居中</title>
    <style type="text/css">
        .father {
            width: 200px;
            height: 200px;
            background: yellow;
        }
        .child {
            width: 100px;
            height: 50px;
            background: aquamarine;
            position: relative;
            left: 30px;
        }
    </style>
</head>
<body>
    <div class="father">
        <div class="child"></div>
    </div>
</body>
</html>

clipboard.png

child模块由左边与father左边重合,到与father的左边相距30px。
absolute
生成绝对定位的元素,相对于除static 定位以外的第一个父元素进行定位。元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。
sticky
粘性定位,该定位基于用户滚动的位置。它的行为就像 position:relative; 而当页面滚动超出目标区域时,它的表现就像 position:fixed;,它会固定在目标位置。通过设置top/left/right/bottom的值来确定粘连的位置。
sticky使用示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>水平垂直居中</title>
    <style type="text/css">
        .father {
            width: 200px;
            height: 200px;
            background: yellow;
            overflow-y: scroll;
        }
        .child {
            width: 100px;
            height: 50px;
            background: aquamarine;
        }
        .stickydiv {
            position: sticky;
            top: 0;
            width: 100px;
            height: 50px;
            background: red;
        }
    </style>
</head>
<body>
    <div class="father">
        <div class="child">child1</div>
        <div class="child">child2</div>
        <div class="stickydiv">stickydiv</div>
        <div class="child">child3</div>
        <div class="child">child4</div>
        <div class="child">child5</div>
        <div class="child">child6</div>
    </div>
</body>
</html>

滚动以前:

clipboard.png
滚动到stickydiv要超出可视界面以后,styckydiv粘连在top为0的地方。

clipboard.png

inherit
规定应该从父元素继承 position 属性的值。
initial
设置该属性为当前默认值。
使用absolute和relative实现水平垂直居中的4种方式:

  • 方式1
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>水平垂直居中</title>
    <style type="text/css">
        .father {
            width: 200px;
            height: 200px;
            background: yellow;
            position: relative;
        }
        .child {
            width: 100px;
            height: 50px;
            background: aquamarine;
            position: absolute;
            left: 50%;
            top: 50%;
            margin-left: -50px;
            margin-top: -25px;
        }
    </style>
</head>
<body>
    <div class="father">
        <div class="child"></div>
    </div>
</body>
</html>
  • 方式2
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>水平垂直居中</title>
    <style type="text/css">
        .father {
            width: 200px;
            height: 200px;
            background: yellow;
            position: relative;
        }
        .child {
            width: 100px;
            height: 50px;
            background: aquamarine;
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
        }
    </style>
</head>
<body>
    <div class="father">
        <div class="child"></div>
    </div>
</body>
</html>
  • 方式3
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>水平垂直居中</title>
    <style type="text/css">
        .father {
            width: 200px;
            height: 200px;
            background: yellow;
            position: relative;
        }
        .child {
            width: 100px;
            height: 50px;
            background: aquamarine;
            position: absolute;
            left: 0;
            right: 0;
            top: 0;
            bottom: 0;
            margin: auto;
        }
    </style>
</head>
<body>
    <div class="father">
        <div class="child"></div>
    </div>
</body>
</html>
  • 方式4
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>水平垂直居中</title>
    <style type="text/css">
        #father {
            width: 200px;
            height: 200px;
            background: yellow;
            position: relative;
        }
        #child {
            width: 100px;
            height: 50px;
            background: aquamarine;
        }
    </style>
</head>
<body>
    <div id="father">
        <div id="child"></div>
    </div>
    <script>
        let fatherDom = document.getElementById('father')
        let childDom = document.getElementById('child')
        let fatherDomWidth = fatherDom.clientWidth
        let fatherDomHeight = fatherDom.clientHeight
        let childDomWidth = childDom.clientWidth
        let childDomHeight = childDom.clientHeight
        childDom.style.position = 'absolute'
        childDom.style.left = (fatherDomWidth - childDomWidth) / 2 + 'px'
        childDom.style.top = (fatherDomHeight - childDomHeight) / 2 + 'px'
    </script>
</body>
</html>

获取dom元素宽度有这几种方式:scrollWidth、clientWidth、offsetWidth,这三种方式的区别主要在于是否超出父级的范围。
scrollWidth:内容实际应该占据的宽度,不包括滚动条等边界线。当出现滚动条以后,内容应该占据的理想宽度。
clientWidth:内容可以看到的宽度,不包括滚动条等边界线,会随内容显示大小的变化而变化。
offsetWidth:内容可以看到的宽度,包括滚动条等边界线,会随内容显示大小的变化而变化。
示例:
(1)无滚动条

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>水平垂直居中</title>
    <style type="text/css">
        #father {
            width: 200px;
            height: 50px;
            background: yellow;
            display: flex;
            flex-direction: row;
        }
        .child {
            width: 80px;
            height: 50px;
            background: aquamarine;
        }
    </style>
</head>
<body>
    <div id="father">
        <div class="child">child</div>
        <div class="child">child</div>
    </div>
    <script>
        let fatherDom = document.getElementById("father")
        console.log('scrollWidth:' + fatherDom.scrollWidth)
        console.log('clientWidth:' + fatherDom.clientWidth)
        console.log('offsetWidth:' + fatherDom.offsetWidth)
    </script>
</body>
</html>

输出:

clipboard.png
(2)有滚动条

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>水平垂直居中</title>
    <style type="text/css">
        #father {
            width: 200px;
            height: 50px;
            background: yellow;
            display: flex;
            flex-direction: row;
            overflow: scroll;
        }
        .child {
            min-width: 80px;
            height: 50px;
            background: aquamarine;
        }
    </style>
</head>
<body>
    <div id="father">
        <div class="child">child</div>
        <div class="child">child</div>
        <div class="child">child</div>
        <div class="child">child</div>
    </div>
    <script>
        let fatherDom = document.getElementById("father")
        console.log('scrollWidth:' + fatherDom.scrollWidth)
        console.log('clientWidth:' + fatherDom.clientWidth)
        console.log('offsetWidth:' + fatherDom.offsetWidth)
    </script>
</body>
</html>

输出:

clipboard.png
4个child子模块模块理论上应该有320px的宽度,clientWidth为去除滚动条以后的可视宽度,offsetWidth为包含滚动条的可视宽度。

2. 通过flex实现水平垂直居中。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>水平垂直居中</title>
    <style type="text/css">
        .father {
            width: 200px;
            height: 200px;
            background: yellow;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .child {
            width: 100px;
            height: 50px;
            background: aquamarine;
        }
    </style>
</head>
<body>
    <div class="father">
        <div class="child"></div>
    </div>
</body>
</html>

总结

主要介绍了平时开发过程中常用的一些盒子水平垂直居中的方法,对实现过程中的一些细节做了浅析。