问题描述

在做项目的过程中,我发现了浏览器渲染的一个特殊的点:外边距坍塌!
只有普通文档流中块框的垂直外边距才会发生外边距合并。行内框、浮动框或绝对定位之间的外边距不会合并。

哭泣!!
在父子块状元素的如上图下面部分的样式,如果我们不想让浏览器执行这个默认操作,有如下的解决方法:

  1. 父元素是BFC元素
  2. 父元素拥有border
  3. 父元素拥有padding
  4. 子元素是可置换元素或display为inline-block、inline-table、table-caption的元素

BFC? 这是什么? 让我们细细道来。

在 普通流 中的盒子会参与一种格式上下文,这个盒子可能是块盒也可能是行内盒,但不可能同时是块盒又是行内盒。块级盒参与块级格式上下文( BFC ),行内级盒参与行级格式上下文( IFC )。BFC内部元素和外部元素不会互相影响。

除了BFC和IFC,我们的flex布局参加 FFC( flex formatting context ) , grid布局参加 GFC(grid formatting context)

BFC

BFC(Block Formatting Context,属于普通流) ,独立渲染区域,区域内 垂直方向上 相邻的块级元素会发生margin合并

触发BFC特性

  • body 根元素
  • 浮动元素:float 除 none 以外的值
  • position的值不为 static 或 relative (absolute、fixed)
  • display 为 inline-block、table-cells、flex、grid
  • overflow 除了 visible 以外的值 (hidden、auto、scroll)

BFC的特性

  1. 子元素的CSS样式不会影响BFC元素外部
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//bfc
<body >
<div style="margin: 20px;overflow: hidden;background-color: #F6B7B7">
<div style="margin: 20px;">我是块级元素,margin为20</div>
<div style="margin: 20px;">我是块级元素,margin为20</div>
</div>
<div style="margin: 20px;overflow: hidden;background-color: #F6B7B7">
<div style="margin: 20px;">我是块级元素,margin为20</div>
<div style="margin: 20px;">我是块级元素,margin为20</div>
</div>
</body>

//普通流
<body >
<div style="background-color: #F6B7B7">
<div style="margin: 20px;">我是块级元素,margin为20</div>
<div style="margin: 20px;">我是块级元素,margin为20</div>
</div>
<div style="background-color: #F6B7B7">
<div style="margin: 20px;">我是块级元素,margin为20</div>
<div style="margin: 20px;">我是块级元素,margin为20</div>
</div>
</body>

说明:
普通块级元素,其子元素的margin-top,不会隔开自身与父元素(普通块级元素),但是会作用到父元素外部(将父元素和叔伯元素或祖父元素隔开);
BFC元素,作为一个独立、封闭的渲染区域,其子元素的margin-top,则会隔开自身与父元素(BFC元素),而不会影响到父元素外部;

  1. 浮动子元素参与BFC父元素的高度计算,也就是BFC元素能够识别浮动元素(将元素声明为BFC元素,也是clearfix解决父元素塌陷问题的一种常用方法)
    1
    2
    3
    4
    5
    6
    7
    <div style="background-color: #F6B7B7">
    <div style="margin: 20px;float: left;">我是块级元素,margin为20</div>
    </div>

    <div style="margin: 20px;overflow: hidden;background-color: #F6B7B7">
    <div style="margin: 20px;float: left;">我是块级元素,margin为20</div>
    </div>
  1. 占据文档流的BFC元素(可使用overflow: auto创建),能够识别浮动的兄弟元素;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <div style="margin: 20px;background-color: #F6B7B7">
    <div style="margin: 20px;float: left;background-color: #890909">我是浮动元素</div>
    <div style="margin: 20px;background-color: #FFE0E0">我是普通元素呀呀呀呀呀呀呀呀</div>
    </div>

    <div style="margin: 20px;background-color: #F6B7B7">
    <div style="margin: 20px;float: left;background-color: #890909">我是浮动元素</div>
    <div style="margin: 20px;overflow: hidden;background-color: #FFE0E0">我是BFC块呀呀呀呀呀呀呀呀呀</div>
    </div>
  1. 占据文档流的BFC元素(可使用overflow: auto创建),width为auto时,会占满当前行的剩余宽度,但margin-left设置没有用; 如上图,BFC元素设置了margin-left,但是没有作用。

总结

BFC会阻止垂直外边距(margin-top、margin-bottom)折叠
BFC不会重叠浮动元素
BFC高度可以包含浮动

那么,IFC又是什么?

IFC

在IFC中,盒子水平放置,一个接着一个,从包含块的顶部开始。水平margins,borders,和padding在这些盒子中被平分。这些盒子也许通过不同的方式进行对齐:他们的底部和顶部也许被对齐,或者通过文字的基线进行对齐。矩形区域包含着来自一行的盒子叫做line box。line box 的宽度由浮动情况和它的包含块决定。line box的高度由 line-height 的计算结果决定。

具体介绍可见下一篇~《页面布局的简单介绍》