关于css margin塌陷、合并问题浅谈

986 阅读3分钟

关于css margin塌陷、合并问题

问题一:什么是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>
    <script type="text/javascript">
        window.onload = function (){
            console.log("父子盒子嵌套,父盒子塌陷");
        }
    </script>
    <style type="text/css">
        * {
            margin: 0px;
            padding: 0px;
        }
        .father {
            height: 100px;
            width: 100px;
            background-color: red;
            /* overflow: hidden; */
        }
        .son {
            height: 50px;
            width: 50px;
            background-color: blue;
            margin: 25px 25px;
        }
    </style>
</head>
<body>
    <!-- 父子盒子嵌套,子盒子设置了垂直margin为25px,结果父盒子向下移动25px,呈现出父盒子塌陷现象 -->
    <div class="father">
        <div class="son">
        </div>
    </div>
</body>
</html>

说明

代码中设置了子盒子margin 垂直为25px,但实际效果为父盒子向下移动了25px,子盒子未动,该现象称之为margin垂直塌陷。可以将该现象理解为css中的一个重大BUG。

解决方法

方法一:给父盒子增加一个上边框或者设置内边距
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript">
        window.onload = function (){
            console.log("父子盒子嵌套,父盒子塌陷");
        }
    </script>
    <style type="text/css">
        * {
            margin: 0px;
            padding: 0px;
        }
        .father {
            height: 100px;
            width: 100px;
            background-color: red;
          	<!-- 新增加的代码-->
          	boder-top:1px solid red;
            /* padding: 1px 1px;*/
        }
        .son {
            height: 50px;
            width: 50px;
            background-color: blue;
            margin: 25px 25px;
        }
    </style>
</head>
<body>
    <!-- 父子盒子嵌套,子盒子设置了垂直margin为25px,结果父盒子向下移动25px,呈现出父盒子塌陷现象 -->
    <div class="father">
        <div class="son">
        </div>
    </div>
</body>
</html>

方法二:触发BFC规则

BFC是CSS中的一种规则,会影响盒子属性,使其与普通盒子不一样,恰好可以解决margin垂直塌陷问题,BFCBlock Formatting Context块级格式化上下文

W3CBFC的解释:它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。当涉及到可视化布局的时候,Block Formatting Context提供了一个环境,HTML元素在这个环境中按照一定规则进行布局。

但其实我们只需要记住,BFC目的就是:形成一个完全独立的空间,让空间中的子元素不会影响到外面的布局。解决手段如下所示

  • float不为none
  • position不为relativestatic
  • overflowautoscrollhidden
  • display的值为table-cellinline-block

总结:

解决margin垂直塌陷问题,可以通过设置父盒子边框方法解决,但该方案一般不作为解决手段,因为设置boder值或者设置内边距都有可能使盒子大小改变,与设计相违背。我们一般通过触发BFC的方法来实现。

问题二:什么是margin外边距合并?

当上下相邻的两个块元素(兄弟关系)相遇时,如果上面的元素有下外边距 margin-bottom,下面的元素有

上外边距 margin-top ,则他们之间的垂直间距不是 margin-bottom 与 margin-top 之和。取两个值中的

较大者这种现象被称为相邻块元素垂直外边距的合并

现象

代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript">
        window.onload = function () {
            console.log("margin合并问题");
        }
    </script>
    <style type="text/css">
        .brother {
            height: 100px;
            width: 100px;
            background-color: red;
            margin: 20px 20px;
        }
        .sister {
            height: 100px;
            width: 100px;
            background-color: blue;
            margin: 20px 20px;
        }
    </style>
</head>
<body>
    <div class="brother"></div>
    <div class="sister"></div>
</body>
</html>

说明

相邻的两个盒子之间设置了margin值,代码中都分别为20px,理论上盒子brother与盒子sister应该相距40px,实际效果上只有20px,该现象就称之为margin外边距合并

解决方法

方法一:只设置一个盒子的margin值为需要的理想值

盒子brother的垂直margin设置为40px,盒子sister的垂直margin设置为0

方法二:把它们放到一个父级盒子里面,并且触发父级盒子的BFC规则
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript">
        window.onload = function () {
            console.log("margin合并问题");
        }
    </script>
    <style type="text/css">
        .father {
            overflow: hidden;
        }
        .brother {
            height: 100px;
            width: 100px;
            background-color: red;
            margin: 20px 20px;
        }
        .sister {
            height: 100px;
            width: 100px;
            background-color: blue;
            margin: 20px 20px;
        }
    </style>
</head>
<body>
    <div class="father">
        <div class="brother"></div>
    </div>
    <div class="father">
        <div class="sister"></div>
    </div>
</body>
</html>

总结:

添加一个父元素等于修改了整个html结构,该方案慎用,最好还是通过方案一来实现。这样可以不需要修改html结构