# BFC(块格式化上下文)

Block Formatting Context

# 1).定义

BFC是Web页面的可视化CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域 (opens new window)

它是一个独立的渲染区域,只有块级元素参与,它规定了内部的Block level Box如何布局,并且与这个区域外部毫不相干。

具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性。 (opens new window)

下列方式会创建块格式化上下文:

  • 根元素(<html>)
  • 浮动元素(元素的 float 不是 none)
  • 绝对定位元素(元素的 position 为 absolute 或 fixed)
  • 行内块元素(元素的 display 为 inline-block)
  • 表格单元格(元素的 display为 table-cell,HTML表格单元格默认为该值)
  • 表格标题(元素的 display 为 table-caption,HTML表格标题默认为该值)
  • 匿名表格单元格元素(元素的 display为 table、table-row、 table-row-group、table-header-group、table-footer-group(分别是HTML table、row、tbody、thead、tfoot的默认属性)或 inline-table)
  • overflow 值不为 visible 的块元素
  • display 值为 flow-root 的元素(一个新的 display 属性的值,它可以创建无副作用的BFC)
  • contain 值为 layout、content或 paint 的元素
  • 弹性元素(display为 flex 或 inline-flex元素的直接子元素)
  • 网格元素(display为 grid 或 inline-grid 元素的直接子元素)
  • 多列容器(元素的 column-count 或 column-width 不为 auto,包括 column-count 为 1) column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中(标准变更,Chrome bug)

简单点描述为:

  • 1.根元素或包含根元素的元素
  • 2.浮动元素(float不为none)
  • 3.绝对定位元素(position为absolute或者fixed)
  • 4.display为inline-block,table-cell,table-caption,flow-root
  • 5.overflow值不为visible
  • 6.弹性元素(flex布局)
  • 7.网格元素(grid布局)

# 2).BFC的约束规则 (opens new window)

  • 内部的Box会在垂直方向上一个接一个的放置
  • 垂直方向上的距离由margin决定。(完整的说法是:属于同一个BFC的两个相邻Box的margin会发生重叠(塌陷),与方向无关。)
  • 每个元素的左外边距与包含块的左边界相接触(从左向右),即使浮动元素也是如此。(这说明BFC中子元素不会超出他的包含块,而position为absolute的元素可以超出他的包含块边界)
  • BFC的区域不会与float的元素区域重叠
  • 计算BFC的高度时,浮动子元素也参与计算
  • BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面元素,反之亦然

# 3).BFC的应用

# (1).防止margin重叠

通常情况下,处于同一个BFC下面的两个元素,两者中间的margin值会发生重叠。

【tlm时刻】:同一个BFC下面—————指的是这个包括相邻元素,嵌套元素,只要他们之间没有阻挡(例如边框,非空内容,padding等)就会发生margin重叠。 (opens new window);通常下,可以认为测试的时候的两个div同在html下面。

 <div class="paras-box">
    <p>hello</p>
    <p>hi</p>
</div>
1
2
3
4
p{
    background:#fcc;
    width:200px;
    margin:20px;
}
1
2
3
4
5

这两个p元素每个的margin都是20px,所以两者之间应该是40px的margin。但是实际图上可以看出,其两者之间的margin只有20px,发生了重叠。

image.png

此时可以通过将两个元素放在不同BFC下面解决:

<div class="paras-box">
    <p>hello</p>
    <div class="wapper">
        <p class='p2'>hi</p>
    </div>
</div>
1
2
3
4
5
6

然后触发wapper为一个BFC元素即可,下面的以及上面所列的方式均可,但是有些就会根据自身的属性特点产生一定的副作用(如果没有后代元素的话,下面的都看不出来有什么副作用),推荐一个好用的,没有副作用的display:flow-root;

.wapper{
    /* overflow:hidden; */
    /* display:inline-block; */
    display:flow-root; /*没有副作用*/
    /* display:flex; */
    /* position:absolute; */
    /* overflow: auto; */
}
1
2
3
4
5
6
7
8

display:flow-root:该元素生成一个块容器框,并使用流布局布置其内容。它始终为其内容建立新的块格式化上下文 说明这是CSS2新增的专为建立块格式化上下文的一个属性值

兼容性问题,一般都是直接Can I use一把梭,会发现,其实除了firefox和chrome(当然还有Opera)对这个属性比较友好外,其他浏览器还不太支持 顺便提一下display:flow-root (opens new window)

# 2). BFC 可以阻止元素被浮动元素覆盖--实现两列自适应布局

<div class="box">
    <div class="aside"></div>
    <div class="main"></div>
</div>
1
2
3
4
.box{
    width:300px;
    position:relative;
}
.aside{
    width:100px;
    height: 150px;
    float:left;
    background: #f66;
}
.main{
    height:200px;
    background: #fcc;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

image.png

由于BFC元素有一个规则是其不会覆盖浮动元素,所以只需要让main触发BFC即可。

.main{
    height:200px;
    background: #fcc;
    
    /* display:flow-root; */
    overflow: hidden;
}
1
2
3
4
5
6
7

image.png

# 3).让浮动内容与周围内容等高----【清除浮动】

<div class="box1">
    <div class="child"></div>
</div>
1
2
3
.box1{
    border:5px solid yellow;
    width:300px;
}
.child{
    border:5px solid #f66;
    width:100px;
    height:100px;
}          
1
2
3
4
5
6
7
8
9

image.png

由于BFC计算高度时,会把浮动元素的计算之内,所以可以使box1元素触发BFC即可。

.box1{
    border:5px solid orange;
    width:300px;
    /* overflow:hidden; */
    /* display:inline-block; */
    /* display:flow-root;*/
    /* display:flex; */
    /* position:absolute; */
    /* overflow: auto; */
    /* contain: content; */
    /*display:table;*/
    float:left;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

image.png

BFC清除浮动的后果:

  • 利用float来使父容器形成BFC,父容器高度没有塌陷,但是长度变短了,因为div应用float后会根据内容来改变长度
  • overflow属性会影响滚动条
  • position会改变元素的定位方式,这是我们不希望的
  • display这几种方式依然没有解决低版本IE问题

清除浮动和BFC (opens new window)这篇文章中还讲到了IE清除浮动的问题---最终得到最佳方案:

.clearfix{
    *zoom:1;
}
.clearfix:after{
    content:"";
    display:table;
    clear:both;
}
1
2
3
4
5
6
7
8

CSS清浮动处理(Clear与BFC) (opens new window)这篇文章中详细讲述了clear清除浮动的具体细节:

clear属性是个什么东东呢?clear 属性规定元素的哪一侧不允许其它之前浮动元素

参考: