外边距叠加是一个相当简单的概念。 但是,在实践中对网页进行布局时, 它会造成许多混淆。 简单的说,当两个或更多个垂直边距相遇时,它们将形成一个外边距。这个外边距的高度等于两个发生叠加的外边距的高度中的较大者。只有普通文档流中块框的垂直外边距才会发生外边距叠加。 行内框、浮动框或绝对定位框之间的外边距不会叠加。
一般来说, 垂直外边距叠加有三种情况:
- 元素自身叠加
- 包含(父子)元素叠加
- 相邻元素叠加
元素自身叠加
我们知道, 盒模型是 内容→内边距→边框→外边距 这样逐层包含的结构。 当元素没有内容(即空元素)、内边距、边框时, 它的上下边距就相遇了, 即会产生叠加(垂直方向)。 当为元素添加内容、 内边距、 边框任何一项, 就会取消叠加。
元素的顶外边距和底外边距发生叠加
包含(父子)元素叠加
包含元素的外边距隔着 父元素的内边距和边框, 当这两项都不存在的时候, 父子元素垂直外边距相邻, 产生叠加。
元素的顶外边距与父元素的顶外边距发生叠加
相邻元素叠加
这个比较好理解, 相邻的两个元素, 如果它们的上下边距相遇,即会产生叠加。
元素的顶外边距与前面元素的底外边距发生叠加
后两种情况对于网页布局的影响比较大,在某些场合需要合适的方案解决这个问题。
1.解决父子元素外边距叠加问题
<style>
#box {
margin: 10px;
background-color:#d5d5d5;
}
p {
margin: 20px;
background-color:#90C2F3;
}
</style>
</head>
<body>
<div class="wrapper">
<div id="box">
<p>This paragraph has a 20px margin.</p>
</div>
</div>
</body>
</html>
以上示例中div框设置了10像素的外边距,段落设置了20像素的外边距,预期的样式如下左图所示,在段落和div之间有20像素的外边距,在div外边围绕着10像素的外边距。
预期样式 实际样式
这里发生了两个情况。首先,段落的20像素顶外边距和底外边距与div的10像素外边距叠加,形成一个20像素的垂直外边距。其次,这些外边距不是被父div包围 ,而是突出到div的顶部和底部的外边。出现这种情况是由于具有块级子元素的元素计算其高度的方式造成的。
如果元素没有垂直边框或内边距 ,那么它的髙度就是它包含的子元素的顶部和底部边框边缘之间的距离。 因此,包含的子元素的顶部和底部外边距就突出到容器元素的外边。有一个简单的解决方案:通过添加一个垂直边框或内边距,外边距就不再叠加了, 而且元素的高度就是它包含的子元素的顶部和底部外边距边缘之间的距离。
为了让前面的示例看起来像左图只需在div周围添加内边距或边框:外边距叠加的大多数问题可以通过添加一点内边距或与元素背景颜色相同的小边框来修复。
#box {
margin: 10px;
padding:1px;
background-color:#d5d5d5;
}
p {
margin: 20px;
background-color:#90C2F3;
}
另外一个常用的解决方案是给让父级元素触发 BFC,使父元素不和它的子元素发生 margin 折叠(注意这里指的是创建了BFC的元素和它的子元素不会发生折叠)
触发BFC的方法主要有以下几种:
1. float(除了none)
2. overflow(除了visible)
3. display设为‘table-cell’, ‘table-caption’, 或‘inline-block’
4. position(除了static和relative)
5. zoom:1, IE的hasLayout特性会建立一个新的BFC
2. overflow(除了visible)
3. display设为‘table-cell’, ‘table-caption’, 或‘inline-block’
4. position(除了static和relative)
5. zoom:1, IE的hasLayout特性会建立一个新的BFC
其中方法1、3、4我们很容易理解,因为前面说过只有普通文档流中块框的垂直外边距才会发生外边距叠加。 行内框、浮动框或绝对定位框之间的外边距不会叠加(当然也可以自行验证一下)
方法2、5可以如下示例验证:
方法2、5可以如下示例验证:
#box {
margin: 10px;
overflow: hidden;
/*去掉下行注释触发hasLayout*/ /**zoom:1;*/
background-color:#d5d5d5;
}
p {
margin: 20px;
background-color:#90C2F3;
}
2.解决相邻外边距叠加问题
<style>
#box1 {
margin: 10px;
background-color:red;
height: 50px;
1000px;
}
#box2 {
margin: 10px;
background-color:blue;
height: 50px;
1000px;
}
</style>
</head>
<body>
<div id="box1">
</div>
<div id="box2">
</div>
</body>
</html>
不做任何处理时,两个div块的间隙是10px;并不是累加的20px;
根据 BFC 的定义,两个元素只有在同一 BFC 内,才有可能发生垂直外边距的重叠,包括相邻元素、嵌套元素。要解决 margin
重叠问题,只要让它们不在同一个 BFC 内就行。对于嵌套元素,只要让父级元素触发 BFC,就能使父级 margin 和当前元素的 margin 不重叠。对于相邻元素,也可以采用以下方法使它们的 margin
不重叠。
触发BFC的方法主要有以下几种:
1. float(除了none)
2. overflow(除了visible)
3. display设为‘table-cell’, ‘table-caption’, 或‘inline-block’
4. position(除了static和relative)
5. zoom:1, IE的hasLayout特性会建立一个新的BFC
2. overflow(除了visible)
3. display设为‘table-cell’, ‘table-caption’, 或‘inline-block’
4. position(除了static和relative)
5. zoom:1, IE的hasLayout特性会建立一个新的BFC
<style>
#box1 {
margin: 10px;
background-color:red;
height: 50px;
width: 1000px;
float: left;
- /*display:inline-block;*/
}
#box2 {
margin: 10px;
background-color:blue;
height: 50px;
width: 1000px;
float: left;
/*display:inline-block;*/
}
</style>
</head>
<body>
<div id="box1">
</div>
<div id="box2">
</div>
</body>
</html>
两个div块的间隙变成了20px,解决了叠加问题。
这里有个特别奇怪的问题需要注意一下,如果选择使用overflow属性消除外边距叠加,需要给每个元素添加 BFC 的外壳,而不是将overflow属性直接添加到两个元素中。
<style>
.wrap{
overflow: hidden;
}
#box1 {
margin: 10px;
background-color:red;
height: 50px;
width: 1000px;
}
#box2 {
margin: 10px;
background-color:blue;
height: 50px;
width: 1000px;
}
</style>
</head>
<body>
<div class="wrap">
<div id="box1">
</div>
</div>
<div class="wrap">
<div id="box2">
</div>
</div>
</body>
</html>
参考:
《精通CSS高级Web标准解决方案》