margin 重叠问题 Margin Collapse

块的上外边距(margin-top)和下外边距(margin-bottom)有时合并(重叠)为单个边距,其大小为单个边距的最大值(或如果它们相等,则仅为其中一个),这种行为称为边距重叠。

MDN-外边距重叠

重叠的结果:

1、两个相邻的外边距都是正数时,重叠结果是它们两者之间较大的值。

2、两个相邻的外边距都是负数时,重叠结果是两者绝对值的较大值。

3、两个外边距一正一负时,重叠结果是两者的相加的和。

margin 重叠本质上的问题还是 BFC,要理解这个问题,我们先来看看重叠的条件。

重叠的条件

  • 必须是处于常规文档流(非 float 和绝对定位)的块级盒子,并且处于同一个 BFC 当中。
  • 没有线盒,没有空隙(clearance,下面会讲到),没有 padding 和 border 将他们分隔开
  • 都属于垂直方向上相邻的外边距,可以是下面任意一种情况
    • 元素的 margin-top 与其第一个常规文档流的子元素的 margin-top
    • 元素的 margin-bottom 与其下一个常规文档流的兄弟元素的 margin-top
    • height 为 auto 的元素的 margin-bottom 与其最后一个常规文档流的子元素的 margin-bottom
    • 高度为 0 或 auto 并且最小高度也为 0,不包含常规文档流的子元素,并且自身没有建立新的 BFC 的元素的 margin-top 和 margin-bottom

根据以上描述的条件,我们可以得出以下结论

  • 浮动元素不与任何元素的外边距产生重叠(包括其父元素和子元素)
  • 绝对定位元素不与任何元素的外边距产生重叠
  • 建立 BFC 的元素(例如浮动或 overflow 属性的值不为 visible)不会与其在流中的子元素的外边距重叠
  • inline-block 元素不与任何元素的外边距产生重叠
  • 一个常规文档流元素的 margin-bottom 与它下一个常规文档流的兄弟元素的 margin-top 会产生重叠,除非它们之间存在间隙(clearance)
  • 一个不包含 padding 和 border 的父元素的 margin-top 与其第一个不包含 clearance 子元素的 margin-top 产生重叠
  • 一个 'height' 为 'auto' 并且 'min-height' 为 '0'的常规文档流元素的 margin-bottom 会与其最后一个常规文档流子元素的 margin-bottom 重叠,条件为父元素不包含 padding 和 border ,子元素的 margin-bottom 不与包含 clearance 的 margin-top 重叠
  • 一个不包含border-top、border-bottom、padding-top、padding-bottom的常规文档流元素,并且其 'height' 为 0 或 'auto', 'min-height' 为 '0',其里面也不包含行盒(line box),其自身的 margin-top 和 margin-bottom 会重叠。

Collapsing margins

总结一下就是

  • 浮动元素、绝对定位、inline-block元素不与任何元素的外边距产生重叠
  • 不同 BFC 的元素不会产生重叠
  • 特殊情况下存在间隙(clearance)的元素不会产生重叠

我们来看看产生重叠的几种情况

相邻兄弟元素重叠

<div class="BFC">
<div class="middle-box margin red"></div>
<div class="middle-box margin green"></div>
</div>
<style>
.BFC{
display: flow-root;
}
.margin{
margin:20px;
}
.big-box{
width: 100px;
height: 100px;
}
.middle-box{
width: 50px;
height: 50px;
}
.red{
background-color: red;
}
.green{
background-color: green;
}
.blue{
background-color: blue;
}
</style>

效果如下图



我们通过absolute、inline-block、float可以使其margin不重叠







但是需要注意的是,使用absolute和float时,元素会脱离文档流,需要对其定位做相应处理。

另外,由于这两者脱离文档流之后,如果后面还有兄弟元素,这个兄弟元素仍然会与前一个元素邻接,也就是会继续产生 margin 重叠

<div class="BFC relative">
<div class="middle-box margin red"></div>
<div class="middle-box margin green" style="position:absolute;">absolute</div>
<div class="middle-box margin blue"></div>
</div>
<div class="BFC">
<div class="middle-box margin red"></div>
<div class="middle-box margin green" style="float: left">float</div>
<div class="middle-box margin blue"></div>
</div>

效果如下图



在这里就必须提一下经常与 float 一起出现的 clear 属性,这与我们上面提到的 间隙(clearance)也有关

clear 属性规定元素的哪一侧不允许其他浮动元素

描述
left 元素框的上外边界低于这个元素之前的任何左浮动框的下外边界
right 元素框的上外边界低于这个元素之前的任何右浮动框的下外边界
both 元素框的上外边界低于这个元素之前的任何左浮动框或右浮动框的下外边界
none 对浮动框没有限制

clear 属性设置了非 none 值后,就会产生间隙。这里摘抄文档中的原文,意思是间隙可以抑制重叠,并且充当元素的 margin-top

Values other than none potentially introduce clearance. Clearance inhibits margin collapsing and acts as spacing above the margin-top of an element. It is used to push the element vertically past the float.

看一个例子

<div class="BFC">
<div class="middle-box margin green" style="float: left">float</div>
<div class="middle-box margin blue" style="clear: both;"></div>
<div class="middle-box margin red"></div>
</div>

效果如下,由于元素的 margin-top 会与 float 元素的 margin-bottom 相接,间隙就是元素 margin-top 到 float 元素 margin-top 的距离



其实这里又隐式地产生了一个 margin 重叠,这不是套娃吗!

所以关于兄弟组件的 margin 重叠问题,还是建议用新建一个 BFC 的方式来解决。

上面 float 产生的重叠也可以用 BFC 来解决。

<div class="BFC">
<div class="middle-box margin red"></div>
<div class="BFC">
<div class="middle-box margin green"></div>
</div>
</div>

需要注意的是,建议新建 BFC 的时候使用 display:flow-root,意为创建一个行为类似于根元素的元素,这样语义化更好

父子元素 margin-top 重叠

<div class="BFC">
<div class="big-box margin green">
<div class="middle-box margin red"></div>
</div>
</div>

效果如下,子元素和父元素的 margin-top 重叠了



根据上面的总结,我们也可以在父子元素是上使用 inline-block、absolute、float 或在子元素上建立 BFC 来解决重叠问题

但这里提供一种更好的方式,设置父元素的 padding 或 border

<div class="BFC">
<div class="big-box margin green" style="padding: 10px">
<div class="middle-box margin red"></div>
</div>
</div>



这样父元素子元素的 margin 也就不会重叠了

另外,你可以在父元素中填充内容来制造间隙,可以使用::before 或 ::after 伪元素,不过这样会被内容占掉一部分的容器高度

<div class="BFC">
<div class="big-box margin green before">
<div class="middle-box margin red"></div>
</div>
</div>
<style>
.before::before{
content: '';
display: inline-block;
}
</style>



在实际使用中需要具体问题具体分析

auto 高度的父元素与子元素的 margin 重叠

<div class="BFC">
<div class="auto-box margin green">
<div class="middle-box margin red"></div>
</div>
</div>
<style>
.auto-box{
width: 100px;
height: auto;
}
</style>

效果如下

解决的方式和上面的思路类似,这里需要注意的就是由于父元素的高度是 auto,子元素脱离文档流的情况需认真考虑

仍然推荐在父元素中添加 border、padding 属性或在子元素上建立 BFC 的方式来解决这个问题

<div class="BFC">
<div class="auto-box margin green" style="border: 10px solid;">
<div class="middle-box margin red"></div>
</div>
</div>

在查阅资料中发现可以通过设置 min-height 来解决 margin 重叠,其实本质上只是把父元素的内容撑开了。

我个人认为这没有从根本上解决重叠的问题。

<div class="BFC">
<div class="auto-box margin green" style="min-height: 100px">
<div class="middle-box margin red"></div>
</div>
</div>

margin 重叠问题深入探究的更多相关文章

  1. 上下margin重叠传递问题

    我发现强迫症真的是我一个大病...每次都非得把所有情况都实验出来不可...BUT!!!!!!!!!悲催的是,这么多情况我根本记不住...还是要在写代码的时候不断出错再排错~受不了自己了!不过还是把这部 ...

  2. CSS 外边距(margin)重叠及防止方法

    边界重叠是指两个或多个盒子(可能相邻也可能嵌套)的相邻边界(其间没有任何非空内容.补白.边框)重合在一起而形成一个单一边界. 两个或多个块级盒子的垂直相邻边界会重合.结果的边界宽度是相邻边界宽度中最大 ...

  3. css margin重叠

    父子元素margin(垂直方向)重叠 解决办法: 给子元素添加浮动属性,相应父元素添加必要的清浮动属性: 给父元素添加边缘属性,如padding.border: 同级元素margin(垂直方向)反向重 ...

  4. 清浮动,防止上下margin重叠(浏览器顶部空白崩溃)

    清浮动 父级添加类别! .clearfix{zoom:1;//兼容ie6,7} .clearfix:after{ content:"."; display: "block ...

  5. CSS盒模型和margin重叠

    在 CSS 中,width 和 height 指的是内容区域的宽度和高度.增加内边距.边框和外边距不会影响内容区域的尺寸,但是会增加元素框的总尺寸.(div的实际占用尺寸变打了) 但: 一旦为页面设置 ...

  6. margin重叠

    margin重叠也就是我们常说的CSS 外边距合并,W3C给出如下定义: 外边距合并指的是,当两个垂直外边距相遇时,它们将形成一个外边距. 合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者 ...

  7. margin重叠现象

    1.上下/左右相邻的普通元素margin,不是两者相加之和,而是取最大值,这个现象叫做margin重叠. 2. 普通元素才会发生margin重叠,如果是float元素,就不会发生.margin是两者相 ...

  8. 解决margin重叠的问题

    margin重叠有两种情况: 1.兄弟级的垂直块之间,margin这个属性上下边距,会发生重叠的情况 解决办法:float浮动或display:inline-block 2 .父子级的块之间,子级的上 ...

  9. 2016/2/25 1, margin auto 垂直方向测试 无效 2,margin重叠 3,哪些是块状哪些是内联 4,display:block inline 导航栏把内联转块状最常见+ 扩展

    1.利用margin auto完成首页居中,并自行研究,竖直方向用margin auto,是什么效果#container{width:1002px;margin: 0px auto;}    竖直方向 ...

随机推荐

  1. Spring的IOC控制反转和依赖注入-重点-spring核心之一

    IoC:Inverse of Control(控制反转): 读作"反转控制",更好理解,不是什么技术,而是一种设计思想,好比于MVC.就是将原本在程序中手动创建对象的控制权,交由S ...

  2. Centos-shell-特殊字符

    shell 通配符 # 注意完全不同于正则,类似正则 * 任意至少一个字符 ? 任意一个字符 []   []中任意一个字符,相关字符集a-z A-Z 0-9 shell 重定向 # 重新指定系统标准输 ...

  3. 用ThreadLocal来优化下代码吧

    最近接手了一个老项目,看到一个很有意思的现象. 这个项目中大量的方法入参都会带上user信息,比如这样 它的意图是希望在方法内使用user的信息,但是如此大范围的传递用户信息,第一感觉就是不优雅.那有 ...

  4. 一篇文章带你了解Java OOP思想

    Java OOP 思想深度刨析 Java面向对象编程 面向对象编程简称OOP(Object--对象.Oriendted--导向的.Programming--程序设计) 面向对象通俗来讲,就是指使用丰富 ...

  5. I2C的库函数应用示例

    I2C  Arduino 简单应用举例   例1  多机通信 主机代码:(从编译器串口监视器发送数字1,2,3,4来控制从机的LED亮与灭) 1 #include <Wire.h> 2 v ...

  6. [BJWC 2011]元素

    题目大意: 你有n个二元组(x,y),要求从中任取几个,使得x的值亦或起来不为0,且y之和最大. 题解: 显然是以x来构造线性基的,然而加入元素的个数是有限制的,那当然就是大的先来喽,排个序就OK啦! ...

  7. 树型大融合——NOIP提高组2015 D1T3 【运输计划】

    下午用一个小时看了一下树上差分,打了个差分模板,A了3题,真的爽! 题目描述: 公元2044 年,人类进入了宇宙纪元. L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 ...

  8. 为什么在M3架构中 PC总是返回加4

    由于CPU是3级流水线的方式运行.在执行第一条指令时候,已经对第二条指令译码,对第三条指令取值. PC总是指向正在取值的指令.由于在M3架构中,采用Thumb-2指令,每个指令占据2个字节,所以PC总 ...

  9. 多测师讲解jmeter _图片详解_(全)高级讲师肖sir

  10. 多测师讲解自动化测试 _RF连接数据库_高级讲师肖sir

    RF连接数据库:1.Connect To Database(连接数据库)2.Table Must Exist(表必须存在)3.Check If Exists In Database(查询某条件是否存在 ...