1. margin折叠问题
因为这里主要讨论BFC与折叠现象的问题,所以具体折叠是只做概要说明,具体内容请参考w3c文档中CSS外边距合并一文,这里只作简要描述。
外边距合并指的是,当两个垂直外边距相遇时,它们将形成一个外边距。合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者。
<style type="text/css">
body {
margin: 0px;
padding: 0px;
}
#out_box{
width: 300px;
height: 300px;
/*overflow: hidden;*/
background-color: blue;
}
#inside_box{
width: 100px;
height: 100px;
margin-top: 50px;
background-color: green;
}
</style>
</head>
<body>
<div id="out_box">
<div id="inside_box"></div>
</div>
</body>
根据上面的代码正常来看应该是out_box贴着左上角,而inside_box距离out_box上边距50px,可实际情况却是下图所示。这就是margin折叠问题。

2. 如何解决该问题
根据margin折叠的概念可以知道,折叠现象仅在两个垂直外边距相遇时才会发生,因此自然可以想到如何使两个垂直外边距不相遇,可是相遇又是如何定义的呢?
产生折叠的必备条件:margin必须是邻接的
而根据w3c规范,两个margin是邻接的必须满足以下条件:
- 必须是处于常规文档流(非float和绝对定位)的块级盒子,并且处于同一个BFC当中。
- 没有线盒,没有空隙(clearance,下面会讲到),没有padding和border将他们分隔开
- 都属于垂直方向上相邻的外边距,可以是下面任意一种情况
- 元素的margin-top与其第一个常规文档流的子元素的margin-top
- 元素的margin-bottom与其下一个常规文档流的兄弟元素的margin-top
- height为auto的元素的margin-bottom与其最后一个常规文档流的子元素的margin-bottom
- 高度为0并且最小高度也为0,不包含常规文档流的子元素,并且自身没有建立新的BFC的元素的margin-top和margin-bottom
这里出现了两个新的概念BFC与clearance。
BFC
全称Block formatting contexts,译为块级格式化上下文,它是指块级元素所在的一个环境,该环境下会遵守一定规则,w3c中定义为
浮动元素和绝对定位元素,非块级盒子的块级容器(例如 inline-blocks, table-cells, 和 table-captions),以及overflow值不为“visiable”的块级盒子,都会为他们的内容创建一个新的BFC(块级格式上下文)。
在BFC中,盒子从顶端开始垂直地一个接一个地排列,两个盒子之间的垂直的间隙是由他们的margin 值所决定的。在一个BFC中,两个相邻的块级盒子的垂直外边距会产生折叠。
在BFC中,每一个盒子的左外边缘(margin-left)会触碰到容器的左边缘(border-left)(对于从右到左的格式来说,则触碰到右边缘)。
3. clearance
当浮动元素之后的元素设置clear以闭合相关方向的浮动时,根据w3c规范规定,闭合浮动的元素会在其margin-top以上产生一定的空隙,该空隙会阻止元素margin-top的折叠,并作为间距存在于元素的margin-top的上方。
.up-box {
width: 100px;
height: 100px;
background: red;
margin-bottom: 50px;
}
.middle-box {
width: 100px;
height: 100px;
background: blue;
margin-top: 50px;
margin-bottom: 50px;
float: left;
}
.down-box {
width: 100px;
height: 100px;
background: yellow;
margin-top: 50px;
clear: both;
}
</style>
</head>
<body>
<div class="up-box">
up-box
</div>
<div class="middle-box">
middle-box
</div>
<div class="down-box">
down-box
</div>
</body>
根据实例代码测试结果可以发现,无论怎样修改inside_box2的margin-top的值,该盒子位置都不会发生变化,而只有修改inside_box1的margin-bottom时会让inside_box2位置向下移动

总结:使用clear的元素可以让被清除浮动的元素与其上方元素的margin不会产生重叠问题
4. BFC与clearance是怎样使margin不相邻的
根据margin邻接条件中的内容可以判断
- 通过创建新的BFC让子元素与父元素不在同一个BFC中
- 使元素带有clear:left|right|both产生clearance
具体产生BFC的方法可在网上查阅
网友评论
我是看大漠大大的文章整理的,他那里面有一个clearance的图片,大概在文章结尾处有一个计算公式,那里仔细看一下应该会好些,如果没看懂的话我今晚下班回去再整理清除一下告诉你