【前端帮帮忙】第8期 关于BFC,你需要了解的

栏目: CSS · 发布时间: 4年前

内容简介:BFC是耳熟能详的一个东西了,经常听到,其实在项目中也经常用到,比如最常用的清除浮动,自适应两栏布局等等。只是都没有去深究其原理和相关的知识点,今天就一起来好好学习一下吧。要明白MDN对其描述如下:

BFC是耳熟能详的一个东西了,经常听到,其实在项目中也经常用到,比如最常用的清除浮动,自适应两栏布局等等。只是都没有去深究其原理和相关的知识点,今天就一起来好好学习一下吧。

要明白 BFC 是什么,我们要先来了解几个相关的概念。

盒模型

MDN对其描述如下:

当对一个文档进行布局(lay out)的时候,浏览器的渲染引擎会根据标准之一的 CSS基础盒模型(CSS basic box model) ,将所有元素表示为一个个矩形的盒子(box)。CSS决定这些盒子的大小、位置和以及属性(例如颜色、背景、边框尺寸...)。

每个盒子由四个部分(或称区域)组成,其效用由它们各自的边界(Edge)所定义(原文:defined by their respective edges,可能意指容纳、包含、限制等)。如图,与盒子的四个组成区域相对应,每个盒子有四个边界:内容边界 Content edge、内边距边界 Padding Edge、边框边界 Border Edge、外边框边界 Margin Edge。

【前端帮帮忙】第8期 关于BFC,你需要了解的

我们在浏览器的控制台也可以很清楚的看到页面的每一个元素(除了单独的文本元素),其实都是一个盒子:

【前端帮帮忙】第8期 关于BFC,你需要了解的

更加详细的介绍可以参考MDN或者W3C规范的描述:

www.ayqy.net/doc/css2-1/…

视觉格式化模型

MDN 对其描述如下:

CSS视觉格式化模型(visual formatting model)是用来处理和在视觉媒体上显示文档时使用的计算规则。该模型是CSS的基础概念之一。

视觉格式化模型会根据 CSS盒子模型 将文档中的元素转换为一个个盒子,每个盒子的布局由以下因素决定:

  • 盒子的尺寸:精确指定、由约束条件指定或没有指定
  • 盒子的类型:行内盒子(inline)、行内级盒子(inine level)、原子行内级盒子(atomic inine-level)、块盒子(block)
  • 定位方案(position scheme):普通流定位、浮动定位或绝对定位
  • 文档树中的其他元素:即当前盒子的子元素或兄弟元素
  • 视口尺寸与位置
  • 所包含的图片的尺寸
  • 其他的某些外部因素

关于不同类型盒子的介绍,大家可以直接看MDN,写的很详细了,这里就不再阐述。这边着重讲下 定位方案

定位方案

一旦生成了盒子,CSS引擎就需要定位它们以完成布局。在定位的时候,浏览器会根据元素的盒类型和上下文对这些元素进行定位,可以说盒就是定位的基本单位。定位时有三种定位方案,分别是:常规流(即普通流)、浮动流以及绝对定位。

常规流(Normal flow)

  • 在常规流中,盒子一个接着一个排列;
  • 块级格式化上下文 里面,它们 竖着 排列;
  • 行内格式化上下文 里面,它们 横着 排列;
  • positionstaticrelative ,并且 floatnone 时,会触发常规流
  • 对于 静态定位 (static positioning), position: static ,盒的位置是常规流布局里的位置;
  • 对于 相对定位 *(relative positioning), position: relative ,盒偏移位置右这些属性定义: topbottomleftright即使有偏移,仍然保留原有的位置 ,其他常规流不能占用这个位置。

浮动(Floats)

  • 盒成为浮动盒(floating boxes);
  • 它定位于当前行的开头或末尾;
  • 导致常规流环绕在它的周边 ,除非设置 clear 属性;

绝对定位(Absolute positioning)

  • 绝对定位方案, 盒从常规流中被移除 ,不影响常规流的布局;
  • 它的定位相对于它的包含块,相关CSS属性: topbottomleftright
  • 对于 position: absolute ,元素定位相对于最近的一个 relativeabsolutefixed 的父元素,如果没有则相对于 body

FC(Formatting context)

Formatting context是W3C CSS2.1规范中的一个概念。它是页面中一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。最常见的Formatting context有Block formatting context(简称BFC)和Inline formatting context(简称IFC)。

CSS2.1中只有 BFCIFC ,CSS3中还增加了 GFCFFC 。我们主要来讲下 BFC

好了,接下来轮到我们的主角 BFC 出场了。

BFC是什么

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

讲了这么多概念,说下自己的理解,如果有不对的地方,烦请指出,感激不尽。

  • 当我们对一个页面进行布局的时候,浏览器的渲染引擎会根据 CSS的盒模型 将所有元素表示为一个个盒子;
  • 盒子的定义是由 视觉格式化模型 来定义的,盒子的类型可以分为:行内盒子(inline)、行内级盒子(inine level)、原子行内级盒子(atomic inine-level)、块盒子(block);
  • 接下来就是真正的布局开始,浏览器会根据盒子的类型和所处的上下文来对这些元素进行定位,定位有3种方案,分别是:普通流、浮动流和绝对定位。
  • 普通流中的盒子就是属于一个格式化上下文,可能是块或是行内(格式化上下文),但不能两者都是。块级盒参与块格式化上下文。行内级盒参与行内格式化上下文。

是不是可以这样理解: BFC 就是普通流中的元素布局定位时的一个执行环境?

BFC布局规则

  • 内部的Box会在垂直方向,一个接一个的放置。(这边不是很理解,内部的Box不是也可能有行内元素吗?行内元素不是按水平方向来排列吗?这边可能还需要参考行内格式化上下文来理解,还有一个是 writing-mode 属性。)
  • Box垂直方向的距离由 margin 决定。属于同一个 BFC 的两个相邻Box的 margin 会发生重叠
  • 每个元素的margin box的左边,与包含快border box的左边相接触(对于从左往右的格式化,否则相反),即使存在浮动也是如此(除非该盒建立了一个新的块格式化上下文)
  • BFC 的区域不会与float box重叠
  • BFC 就是页面上的一个隔离的独立的容器,容器里面的子元素不会影响到外面的元素,反之亦如此
  • 计算 BFC 的高度时,浮动元素也参与计算

如何创建BFC

  • 根元素
  • float 属性值不为 none
  • positionabsolutefixed
  • displayinline-blocktable-celltable-captionflexinline-flex
  • overflow 不为 visible
  • ...

其实还有很多,这里列出的是一些比较常用的,跟详细的可以看MDN。

通过几个实例来加深理解

1.自适应两栏布局

实现自适应两栏布局的方法有很多,但是我觉得 BFC 的方式应该是最简单的了。

<body>
  <div class="container">
    <div class="side"></div>
    <div class="main"></div>
  </div>
</body>
复制代码
.container {
  width: 400px;    
}

.side {
  float: left;
  width: 100px;
  height: 100px;
  background: lightpink;
}

.main {
  height: 300px;
  background: lightblue;
}
复制代码

页面截图:

【前端帮帮忙】第8期 关于BFC,你需要了解的

根据 BFC 布局规则第3条:

每个元素的margin box的左边,与包含快border box的左边相接触(对于从左往右的格式化,否则相反),即使存在浮动也是如此(除非该盒建立了一个新的块格式化上下文)

即使存在浮动元素 sidemain 的左边依然会与包含快的左边相接触。

根据 BFC 布局规则第4条:

BFC 的区域不会与float box重叠

所以,我们可以给 main 创建一个新的 BFC ,这样就不会跟浮动的 side 重叠了,它会根据包含块的宽度和 side 的宽度,自动变窄。

main 加上 overflow: hidden

main {
  overflow: hidden;
}
复制代码

再来看下效果:

【前端帮帮忙】第8期 关于BFC,你需要了解的

2.清除内部浮动

<div class="parent">
  <div class="child"></div>
</div>
复制代码
.parent {
   width: 200px;
   border: 2px solid blue;
   background: lightblue;
}

.child {
  float: left;
  width: 100px;
  height: 100px;
  border: 2px solid red;
  background: lightcoral;
}
复制代码

页面截图:

【前端帮帮忙】第8期 关于BFC,你需要了解的

可以看到,由于子元素设置了浮动,而父元素又没有设置高度,导致父元素高度塌陷了:没有自动被子元素的高度撑开。

根据 BFC 布局规则第6条:

计算BFC的高度时,浮动元素也参与计算

我们可以给父元素 parent 触发 BFC ,那么它在计算高度时,内部的浮动元素也会参与计算。

.parent {
  overflow: hidden;
}
复制代码

再看下效果:

【前端帮帮忙】第8期 关于BFC,你需要了解的

3.阻止margin重叠

<div class="box">box</div>
<div class="box">box</div>
复制代码
.box {
  width: 200px;
  height: 200px;
  margin: 100px;
  background: red;
}
复制代码

页面截图:

【前端帮帮忙】第8期 关于BFC,你需要了解的

根据 BFC 布局规则第2条:

Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠

可以看到,第一个div的下边距跟第二个的上边距发生了重叠。

重叠的结果按照如下规则计算:

  • 两个相邻的外边距都是正数时,重叠结果是它们两者之间较大的值。
  • 两个相邻的外边距都是负数时,重叠结果是两者绝对值的较大值。
  • 两个外边距一正一负时,重叠结果是两者的相加的和。

产生折叠的必备条件:margin必须是邻接的!

我们只要给其中一个div外层再包裹一层div,然后触发其生成一个新的 BFC ,它们就不会发生重叠了。

<div class="box">box</div>
<div class="new-bfc">
  <div class="box">box</div>
</div>
复制代码
.new-bfc {
  overflow: hidden;
}
复制代码

页面截图:

【前端帮帮忙】第8期 关于BFC,你需要了解的

还有很多其他的例子,比如可以避免文字环绕、多列布局等等,这里就不再一一列举,大家有兴趣的可以自己多尝试下,这里有一个网址可以在线演示,更加直观, 链接地址: www.cnblogs.com/xiaohuochai…

创建BFC的新方式

我们上面举的例子都是通过 overflow 来创建 BFC ,但是其实这个方法会有两个问题。

  1. 这些方法本身是有自身的设计目的的,所以在使用它们创建 BFC 时可能会存在一些副作用。例如,使用 overflow 创建 BFC 后,在某些情况下可能会看到出现一个滚动条或者元素内容被裁切。这是由于 overflow 属性的设计是用来让你告诉浏览器如何定义元素的溢出状态的。浏览器执行了它最基本的定义。
  2. 另一个问题是,即使在没有出现副作用的情况下,使用 overflow 也可能会使另一个开发人员感到困惑。他们可能会各种猜想:这里为什么要把 overflow 的值设为 autohidden ?原来的开发人员这样做的意义是什么?原来的开发人员是想让这里出现滚动条吗?

所以实际项目开发中,还需要根据项目的需求来选择合适的方法,最好也能在代码里写明注释。

那有没有什么更好的方式呢?CSS工作组定义了一个新的属性值: display: flow-root

你可以使用 display: flow-root 安全的创建 BFC ,来解决上文中提到的各种问题:自适应两栏布局、清除内部浮动、阻止margin重叠等等。

caniuse上 display: flow-root 在各浏览器的兼容情况,看图:

【前端帮帮忙】第8期 关于BFC,你需要了解的

目前来看,兼容性还是差了一点。

有关于 flow-root 的详细介绍可以看这篇文章: www.w3cplus.com/css3/displa…

BFC概念理解

可以想象一下, BFC 就相当于我们现实中的一个纸箱(盒子),箱子里面的东西的放置(布局)是不会受到外部其他东西的影响的,它形成了一个独立的封闭的区域。当然它里面东西的放置(布局)也不会影响到外面的东西。

最后

感谢您的阅读,希望对你有所帮助,希望你能通过这篇文章能对 BFC 有一个比较全面的理解并能实际应用到项目开发中。本人水平有限,如果文中有不当的地方烦请指正,感激不尽。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

信息论、推理与学习算法

信息论、推理与学习算法

麦凯 / 高等教育出版社 / 2006-7 / 59.00元

本书是英国剑桥大学卡文迪许实验室的著名学者David J.C.MacKay博士总结多年教学经验和科研成果,于2003年推出的一部力作。本书作者不仅透彻地论述了传统信息论的内容和最新编码算法,而且以高度的学科驾驭能力,匠心独具地在一个统一框架下讨论了贝叶斯数据建模、蒙特卡罗方法、聚类算法、神经网络等属于机器学习和推理领域的主题,从而很好地将诸多学科的技术内涵融会贯通。本书注重理论与实际的结合,内容组......一起来看看 《信息论、推理与学习算法》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具