自从看了这篇文章我也明白css中的BFC了,这也太厉害了

前言

BFC是css中的一个重要,也经常会在面试中问到。想当年,小编在面试时被问到BFC也是一脸蒙圈,同时小编有时候也会面试一些其他人,有的甚至没听过这个的概念,也可能在工作中,有的人无意中用到了BFC却不知道它的概念。因此,今天有必要再把这个问题拿出来说一说了。

一、简介

所谓的文档流,就好比如一块块的正方形组成的一个整体,而这些正方形就代表着每个div。当某个div脱离了这个整体,也就代表他脱离了文档流。然后下一个div就会来填补脱离的div的位置。

我们常说的文档流其实分为定位流、浮动流、普通流三种。而普通流其实就是指BFC中的FC。FC(Formatting Context),直译过来是格式化上下文,它是页面中的一块渲染区域,有一套渲染规则,决定了其子元素如何布局,以及和其他元素之间的关系和作用。

普通流

  1. 在常规流中,盒一个接着一个排列;
  2. 在块级格式化上下文里面, 它们竖着排列;
  3. 在行内格式化上下文里面, 它们横着排列;
  4. 当position为static或relative,并且float为none时会触发常规流;
  5. 对于静态定位(static positioning),position: static,盒的位置是常规流布局里的位置;
  6. 对于相对定位(relative positioning),position: relative,盒偏移位置由top、bottom、left、right属性定义。即使有偏移,仍然保留原有的位置,其它常规流不能占用这个位置。

浮动流

  1. 左浮动元素尽量靠左、靠上,右浮动同理;
  2. 这导致常规流环绕在它的周边,除非设置 clear 属性;
  3. 浮动元素不会影响块级元素的布局;
  4. 但浮动元素会影响行内元素的布局,让其围绕在自己周围,撑大父级元素,从而间接影响块级元素布局;
  5. 最高点不会超过当前行的最高点、它前面的浮动元素的最高点;
  6. 不超过它的包含块,除非元素本身已经比包含块更宽;
  7. 行内元素出现在左浮动元素的右边和右浮动元素的左边,左浮动元素的左边和右浮动元素的右边是不会摆放浮动元素的;

定位流

  1. 绝对定位方案,盒从常规流中被移除,不影响常规流的布局;
  2. 它的定位相对于它的包含块,相关CSS属性:top、bottom、left、right;
  3. 如果元素的属性position为absolute或fixed,它是绝对定位元素;
  4. 对于position: absolute,元素定位将相对于上级元素中最近的一个relative、fixed、absolute,如果没有则相对于body;

二、BFC的概念

块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。这是MDN上对BFC的解释。

BFC 指一个独立的渲染区域或者说是一个隔离的独立容器。用于决定这块盒子的布局及浮动相互影响范围的一个区域,只有块级元素盒子(Block-level box)参与,它规定了内部的块级元素盒子(Block-level box)如何布局,并且与这个区域外部毫不相干。

注意:
一个BFC的范围包含创建该上下文元素的所有子元素,但不包括创建了新BFC的子元素的内部元素。这从另一方角度说明,一个元素不能同时存在于两个BFC中。因为如果一个元素能够同时处于两个BFC中,那么就意味着这个元素能与两个BFC中的元素发生作用,就违反了BFC的隔离作用。

三、BFC的特征

(1)BFC内部,盒子由上至下按顺序进行排列,其间隙由盒子的外边距决定,并且,当同一个BFC中的两个盒子同时具有相对方向的外边距时,其外边距还会发生叠加(Margin Collapse);

(2)BFC内部,无论是浮动盒子还是普通盒子,其左总是与包含块的左边相接触(从右到左的的格式,否则为与右边框相接触);

(3)BFC 区域不会与float box区域相叠加;

(4)BFC内外布局不会相互影响;

(5)计算BFC高度的时候,浮动元素的高度也计算在内。

四、形成BFC的条件

1.根元素:html;
2. 浮动元素:float除none以外的值;
3. 绝对定位元素:position的值为absolute和fixed;
4. overflow的计算值(Computed)不为 visible 的块元素;
5. contain的值为 layout、content 或 paint 的元素;
6. display的值为:
(1) 行内块元素:inline-block;
(2) 表格单元格:table-cell,HTML表格单元格默认为该值;
(3) 表格标题:table-caption,HTML表格标题默认为该值;
(4) 匿名表格单元格元素:table、table-row、 table-row-group、 table-header-group、table-footer-group(分别是HTML table、row、tbody、thead、tfoot 的默认属性)或 inline-table);
(5) flow-root 的元素;
(6) 弹性元素:flex 或 inline-flex 元素的直接子元素;
(7) 网格元素:grid 或 inline-grid 元素的直接子元素;

7.多列容器:元素的column-count或 column-width (en-US) 不为 auto,包括 column-count 为 1;

8.column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中 。

五、BFC的应用

1.阻止相邻元素的margin合并

BFC内部,盒子由上至下按顺序进行排列,其间隙由盒子的外边距决定,并且,当同一个BFC中的两个盒子同时具有相对方向的外边距时,其外边距还会发生叠加(Margin Collapse)。

<div class="container0">
  <div class="box1"></div>
  <div class="box2"></div>
</div>
.container0 {
    
    
  width: 400px;
  border: 1px solid red;
}
.container0 .box1 {
    
    
  height: 60px;
  margin: 30px 0;
  background-color: red;
}
.container0 .box2 {
    
    
  height: 60px;
  margin: 60px 0;
  background-color: red;
}

图片

第一个子盒子有上边距(不会发生margin穿透的问题);两个子盒子的垂直距离为100px而不是150px,因为垂直外边距会折叠,间距以较大的为准。由此可见,box1和box2两个相邻元素的margin发生了合并。

当使用BFC后:

<div class="container1">
  <div class="wrapper">
    <div class="box1"></div>
 </div>
 <div class="box2"></div>
</div>
.container1 {
    
    
  width: 400px;
  border: 1px solid red;
}
.container1 .wrapper {
    
    
  // 使用BFC
  overflow: hidden;
}
.container1 .wrapper .box1 {
    
    
  height: 60px;
  margin: 30px 0;
  background-color: red;
}
.container1 .box2 {
    
    
  height: 60px;
  margin: 60px 0;
  background-color: red;
}

图片

2.BFC区域不会与float box区域相叠加

(1)两栏布局。左边固定宽度,右边不设宽,因此右边的宽度自适应,随浏览器窗口大小的变化而变化。

<div class="container3">
  <div class="column"></div>
 <div class="column"></div>
</div>
.container3{
    
    
  overflow: hidden;
}
.container3 .column:nth-of-type(1) {
    
    
  float: left;
  width: 200px;
  height: 300px;
  margin-right: 10px;
  background-color: red;
}
.container3 .column:nth-of-type(2) {
    
    
  overflow: hidden;/*创建bfc */
  height: 300px;
  background-color: blue;
}

图片

(2)还有三栏布局。左右两边固定宽度,中间不设宽,因此中间的宽度自适应,随浏览器的大小变化而变化。

<div class="container4">
  <div class="column"></div>
 <div class="column"></div>
 <div class="column"></div>
</div>
.container4 .column:nth-of-type(1),
.container4 .column:nth-of-type(2) {
    
    
    float: left;
    width: 100px;
    height: 300px;
    background-color: green;
}
.container4 .column:nth-of-type(2) {
    
    
  float: right;
}
.container4 .column:nth-of-type(3) {
    
    
  overflow: hidden;  /*创建bfc*/
  height: 300px;
  background-color: red;
}

在这里插入图片描述

3.阻止元素被浮动元素覆盖

也可以用来防止字体环绕浮动的盒子会遮盖下面的盒子,但是下面盒子里的文字是不会被遮盖的,文字反而还会环绕浮动的盒子。这也是一个比较有趣的特性。

先来看一个文字环绕效果:

<div class="container5">
  <div class="left">我是box1</div>
  <p>我是box2,人生得意须尽欢,莫使金樽空对月。天生我材必有用,千金散尽还复来。人生得意须尽欢,    莫使金樽空对月。天生我材必有用,千金散尽还复来。
</div>
.container5 {
    
    
  overflow: hidden;
  width: 300px;
  margin: 100px 0;
}
.container5 .left {
    
    
  float: left;
  width: 80px;
  height: 80px;
  background-color: yellow;
}
.container5 p {
    
    
  background-color: green;
  margin: 0;
  padding: 0;
}

图片

在上图中的box2为p元素。正如我们所看到的,这个p元素并没有移动,但是它却出现在浮动元素的下方。p元素的line boxes(指的是文本行)进行了移位。此处line boxes的水平收缩为浮动元素提供了空间。随着文字的增加,因为line boxes不再需要移位,最终将会环绕在浮动元素的下方,因此文字环绕的情况。

这时候其实第二个元素有部分被浮动元素所覆盖,(但是文本信息不会被浮动元素所覆盖) 如果想避免元素被覆盖,可触发第二个元素的 BFC 特性,在第二个元素中加入 overflow: hidden,就会变成:

<div class="container6">
  <div class="left">我是box1</div>
  <p>我是box2,人生得意须尽欢,莫使金樽空对月。天生我材必有用,千金散尽还复来。人生得意须尽欢,    莫使金樽空对月。天生我材必有用,千金散尽还复来。
</div>
.container6 {
    
    
  overflow: hidden;
  width: 400px;
}
.container6 .left {
    
    
  float: left;
  width: 80px;
  height: 80px;
  background-color: yellow;
}

.container6 p {
    
    
  // 触发
  overflow: hidden;
  background-color: green;
  margin: 0;
  padding: 0;
}

图片

4.BFC包含浮动的块

BFC可以包含浮动的元素(清除浮动)

<div class="container7">
  <div class="box"></div>
</div>

// css
.container {
    
    
  border: 1px solid red;
}
.container .box {
    
    
  float: left;
  width: 100px;
  height: 100px;
  background: blue;
}

图片

由于容器内元素浮动脱离文档流,导致容器只剩下2px边距高度。

采用BFC后:

<div class="container7">
  <div class="box"></div>
</div>

// css
.container {
    
    
  // 创建BFC
  overflow: hidden;
  border: 1px solid red;
}
.container .box {
    
    
  float: left;
  width: 100px;
  height: 100px;
  background: blue;
}

在这里插入图片描述

5.BFC中的盒子对齐

在BFC中,每个盒子的左外边框紧挨着包含块的左边框(从右到左的格式,则为紧挨右边框)。即使存在浮动也是这样的(尽管一个盒子的边框会由于浮动而收缩),除非这个盒子的内部创建了一个新的BFC浮动,盒子本身将会变得更窄)。

<div class="container2">
  <div class="box1"></div>
  <div class="box2"></div>
  <div class="box3"></div>
  <div class="box4"></div>
</div>
.container2 {
    
    
  position: absolute;  /* 创建一个BFC环境*/
  height: auto;
  background-color: #eee;
  height: 20px;
}
.container2 .box1 {
    
    
  width: 300px;
  background-color: red;
  height: 50px;
}
.container2 .box2 {
    
    
  width: 400px;
  background-color: green;
  height: 50px;
}
.container2 .box3 {
    
    
  float: left;
  width: 100px;
  background-color: yellow;
  height: 25px;
}
.container2 .box4 {
    
    
  width: 200px;
  height: 50px;
  background-color: purple;
}

在这里插入图片描述

在上图中我们可以看到,BFC内部,无论是浮动盒子还是普通盒子,其左总是与包含块的左边相接触(从右到左的的格式,则为与右边框相接触)。在最后一个盒子里我们可以看到尽管那里有一个浮动元素(黄色)在它的左边,另一个元素(紫色)仍然紧贴着包含块的左边框。

六、总结

写在最后的建议,创建BFC时最好的方法是使用overflow:hidden,因为overflow:hidden对布局的影响最小,只需要注意盒子内内容的高度,避免出现滚动条即可。

猜你喜欢

转载自blog.csdn.net/qq_39327418/article/details/125824218