div外边距的问题

一个div包着另一个div, 如下代码所示, 如果我设置内部div上边距100px, 则这两个div都会距离浏览器上边缘100px的距离,

<div style="width:400px;height:400px;background-color:blue;">
    <div style="width:200px;height:200px;margin-top:100px;background-color:red;"></div>
</div>

但如果给外部div加上边框的话, 则外部div距离浏览器上边缘就是0, 而内部div与外部div有一个100px的间距, 不明白这是为什么?外部div加边框的代码如下

<div style="width:400px;height:400px;background-color:blue;border-style:solid;">
    <div style="width:200px;height:200px;margin-top:100px;background-color:red;"></div>
</div>
阅读 10.9k
11 个回答

楼主的问题可以分解成几个点
1、重叠发生的机制
2、border如何阻止了重叠
3、重叠解决方案

重叠发生的常见情况
1.元素互为相邻关系
2.元素互为包含关系(父子关系)

重叠发生的机制
无论是相邻关系还是包含关系,重叠发生依赖于两个元素的margin能够相互接触到!!相互触碰到!相互摩擦!

相邻关系

<div class="man" style="width:400px;height:100px;background:red;margin-bottom:100px;"></div>
<div class="brother" style="width:400px;height:50px;background:#af3;margin-top:50px;"></div>

clipboard.png
如果添加border或者padding还会发生重叠吗?答案是肯定的。

<div class="man" style="width:400px;height:100px;background:red;margin-bottom:100px;border-style:solid;"></div>
<div class="brother" style="width:400px;height:50px;background:#af3;margin-top:50px;border-style:solid;"></div>

clipboard.png

不论如何设置padding或者border,对于相邻元素来说,它们的margin都能互相接触!!!!!所以会发生重叠。

包含关系

<div style="width:400px;height:400px;background-color:blue;">
     <div style="width:200px;height:200px;margin-top:100px;background-color:red;"></div>
</div>

注意,这时候border,padding都是0.父元素的margin和子元素的margin能够相互接触到。

clipboard.png

如果给父元素加个padding或者border,那么子元素的margin就无法接触到父元素的margin了。因此也无法发生重叠了!这里以border为例。

<div style="width:400px;height:400px;background-color:blue;border-style:solid;">
        <div style="width:200px;height:200px;margin-top:100px;background-color:red;"></div>
</div>

clipboard.png

如果给子元素添加border或者padding是不起作用的。

外边距重叠的解决方式
1.创建BFC(BFC是个坑,以后再聊吧)
2.避免margin的亲密接触。

---------------------------------------1月19更新部分(为加深理解)---------------------------------
刚好看到这个例子,便试了下,觉得可以算是测试margin负值的理解吧。

首先来考虑下这段代码。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>verticalMargin</title>
</head>
<style type="text/css">
body{margin:0;padding:0;}
li{margin-bottom:20px;background:#ee3;}
ul{background:#af3;margin-bottom:-15px;}
h1{margin-top:-18px;background:#ccc;}
/*h1{background:#ccc;}*/
</style>
<body>
    <ul>
        <li>A list item</li>
        <li>Another list item</li>
    </ul>
        <h1>A haeding</h1>
</body>
</html>

这里有各种重叠,ul的负外边距、h1的负外边距以及li的正外边距。
以上代码运行的效果最终效果是:
1.文字描述:ul和h1之间相间隔2px
2.实际效果图

clipboard.png

为什么会这样呢?
这个问题的思路有两种,
一、是先考虑ul和li之间的重叠,再考虑h1的重叠。(先考虑包含关系再考虑相邻关系)
二、是先考虑ul和h1的重叠,再考虑li的重叠。(先考虑相邻关系再考虑包含关系)
最终得到的结果都一样。

垂直外边距合并问题

Top and bottom margins of blocks are sometimes combined (collapsed) into a single margin whose size is the largest of the margins combined into it, a behavior known as margin collapsing.
多个块级元素的的margin-top和margin-bottom属性在满足一定条件下,会合并成一个值比较大的那个margin值,这就是外边距折叠或外边距合并

Margin collapsing occurs in three basic cases:
发生在以下3种情况
Adjacent siblings
相邻的兄弟块元素之间
The margins of adjacent siblings are collapsed (except when the later sibling needs to be >cleared past floats). For example:、
相邻兄弟块元素之间的上下边距将会被合并
<p>The bottom margin of this paragraph is collapsed...</p>
<p>...with the top margin of this paragraph.</p>

Parent and first/last child
父元素和它的第1个子元素和最后一个子元素之间
If there is no border, padding, inline content, or clearance to separate the margin-top of a block with the margin-top of its first child block, or no border, padding, inline content, height, min-height, or max-height to separate the margin-bottom of a block with the margin-bottom of its last child, then those margins collapse. The collapsed margin ends up outside the parent.
如果父元素没有border-top、border-bottom,padding-top、padding-bottom,行内元素,和clearance属性来隔离与第1个块级子元素的margin-top,或没有border,padding,内联元素,height,min-height,max-height属性来隔离与最后一个块级子元素的margin-bottom属性,那么它们之间的margin-top和margin-bottom属性合并

Empty blocks
空块级元素
If there is no border, padding, inline content, height, or min-height to separate a block's margin-top from its margin-bottom, then its top and bottom margins collapse.
如果一个块级元素没有border-top、border-bottom,padding-top、padding-bottom,行内元素,height,min-height,max-height属性来隔离自身的margin-bottom和margin-top属相,那么margin-top和maring-bottom将合并

More complex margin collapsing (of more than two margins) occurs when these cases are combined.
当上面3种情况组合出现的时候,情况和复杂些

These rules apply even to margins that are zero, so the margin of a first/last child ends up outside its parent (according to the rules above) whether or not the parent's margin is zero.

以上规则在margin-top、margin-bottom为0的情况下依旧适用,那么就会出现第1个子元素和最后一个子元素的margin出现在父元素外面的情形,请不要奇怪

When negative margins are involved, the size of the collapsed margin is the sum of the largest positive margin and the smallest (most negative) negative margin.

当margin-top、margin-bottom为负值时,规则依旧适用,取值为最大正值和最小负值之间的和

Margins of floating and absolutely positioned elements never collapse.
floating元素和绝对定位的元素margin值绝对不会合并

<div style="width:400px;height:400px;background-color:blue;">
    <div style="width:200px;height:200px;margin-top:100px;background-color:red;"></div>
</div>

就符合第2种情况父子元素垂直边距的合并
外层DIV元素没有margin-top值没有指定,就认为其值为0
第1个块级子元素的maring-top为100px,按照合并规则,2个margin-top合并成一个100px的margin-top,也即是父DIV的margin-top为100px,同时子元素共享了父元素的margin-top区域,其内边框位置现在父DIV的top位置
视觉效果就如同没有外边距合并按正常理解的效果:

<div style="width:400px;height:400px;background-color:blue;margin-top:100px;">
    <div style="width:200px;height:200px;background-color:red;"></div>
</div>
<div style="width:400px;height:400px;background-color:blue;border-style:solid;">
    <div style="width:200px;height:200px;margin-top:100px;background-color:red;"></div>
</div>

就是没有垂直外边距合并的效果
如果代码修改成

<div style="width:400px;height:400px;background-color:blue;border-left-style:solid;">
    <div style="width:200px;height:200px;margin-top:100px;background-color:red;"></div>
</div>

<div style="width:400px;height:400px;background-color:blue;border-right-style:solid;">
    <div style="width:200px;height:200px;margin-top:100px;background-color:red;"></div>
</div>

还是执行垂直外边距合并

BFC的问题,可以百度BFC

我没有具体看你的代码,但听你意思应该是盒子的外边界合并的问题~垂直的情况下,大的边距会合并小的。你可以用浏览器看下你写的盒子的范围~

简单解决办法 加上overflow hidden

外层div中加上border:1px solid red;

产生折叠的必备条件:margin必须是邻接的!
第一种情况明显是父级的margin:0和子级的margin:100px折叠了;
第二种情况由margin折叠条件: 没有线盒,没有空隙,没有padding和border将他们分隔开;可知 一个常规文档流元素的margin-top 与其第一个常规文档流的子元素的margin-top产生折叠,条件为父元素不包含 padding 和 border即子元素不包含缝隙。所以就不会发生margin折叠。至于父级是否变成BFC从目前资料来看并不确定。

这就是margin collpse现象具体的你可以百度一下,解决办法有多种,最简单的就是在最外层div加上overflow:hidden; 第二种border:1px solid transparent;或者border-top:1px solid transparent;第三种解决方式,给最外层div加个padding

外边距折叠的原因
外层div与内层div的外边距发生了折叠

使内部div在另一个bfc中就可以了

1,产生这个的原因是 margin collapse,即两个或多个盒子相邻或者包含的话,这些盒子的 margin 会合并成一个 margin 。但是这个合并的前提是这两个盒子之间不能有 padding,border 或者其他元素在两个盒子之间。
2,具体到这个问题:第一个因为外面的盒子和内部的盒子没有 border 隔离,所以这两个盒子的 margin 合并,分别是 0 和 100,合并之后就变成 100. 第二个因为外面的盒子有 border 隔离,所以这两个盒子的 margin 不会合并,内部的盒子相对外部的外边距是 100 ,但是外边距还是 0.

参考:margin-collpase

推荐问题
宣传栏