BFC与浮动

可以用于解决浮动元素/绝对定位元素脱离文档流导致父元素计算内部高度时不会计算他们的情况导致的高度塌陷

BFC

  • BFC即块格式化上下文(Block Formatting Context)。
  • 特点: BFC会包含创建它的元素内部的所有内容,也就是在父元素中添加相应的属性来创建BFC则子元素就不会溢出(始终能被包含在父元素内部)。
  • 注意: 浮动元素作为子元素,而父元素高度不够时都会出现溢出(父元素高度塌陷))的问题,BFC能解决这种问题
  • 不理解的话可以先看下面“浮动元素的高度塌陷”和“创建BFC包含浮动元素解决塌陷”的例子帮助理解
  • 重点补充:如果高度塌陷是因为absolute或fixed子元素脱离文档流,则给父元素设置BFC不管用,得设父元素高度

创建BFC元素的方法

可以通过给元素添加下面的属性,使元素变为BFC

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

注意:块级元素不算BFC!!


BFC布局规则

  1. 内部的Box会在垂直方向,一个接一个地放置。
  2. Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
    • 解决方法:在其中一个Box元素外面再罩一个BFC元素,两个BFC元素之间就不会发生外边距重叠了
  3. 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
  4. BFC的区域不会与float box重叠。
  5. BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
  6. 计算BFC的高度时,浮动元素也参与计算

BFC与浮动

  • BFC对浮动定位(float)与清除浮动(clear)都很重要。浮动定位和清除浮动时只会应用于同一个BFC内的元素
  • 浮动不会影响其它BFC中元素的布局,而清除浮动只能清除同一BFC中在它前面的元素的浮动
  • 外边距折叠(Margin collapsing)也只会发生在属于同一BFC的块级元素之间

浮动元素的高度塌陷

  • 通过高度塌陷这一问题帮助理解BFC的作用
  • 在使用float时我们遇到过高度塌陷的问题:
    高度塌陷
  • 产生原因:浮动元素存在于正常的文档流之外,所以他们在父元素中所占的面积的有效高度为0(高度塌陷)
  • 由于浮动的元素比它旁边的元素高,所以浮动元素溢出了,父元素并没能包含它。
1
2
3
4
<div class="box">
<div class="float">I am a floated box!</div>
<p>I am content inside the container.</p>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
.box {
background-color: rgb(224, 206, 247);
border: 5px solid rebeccapurple;
}

.float {
float: left;
width: 200px;
height: 150px;
background-color: white;
border:1px solid black;
padding: 10px;
}

创建BFC包含浮动元素解决塌陷

方法1:使用overflow属性创建BFC

创建一个会包含这个浮动的BFC,通常的做法是设置父元素 overflow: auto 或者设置其他的非默认的 overflow: visible 的值。

比如,给父元素box的样式添加overflow: auto;
实现效果

设置 overflow: auto => 创建一个新的BFC来包含所有子元素(包括浮动) => 父元素<div>变成布局中的迷你布局,则任何子元素都会被包含进去(包括浮动元素)

overflow副作用

当使用overflow属性只是为了创建BFC的时候,可能会发现一些不想要的问题,比如滚动条或者一些剪切的阴影。另外,对于后续的开发,可能不是很清楚当时为什么使用overflow。所以你最好添加一些注释来解释为什么这样做。

方法2:使用display:flow-root创建BFC

  • flow-root是一个新的 display 属性值,它可以创建无副作用的BFC
  • 在父级元素中使用 display: flow-root 即可创建新的BFC。

比如,给父元素box的样式添加display: flow-root;
实现效果
<div> display: flow-root 属性后,<div> 中的所有内容都会参与BFC,浮动的元素自然不会从底部溢出。


外边距塌陷/合并

百度前端技术学院 第五天学习笔记(CSS盒模型)中提到过“(块之间的)外边距margin折叠”的问题。

解决方法:创建新的BFC包裹其中一个box元素,两个BFC元素之间不存在外边距重叠,即可避免两个相邻box元素之间的 外边距合并 问题。