Appearance
什么是 BFC,IFC,GFC,FFC
Box 是 CSS 布局的对象和基本单位,一个页面由很多 Box 组成。
Box 的类型由元素的类型和 display 的属性决定,不同类型的 Box,有其不同的 Formatting Context。
在普通流中的盒子会参与一种格式化上下文,这个盒子可能是块盒或者行盒,但不可能同时是块盒又是行盒,块盒参与 BFC 行盒参与 IFC
Box 类型种类
block-level box : display 为 block,list-item,table 的元素,会生成 block-level box,并参与 Block Formatting Context。
inline-level box: display 为 inline,inline-block,inline-table 的元素,会生成 inline-level box.并参与 Inline Formatting Context。
grid-level box : display : grid
flex-level box : display : flex | inline-flex
BFC (block Formatting Context 块级格式化上下文),规定了内部的 Block-level Box 如何布局。
布局规则:
内部的 Box 会在垂直方向,一个接一个的放置。
Box 垂直方向的距离由 margin 决定,属于同一个 BFC 的两个相邻 Box 的 margin 会重叠。
每个元素的 margin box 的左边,与包含块 border box 的左边相接触。即使浮动元素也是
BFC 的区域不会与 float box 重叠
BFC 就是页面上的一个隔离的独立容器,容器内的子元素不会影响到外面的元素。反之也如此。
计算 BFC 的高度的时候,浮动元素也参与计算
哪些元素产生 BFC:
根元素
float 属性不是 none
position:absolute | fixed
display : inline-block | table-cell | table-caption | flex | inline-flex
overflow 不是 visible
效果
2. Box 垂直方向的距离由 margin 决定,属于同一个 BFC 的两个相邻 Box 的 margin 会重叠。
html
<div class="row row1" style="display: block;height: 20px;width: 100%;background-color: blue;margin: 20px 0;"></div>
<div class="row row2">
<div style="display: block;height: 20px;width: 100%;background-color: red; margin: 20px 0;"></div>
<div style="display: block;height: 20px;width: 100%;background-color: green;margin: 20px 0;"></div>
</div>
效果如下:
可见 row2 与 row1 之间没有形成 BFC,那么其就属于同一个 BFC 的,那么 margin 就会形成穿透和重叠的情况。
html
<div class="row row1" style="display: block;height: 20px;width: 100%;background-color: blue;margin: 20px 0;"></div>
<div class="row row2" style="overflow:auto;margin-top:50px;">
<div class="row2-1" style="display: block;height: 20px;width: 100%;background-color: red; margin: 20px 0;"></div>
<div class="row2-2" style="display: block;height: 20px;width: 100%;background-color: green;margin: 20px 0;"></div>
</div>
效果如下:
这时候通过第五种方式将 row2 形成一个新的 BFC 盒子,那么这时候 row2-1 就跟 row1 不属于同一个 BFC 了,那么两个元素之间的 margin 就不会重叠;
这时候我们在修改一下代码
html
<div class="row" style="display: block;height: 20px;width: 100%;background-color: blue;margin: 20px 0;"></div>
<div class="row" style="overflow: auto;margin-top: 50px;">
<div style="display: block;height: 20px;width: 100%;background-color: red; margin: 20px 0;"></div>
<div style="display: block;height: 20px;width: 100%;background-color: green;margin: 20px 0;"></div>
</div>
3. 每个元素的左外边缘(margin-left), 与包含块的左边(contain box left)相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。除非这个元素自己形成了一个新的 BFC。
4. BFC 的区域不会与 float box 重叠。
我们首先看一下效果
html
<div class="row" style="display: inline-block;height: 50px;width: 100%;background-color: blue;margin: 20px 0;">
<div class="float-1" style="float: left;width:100px;height: 30px;background-color: red;"></div>
<div class="row1-2" style="color: #fff;font-size:14px;">
asdasdasdabdfsabniasdn sadjfoisaasdasdabdfsabniasdn sadjfoisasdasdabdfsabniasdn sadjfoisasdasdabdfsabniasdn
sadjfoisasdasdabdfsabniasdn sadjfoisasdasdabdfsabniasdn sadjfoisasdasdabdfsabniasdn sadjfoisasdasdabdfsabniasdn
sadjfoisasdasdabdfsabniasdn sadjfoisasdasdabdfsabniasdn sadjfoisasdasdabdfsabniasdn sadjfoisasdasdabdfsabniasdn
sadjfoisasdasdabdfsabniasdn sadjfoisj dfoi jasdoi jfoi j
</div>
</div>
效果如下:
但是如果我们将 row1-2 变成浮动元素那?
html
<div class="row" style="display: inline-block;height: 50px;width: 100%;background-color: blue;margin: 20px 0;">
<div class="float-1" style="float: left;width:100px;height: 30px;background-color: red;"></div>
<div style="color: #fff;font-size:14px;overflow: auto;background-color: green;">
asdasdasdabdfsabniasdn sadjfoisaasdasdabdfsabniasdn sadjfoisasdasdabdfsabniasdn sadjfoisasdasdabdfsabniasdn
sadjfoisasdasdabdfsabniasdn sadjfoisasdasdabdfsabniasdn sadjfoisasdasdabdfsabniasdn sadjfoisasdasdabdfsabniasdn
sadjfoisasdasdabdfsabniasdn sadjfoisasdasdabdfsabniasdn sadjfoisasdasdabdfsabniasdn sadjfoisasdasdabdfsabniasdn
sadjfoisasdasdabdfsabniasdn sadjfoisj dfoi jasdoi jfoi j
</div>
</div>
效果如下:
这就是 BFC 的第 4 条规则(BFC 的区域不会与 float box 重叠),所以 float-1 元素就不是浮动在元素 row1-2 上,而是并排排列
5. BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
在我们讲解第一个 margin 重叠的时候,我们在 row2-1 与 row1 之间发生了 margin 的重叠,然后我们通过将 row2 变成 BFC 的方式 使得 row2-1 的 margin-top 与 row1 的 margin-bottom 之间不形成 margin 的重叠。 这也是 BFC 的布局规则 5:BFC 就是页面上的一个隔离独立的容器
6. 计算 BFC 的高度时,浮动元素也参与计算
这个就涉及到浮动元素高度坍塌的问题。如下面
html
<!-- 我们不把row设置成BFC元素 -->
<div class="row" style="width: 100%;height:10px;background-color: blue;margin: 20px 0;">
<div class="float-1" style="float: left;width:100px;height: 30px;background-color: red;"></div>
</div>
效果如下:
但是我们如果将 row 形成 BFC,那么根据布局规则 6,计算 BFC 内部的高度是,浮动元素也参与计算,那么这时候 row 的高度就不应该是 10px 而是 30px;
html
<div class="row" style="display: inline-block;width: 100%;background-color: blue;margin: 20px 0;">
<div class="float-1" style="float: left;width:100px;height: 30px;background-color: red;"></div>
</div>
效果如下:
作用
1. 自适应两栏布局
html
<div class="row" style="background-color: blue;">
<div class="left" style="float: left;width: 100px;height: 100px;background-color: red;"></div>
<div class="center" style="background-color: green;">
asdasdsadfasdfsadfsaaaaaaaaaaa dasdsadfasdfsad 23 4213 4213 5213 45adfasdfsad 23 4213 4213 5213 45adfasdfsad 23 4213
4213 5213 45adfasdfsad 23 4213 4213 5213 45adfasdfsad 23 4213 4213 5213 45
</div>
</div>
我们可以看到右边的元素被左边的元素遮挡起来,当然这时候我们可以设置 padding-left:100px去去除浮动元素遮挡的影响,但是这时候我们会发现几个问题:1. 浮动元素的宽度需要固定,不然padding-left不知道多大的值。 2. 浮动元素的背景色需要与右边元素背景色相同,不然会出现如图的左下方存在一段右边的背景色。这时候就可以通过将右边元素设置成BFC盒子。
html
<div class="row" style="background-color: blue;">
<div class="left" style="float: left;width: 100px;height: 100px;background-color: red;"></div>
<div class="center" style="background-color: green;overflow: auto;">
asdasdsadfasdfsadfsaaaaaaaaaaa dasdsadfasdfsad 23 4213 4213 5213 45adfasdfsad 23 4213 4213 5213 45adfasdfsad 23 4213
4213 5213 45adfasdfsad 23 4213 4213 5213 45adfasdfsad 23 4213 4213 5213 45
</div>
</div>
这是根据BFC布局规则的第4、5条,BFC区域是独立的不会与页面其他元素相互影响,且不会与float元素重叠,从而形成两栏自适应布局
2. 清除内部浮动
这个是很常见的一个问题,我们元素因为子元素是浮动元素,而导致高度坍塌的问题。如上面布局规则6所讲
这时候将元素设置成BFC元素即(overflow: auto;)使其形成BFC,根据BFC规则第六条,计算高度时就会计算float的元素的高度,达到清除浮动影响的效果。