BFC(Block Formatting Context): 块级格式化上下文
首先,我们要看清标题,这是块级!
不是行级。也不是浮动、position、等非常规流。
什么是bfc?
这里先埋下一个伏笔。
下面说的
常规流,也有人称为文档流;
块盒,也有人称为块级元素。
首先我们要理解一点就是,每个div盒子(常规流块盒)都有一套属于自己的渲染规则,就像每个手机都有自己的权限等规则,一些系统级别的应用不能让你随便就能删除。
那么,常规流块盒的规则是什么?
1、常规流块盒在水平的方向上,必须撑满块盒。
2、常规流块盒在包含块垂直方向上,要依次排列。
3、常规流块盒如果 margin 无缝相连接,则 margin 合并。
4、常规流块盒的自动高度和摆放位置,会直接无视浮动元素。
正是因为这些规则,导致出现了一些问题。
1、高度坍塌
什么是高度坍塌?
当父级元素没有设置高度时候(即高度为:auto),这时候,在常规流(文档流)中,高度随着子元素内容自然撑开。
但是,在浮动流中,子元素脱离了常规流,导致父级无法撑开。形成高度坍塌!
也就是上面的第4条规则导致。
形成高度坍塌的根源:
常规流盒子的自动高度,在计算样式时候,不会考虑浮动盒子
![](https://img.haomeiwen.com/i22818803/5cd2e22f00958651.png)
<div class="wrap">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
.wrap {
padding:30px, border:solid skyblue 2px;
}
.box {
width:100px; height:100px;
background-color: pink;
margin:10px; float:left;
}
解决办法1:清除浮动元素产生的浮动流(清浮)
使用 clear
默认值:none
left:清除左浮动,该元素必须出现在前面所有 左浮动 盒子的下方。
right:清除左浮动,该元素必须出现在前面所有 右浮动 盒子的下方。
both:清除左浮动,该元素必须出现在前面所有浮动盒子的下方。
<div class="wrap">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="clearfix"></div> 专门用来清除浮动
</div>
.clearfix {
clear:both;
height:50px; /* 当然要把height去掉,这里只是为测试让你看得到 */
}
他的意思是:抬头一看,天上飘着兄弟们,你们在我前面的,下来吧
![](https://img.haomeiwen.com/i22818803/52f8790edb98e4e9.png)
当然,为了清除个浮动,没必要专门写个标签,所以可以用伪元素代替
<div class="wrap clearfix">
<div class="box"></div>
<div class="box"></div>
</div>
.clearfix::after {
content:"";
display:block; //这里默认是行盒
clear:both;
}
以后开发,凡是出现了浮动元素,一定要加上这个clearfix清除浮动,解决高度坍塌,否则容易出现样式混乱。
解决方法2:修改常规流块盒的渲染规则,也就是触发bfc。
那到底什么是bfc?其实,它是一套独立的区域渲染规则。
- 它规定在该区域中 常规流块盒的布局;
- 在不同的bfc区域中,他们进行渲染时互不干扰;
- 创建bfc的元素,隔绝了它内部和外部的联系,内部的渲染不会影响到外部;
相当于,有了它,就不用受到常规流块盒的一些约束。有点像手机的越狱操作。
创建bfc的元素,上面的常规流规则3、4,直接作废。
也就是:常规流块盒自动高度的时候,要算上正在浮动的子元素;
触发的方法有:
在父级上设置这些属性之一:
-
display:inline-block;
-
overflow:hidden;
-
float: left;
-
position: absolute; //还有fixed 只要脱离常规流就行
虽然这些都可以解决高度坍塌,但是会有副作用,
这3个副作用最小的是 overflow:hidden(但还是会有),
可以根据具体的场景分别使用不同触发方式。
margin塌陷?
这种情况是因为在常规流中边距合并的原因。
![](https://img.haomeiwen.com/i22818803/4434263dfc35002d.png)
.wrap {
width: 300px;
height: 300px;
background-color: skyblue;
}
.content {
width: 100px;
height: 100px;
background-color: pink;
margin-top: 100px;
}
<div class="wrap">
<div class="content"></div>
</div>
解决方法1:
只要不要把俩个盒子的边距粘在一起就行。。
比如给外面的盒子加个边框
![](https://img.haomeiwen.com/i22818803/cdfafcfa3b3ad7a5.png)
解决方法2:当然了也可以考虑改成padding。
解决方法3:修改常规流块盒的渲染规则,也就是触发bfc。
.wrap {
overflow: hidden;
}
还有一种情况:
上下两个块盒之间的 margin 合并了。。
其实,html 根标签就是一整块的bfc,这两个块盒都在同一个bfc中,也会导致粘在一起的两个 margin 合并了。
![](https://img.haomeiwen.com/i22818803/a196303738320304.png)
.content {
width:100px;
height:100px;
background-color:skyblue;
margin:10;
}
<div class="content"></div>
<div class="content"></div>
我明明两个div都各设置了10px,理论应该是叠加成20px的,可是只有10px。。
解决这种方法还是可以使用bfc。
.wrapper {
overfloat:hidden;
}
.content {
width:100px;
height:100px;
background-color:skyblue;
margin:10;
}
<div class="wrapper">
<div class="content"></div>
</div>
<div class="wrapper">
<div class="content"></div>
</div>
这样它们就在各自的bfc中了,就能解决了这个问题了。
但是,它的代价也是非常惨痛的!因为他改了<html>结构。所以,
单单针对这个问题。在一般实际的开发中,是允许上下 margin 合并这个bug存在的,大不了多给 div 加点 margin 就能绕这个bug了。
如果有不对的地方,欢迎指出来。
网友评论