参考链接

前端精选文摘:BFC 神奇背后的原理

清除浮动的四种方式及其原理理解

MDN: 块级格式化上下文

BFC

BFC 定义

BFC (Block Formatting Context) 直译为”块级格式化上下文”。它是一个独立的渲染区域,只有 Block-level Box 参与, 它规定了内部的 Block-level Box 如何布局,并且与这个区域外部毫不相干。

BFC 布局规则:

  1. 内部的 Box 会在垂直方向,一个接一个地放置。
  2. Box 垂直方向的距离由 margin 决定。属于同一个 BFC 两个相邻 Box 的 margin 会发生重叠
  3. 每个元素的左 margin, 与包含块的左 border 相接触 (对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
  4. BFC 的区域不会与外部浮动盒子重叠。
  5. BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
  6. 计算 BFC 的高度时,浮动元素也参与计算
  7. HTML 结构中,当构建 BFC 区域的元素紧接着一个浮动盒子时,即该浮动盒子的兄弟节点,BFC 区域会首先尝试在浮动盒子的旁边渲染,但若宽度不够,就在浮动元素的下方渲染。[看这里]

BFC 的生成

  1. 根元素,即<html>标签
  2. float属性不为none
  3. positionabsolutefixed
  4. displayflow-rootinline-blocktable-celltable-captionflexinline-flexgridinline-grid
    display 值为 flexinline-flex 元素的直接子元素
    display 值为 gridinline-grid 元素的直接子元素
  5. overflow不为visible,为 auto、scroll、hidden 的块元素(子元素生效)

简单总结

因为BFC内部的元素和外部的元素绝对不会互相影响,因此,

BFC外部存在浮动时,它不应该影响 **BFC** 内部Box的布局,BFC通过变窄,而不与浮动有重叠

同样的,当 BFC内部有浮动时,为了不影响外部元素的布局,BFC计算高度时会包括浮动的高度

个人补充

block formatting context

  • block container => block-level box

inline formatting context

  • line box => inline-level box

flex formatting context

  • flex container => flex item

grid formatting context

  • grid container => grid item

不在正常流中,且其中可包含文字的

  • flex 的元素是 FFC,flex item 里面才是 BFC

  • grid 元素是 GFC,grid item 里面才是 BFC

往 block container 内放另一个 block container,

block container 内的 block container = block container + block-level box = block box = block

block + overflow: visible 不产生 BFC,外面有 BFC,内部不产生 BFC(正常流中的特性)

在生成 BFC 时候,flex 、grid、overflow 管的都是内部块级元素的排列,而不是自身的

下面以边框重叠的解决方案为例,简单对比一下几种生成 BFC 的方式

HTML

  1. <div class="red"></div>
  2. <div class="blue"></div>

CSS

  1. .red {
  2. width: 100px;
  3. height: 100px;
  4. background-color: red;
  5. margin-bottom: 100px;
  6. }
  7. .blue {
  8. width: 100px;
  9. height: 100px;
  10. background-color: blue;
  11. margin-top: 100px;
  12. }

BFC - 图1

float

  1. .blue {
  2. float: left;
  3. }

BFC - 图2

position

  1. .blue {
  2. position: absolute;
  3. }

BFC - 图3

overflow

  1. .blue {
  2. overflow: hidden;
  3. }

BFC - 图4

flex

  1. .blue {
  2. display: flex;
  3. }

BFC - 图5

我们发现,floatposition 对应的解决方案是有效的,而 overflowflex 对应的解决方案是无效的,这是为什么呢?

为了解决问题,我们先来对比一下下面几个属性在 MDN 或 W3C 中的定义,不难发现,

floatposition 强调的是元素本身相对于容器的属性,

overflowflex 则强调的是元素的内容 ( 或子元素 ),或者说,强调的是元素本身为框架。

所以,给当前元素设置 flex 或者 overflow 可能达不到我们想要的 BFC 的效果,因为它们的 BFC 特性是针对子元素而言,而非自身。

float CSS 属性指定一个元素应沿其容器的左侧或右侧放置,允许文本和内联元素环绕它。

CSS position属性用于指定一个元素在文档中的定位方式

CSS属性 overflow 定义当一个元素的内容太大而无法适应 块级格式化上下文 时候该做什么。

display: flex 当放置在流布局中时, 此值会导致元素生成块级的flex 容器

display: inline-flex 当放置在流布局中时, 该值会导致元素生成一个内联级别的flex 容器

所以,在原来的例子的基础上,套上一个父元素,在父元素上设置这些属性即可。

  1. <div class="red"></div>
  2. <div class="blue-father">
  3. <div class="blue"></div>
  4. </div>

overflow

  1. .blue-father {
  2. overflow: hidden;
  3. }

BFC - 图6

flex

  1. .blue-father {
  2. display: flex;
  3. }

BFC - 图7

解决方案有效。