原载:Smallni | http://www.smallni.com/collapsing-margin/

恩,margin叠加一直是个问题,也是我们一直会遇到的问题,很久以前就想把这个知识点整理下,做一个详细的讲解和分析。前一段时间知乎上有人问了这个问题,刚好克军也做了个回答,但回答的不尽其然,并且我做了自己的分析。刚好今天写到自己的博客里,并做一个更详细的探讨。

今天主要介绍的就是:到底神马是外边距叠加?神马情况下外边距会叠加?如何避免外边距叠加?

外边距叠加的定义

请先阅读w3c关于collapsing-margin的官方介绍:

In CSS, the adjoining margins of two or more boxes (which might or might not be siblings) can combine to form a single margin. Margins that combine this way are said to collapse, and the resulting combined margin is called a collapsed margin.

在CSS中,两个或多个毗邻(父子元素或兄弟元素)的普通流中的块元素垂直方向上的 margin 会发生叠加。这种方式形成的外边距即可称为外边距叠加(collapsed margin)。

1、两个或多个

说明其数量必须是大于一个,又说明,叠加是元素与元素间相互的行为,不存在 A 和 B 折叠,B 没有和 A 叠加的现象。

2、毗邻

是指没有被非空内容、padding、border 或 clear 分隔开,说明其位置关系。

注意一点,在没有被分隔开的情况下,一个元素(非浮动元素等)的 margin-top 会和它普通流中的第一个子元素的 margin-top 相邻; 只有在一个元素的 height 是 “auto” 的情况下,它的 margin-bottom 才会和它普通流中的最后一个子元素(非浮动元素等)的 margin-bottom 相邻。

3、垂直方向

是指具体的方位,只有垂直方向的 margin 才会叠加,也就是说,水平方向的 margin 不会发生叠加的现象。

4、普通流

何为普通流?浮动(float)不是普通流,绝对定位(absolute)也不是普通流,恩,所以我们平常最普通的按序写的结构代码即为普通流。

何时会发生margin叠加?

margin叠加会发生在2种关系下,一种是父子元素,一种是兄弟元素。

来看demo:

1

2

3

<div style="width: 500px; background: #000; height: auto; margin: 40px 0;">

<div style="margin: 50px 0; width: 100px; height: 100px; background: #F90;">asdasd</div>

</div>

很明显,我们发现父元素和子元素发生了margin叠加,但要注意是第一个子元素。

再来看下面的DEMO:

1

2

<div style="width:100px; height:100px; background:#000; margin:40px 0; "></div>

<div style="margin:50px 0; width:100px; height:100px; background:#F90;">asdasd</div>

恩,相邻的兄弟元素,上面的元素margin-bottom为40px,下面元素的margin-top为50px,最后你会发现2个元素垂直方向上的margin为50px,的确是发生叠加了,如果不发生折叠应该是50+40=90px。可是折叠了为什么是50px而不是40px?这涉及到了外边距叠加时的具体计算方法,下面会为大家讲解。

如何避免外边距叠加?

避免外边距叠加,其实很简单:外边距发生叠加的4个必要条件(2个或多个、毗邻、垂直方向、普通流),破坏任一个即可。

我们主要来谈一下“毗邻”,只有理解“毗邻”的概念之后,让元素互相之间不毗邻才能元素避免外边距的叠加。

毗邻不仅仅是兄弟元素之间,也有可能在父子元素之间,元素之间的外边距叠加只有在四种情况下才能叫毗邻:

  • 一个元素的margin-top和它的第一个子元素的margin-top
    top margin of a box and top margin of its first in-flow child
  • 普通流中一个元素的margtin-bottom和它的紧邻的兄弟元素的的margin-top
    bottom margin of box and top margin of its next in-flow following sibling
  • 一个元素(height为auto)的margin-bottom和它的最后一个子元素的margin-bottom
    bottom margin of a last in-flow child and bottom margin of its parent if the parent has ‘auto’ computed height
  • 一个没有创建BFC、没有子元素、height为0的元素自身的margin-top和margin-bottom
    top and bottom margins of a box that does not establish a new block formatting context and that has zero computed ‘min-height’, zero or ‘auto’ computed‘height’, and no in-flow children

以上4种情况之间的元素都可能会发生外边距的折叠(最后一个是元素自身),但还要注意的是以上4种关系形成毗邻还要加一个条件:元素之间没有被非空内容paddingborder clear 分隔开。

其中第一条父子元素要没有被非空内容、padding、border隔开,第二条兄弟元素之间要没有被非空内容隔开,第三条父子元素没之间要没有被非空内容、padding、border隔开。听起来可能有点乱,先上DEMO后上图,希望大家好理解一点:

1

2

3

4

5

<div style="margin:100px 0; background:#990;">

<div style="height:100px; border:1px solid #009; margin:100px 0;">A</div>

<div style="height:100px 0; border:1px solid #009; margin:100px 0;">B</div>

<div style="height:100px; border:1px solid #009; margin:100px 0">C</div>

</div>

W3C官方对于毗邻元素的margin-collapsing总结出了如下规则:

  • Margins between a floated box and any other box do not collapse (not even between a float and its in-flow children).
  • Margins of elements that establish new block formatting contexts (such as floats and elements with ‘overflow’ other than ‘visible’) do not collapse with their in-flow children.
  • Margins of absolutely positioned boxes do not collapse (not even with their in-flow children).
  • Margins of inline-block boxes do not collapse (not even with their in-flow children).
  • The bottom margin of an in-flow block-level element always collapses with the top margin of its next in-flow block-level sibling, unless that sibling has clearance.
  • The top margin of an in-flow block element collapses with its first in-flow block-level child’s top margin if the element has no top border, no top padding, and the child has no clearance.
  • The bottom margin of an in-flow block box with a ‘height’ of ‘auto’ and a ‘min-height’ of zero collapses with its last in-flow block-level child’s bottom margin if the box has no bottom padding and no bottom border and the child’s bottom margin does not collapse with a top margin that has clearance.
  • A box’s own margins collapse if the ‘min-height’ property is zero, and it has neither top or bottom borders nor top or bottom padding, and it has a ‘height’ of either 0 or ‘auto’, and it does not contain a line box, and all of its in-flow children’s margins (if any) collapse.

英文好的直接读,英文不好的就勉强看我的翻译吧:

  • 浮动元素和其他任何元素之间不发生外边距叠加 (包括和它的子元素).
  • 创建了BFC的元素不会和它的子元素发生外边距叠加
  • 绝对定位元素和其他任何元素之间不发生外边距叠加(包括和它的子元素).
  • inline-block元素和其他任何元素之间不发生外边距叠加 (包括和它的子元素).
  • 普通流中的块级元素的margin-bottom永远和它相邻的下一个块级元素的margin-top叠加(除非相邻的兄弟元素clear)
  • 普通流中的块级元素(没有border-top、没有padding-top)的margin-top和它的第一个普通流中的子元素(没有clear)发生margin-top叠加
  • 普通流中的块级元素(height为auto、min-height为0、没有border-bottom、没有padding-bottom)和它的最后一个普通流中的子元素(没有自身发生margin叠加或clear)发生margin-bottom叠加
  • 如果一个元素的min-height为0、没有border、没有padding、高度为0或者auto、不包含子元素,那么它自身的外边距会发生叠加

亲,你晕了吗,反正我看完这些全部是晕的差不多了,但不要烦,一定要定下心来,总结出一些规律出来,如下:

1.父子元素(分2种情况)之间发生margin叠加的条件:
  1. 父元素和第一个子元素发生margin-top叠加

    • 父元素没有创建BFC
    • 父元素和第一个子元素之间没有非空内容
    • 父元素没有border-top
    • 父元素没有padding-top
  2. 父元素和最后一个子元素发生margin-bottom叠加
    • 父元素没有创建BFC
    • 父元素height为auto、min-height为0
    • 父元素和最后一个子元素之间没有非空内容
    • 父元素没有border-bottom
    • 父元素没有padding-bottom

2种情况都总结了,那么让他们不发生外边距叠加也就显得很容易了:

  • 为父元素创建BFC
  • 为父元素设置相应的padding或者border
2.兄弟元素之间发生外边距叠加的条件:
  • 兄弟元素都不是float元素
  • 兄弟元素都不是absolute元素
  • 兄弟元素都不是inline-block元素

那么让它们之间不发生外边距叠加也显得很容易了啊:

  • 让兄弟元素float
  • 让兄弟元素absolute
  • 让兄弟元素inline-block

恩,对于这个解决外边距折叠的方法你满意么?!可是有时我们根本不需要给元素浮动或者绝对定位或者行内块级啊!所以这根本是一个很坑爹的解决方案。那么如何解决?

其实外边距叠加margin-collapsing一直以来就是W3C所制定的一个规范,为了防止元素之间不小心同时设置了margin而不是期望中的效果,这本是一个合理存在的东西却被我们当做BUG来处理,这也是一个历史遗留了很久的问题,不要把它当做BUG来看,当做一个规范来看吧。其实最好的解决方案是在写结构的时候尽量去写一个方向的margin(top or bottom),这样不就不会发生这样的问题了吗?

前端是一个知识面很广很深的行业,不一定你每样东西了解一点就很牛逼的,还需要有专研精神,因为有时一个很简单的问题可能就反应出你对基础知识和原理的理解。理解margin-collapsing这个概念对于我们日后的学习还是很有帮助的,在没写这篇文章之前,如果没有去详细看W3C的原文,我也不知道一个元素自身会发生外边距叠加。

各种情况,熟记于心,才能在下次写代码时得心应手。

PS:外边距叠加时的计算方法本人不做更多的解释,这里有很详细很好的解释

外边距叠加collapsing-margin的更多相关文章

  1. Margin外边距叠加

    外边距(Margin)叠加 只有普通文档流中块级元素(块框)的垂直外边距才会发生外边距叠加.行内框.浮动框和绝对定位框之间的外边距不会叠加 两个相邻兄弟块框 父元素与子元素,并 父元素没有内边距或边框 ...

  2. 内层div的margin-top影响外层div——引出外边距合并Collapsing margins

    内层div的margin-top影响外层div——引出外边距合并Collapsing margins 作者:zccst 今天才算是了解边距合并.正如一位前辈所言,每一个CSS的坑,都让你学到不少知识. ...

  3. 【21】外边距折叠(collapsing margins)

    [21]外边距折叠(collapsing margins) 外边距合并指的是,当两个垂直外边距相遇时,它们将形成一个外边距. 合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者. [注意]m ...

  4. CSS外边距叠加问题

    CSS外边距叠加就是margin-collapse,边距合并指的是,当两个垂直外边距相遇时,它们将形成一个外边距,水平边 距永远不会重合.重叠结果计算规则:①.两个相邻的外边距都是正数时,折叠结果是它 ...

  5. Css 外边距折叠(collapsed margin ) 浅析

    Css 外边距折叠(collapses margin ) a.先来看看w3c 文档对于外边距折叠的定义: In CSS, the adjoining margins of two or more bo ...

  6. CSS概念 - 可视化格式模型(一) 盒模型与外边距叠加

    可以参考<精通CSS 高级WEB标准解决方案>第三章. 可视化格式模型 可视化格式模型要掌握的3个最重要的CSS概念是 浮动.定位.盒模型. 这些概念控制在页面上安排和显示元素的方式, 形 ...

  7. 认识W3C标准盒子模型,理解外边距叠加

    概述: 注:加粗斜体字是非常重要的概念,决定着你是不是能看懂那句话,所以不懂的请一定要搜索一下. 页面上的每个元素,都在一个矩形框里.   每个矩形框都是一个盒模型.   每个盒模型都由内容区域(co ...

  8. 区分内边距与外边距padding和margin

    以两个并排显示的div为例说明. 现在两个div都有背景颜色, 右边的div中有几行p, 若是想要使两个div之间有间隔, 即两块带了颜色区域之间产生空隙, 则给div的css中外边距margin赋值 ...

  9. Collapsing Margin:外边距叠加

    参考:http://www.smallni.com/collapsing-margin/ http://www.cnblogs.com/v10258/p/3530290.html

随机推荐

  1. BZOJ 1048 [HAOI2007]分割矩阵

    1048: [HAOI2007]分割矩阵 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 623  Solved: 449[Submit][Status ...

  2. 微软Azure Services Bus中的工作流

    在Azure Services Platform上对于工作流服务的支持,一直是我很感兴趣的内容.当然也是疑问 比较多的领域.鉴于这方面的资料太少,所以今天就从AzureServicesKit中的一个D ...

  3. 暴力求解——除法 Division,UVa 725

    Description Write a program that finds and displays all pairs of 5-digit numbers that between them u ...

  4. Velocity常用方法

    1.字符串替换 replace#if($!{name} != '')#set($tempName = $!{name})#set($tempName = $tempName.Replace('abc' ...

  5. JavaScript中的声明提升

    JavaScript中变量或者函数的声明会被提升(赋值语句不会被提升)到当前函数主体的顶部,不管这个声明是否出现在不可到达的地方. var test = 1; function f() { if(!t ...

  6. 数据结构算法集---C++语言实现

    //数据结构算法集---C++语言实现 //各种类都使用模版设计,可以对各种数据类型操作(整形,字符,浮点) /////////////////////////// // // // 堆栈数据结构 s ...

  7. [Locked] Two Sum

    Two Sum II - Input array is sorted Given an array of integers that is already sorted in ascending or ...

  8. J - Invitation Cards

    题目大意:邀请卡 在电视的时代,没有多少人会去剧院观看演出.古老的喜剧演员 Malidinesia知道这个事实.他们想传播戏剧尤其是古老的戏剧,他们在邀请卡上打印必要的信息和一些节目,一些学生被雇佣过 ...

  9. git如何clone所有的远程分支

    问题: 文/赖忠标 周末在家里改了下代码,新建了个angular版本的分支,然后push到coding.net上面了. 今天,到公司却不知道怎么拉取这个angular分支到公司的电脑上面.如下图(1) ...

  10. call, apply的用法意义以及区别是什么

    call和apply没有什么大的区别,两者的作用都是:改变对象的this指向的内容. 他们的写法不同,如下: func.call(func1, var1, var2, var3); func.appl ...