CSS margin合并问题

在CSS当中,相邻的两个盒子(多是兄弟关系也多是祖先关系)的外边距能够结合成一个单独的外边距。这种合并外边距的方式被称为折叠,而且于是所结合成的外边距称为折叠外边距。css

1. 折叠的结果

  1. 两个相邻的外边距都是正数时,折叠结果是它们二者之间较大的值。
  2. 两个相邻的外边距都是负数时,折叠结果是二者绝对值的较大值。
  3. 两个外边距一正一负时,折叠结果是二者的相加的和。

2. 条件

产生折叠的必备条件:margin必须是邻接的
而根据w3c规范,两个margin是邻接的必须知足如下条件:html

  1. 必须是处于常规文档流(非float和绝对定位)的块级盒子,而且处于同一个BFC当中。
  2. 没有线盒,没有空隙(clearance,下面会讲到),没有padding和border将他们分隔开
  3. 都属于垂直方向上相邻的外边距,能够是下面任意一种状况前端

    • 元素的margin-top与其第一个常规文档流的子元素的margin-top
    • 元素的margin-bottom与其下一个常规文档流的兄弟元素的margin-top
    • height为auto的元素的margin-bottom与其最后一个常规文档流的子元素的margin-bottom
    • 高度为0而且最小高度也为0,不包含常规文档流的子元素,而且自身没有创建新的BFC的元素的margin-top和margin-bottom

2.1 条件解读

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

注意:
浮动元素和绝对定位元素不与其余盒子产生外边距折叠是由于元素会脱离当前的文档流,违反了上面所述的两个margin是邻接的条件同时,又由于浮动和绝对定位会使元素为它的内容建立新的BFC,所以该元素和子元素所处的BFC是不相同的,所以也不会产生margin的折叠。segmentfault

可是浮动元素脱离了当前的BFC并不影响它后面的兄弟元素,后面的兄弟元素与浮动元素前面的元素依然在同一个BFC当中,因此,它们之间的margin仍是会折叠的。浏览器

2.2 空隙 clearance

当浮动元素以后的元素设置clear以闭合相关方向的浮动时,根据w3c规范规定,闭合浮动的元素会在其margin-top以上产生必定的空隙(clearance),该空隙会阻止元素margin-top的折叠,并做为间距存在于元素的margin-top的上方。关于这个间距的计算稍微有点复杂,但实际工做中你并不须要去计算它。微信

3. 如何解决

使用BFC解决margin合并问题能够参考这篇文章:CSS中重要的BFC学习

3.1 自身margin合并的状况

  • 加个padding或者border-top/border-bottom

3.2 相邻元素的状况

  1. 相邻元素中间添加一个1px的间隔元素(不推介,由于添加了冗余标签)
  2. 相邻元素加上display: inline-block; 或者gridinline-grid后相邻元素之间的垂直外边距不会合并,不过注意grid的浏览器兼容性不太好。
  3. 相邻元素能够在其中一个元素外面包一层div,并设置任何能触发BFC的属性便可。codepen的DEMO
  4. 浮动与绝对定位之类脱离文档流的元素不发生margin合并

3.3 父子元素的状况

  1. 给父元素添加padding-top值,缺点:增长了一点padding的偏差
  2. 给父元素添加border值,好比border-top:1px solid transparent;,缺点同上
  3. 给父元素或者子元素声明浮动float,缺点:float有时是没必要要的。
  4. 使父元素或子元素声明为绝对定位:position:absolute/fixed;
  5. 给父元素添加属性 overflow:auto/auto/scroll;
  6. 子元素的margin使用父元素的padding代替

网上的帖子大多深浅不一,甚至有些先后矛盾,在下的文章都是学习过程当中的总结,若是发现错误,欢迎留言指出~spa

参考:code

  1. CSS外边距合并的问题
  2. 深刻理解css中的margin属性
  3. 深刻理解BFC和Margin Collapse

PS:欢迎你们关注个人公众号【前端下午茶】,一块儿加油吧~htm

另外能够加入「前端下午茶交流群」微信群,长按识别下面二维码便可加我好友,备注加群,我拉你入群~

相关文章
相关标签/搜索