前置知识
在介绍BFC之前,先了解一下文档流相关的内容。
我们常说的文档流包括定位流、浮动流、普通流三种。
绝对定位
如果元素的属性position为absolute或fixed,那这个元素就是一个绝对定位的元素,它会脱离普通流,它的位置由绝对定位的坐标和层级决定,对于position:absolute的元素来说,它将相对于离自己最近的上级元素且设有relative、fixed、absolute的元素进行定位,如果没有则相对于body元素进行定位。
对于设置fixed的元素来说,相对于浏览器的窗口进行定位,但是如果该元素的祖先有设置transfrom非none时,会相对于该祖先元素进行定位。
浮动
在浮动布局中,元素按照普通流的位置出现,然后根据浮动的方向尽可能的偏移,这里有个坑🕳:请看代码
<body>
<span style="padding:0 10px;background-color: yellowgreen;">span1(没有设置浮动)</span>
<span style="float:left;padding:0 10px;height: 40px;background-color: yellow;">span2(设置左浮动)</span>
</body>
这是运行的效果,会发现第二个设置浮动的span元素跑到了第一个span前面,原因是这样的:float这一属性,float:left会使元素变成一个inline-block元素(使得第一个span元素可以设置宽高)。实际上他是和上一行内元素span显示在同一行。
一个浮动的盒子会向右或向左移动直至触碰到包含块的边界或另一个浮动盒子的边界。
span既不是其包含块也不是另一个浮动的盒子,故div会移动至包含块的边界,所以div会显示在span之前。
普通流
普通流其实就是BFC的FC(Formatting Context)格式化上下文,它是页面中的一块渲染区域,有一套渲染规则,决定了其子元素如何布局以及和其他元素之间的关系和作用。
在普通流中,元素按照在文档中的先后位置从上至下布局,即行内元素水平排列,块级元素独占一行。
BFC相关内容
关于BFC的定义:
块级格式化上下文(BFC)是WEB页面的可视CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。
具有BFC特性的元素可以看作是隔离了的独立容器(想象成一个独立的箱子),容器内的元素不会在布局上影响到外面的元素(你里箱子里面的物品如何怎么摆放都不会影响到外面),并且BFC具有普通容器所没有的一些特性,且同一个元素不可能同时存在于两个BFC中。
BFC的触发方式
满足下方任何一个条件即可触发BFC特性
- 根元素本身就是个BFC
- 浮动元素 float为left或right
- overflow不为visible,即为auto、scroll、hidden
- 绝对定位:position:absolute、fixed
- display的值为inline-block flex grid inline-flex inline-grid block等
BFC的特性
- BFC是页面上的一个独立容器,容器里面的子元素不会影响外面的元素。
- 同一个BFC里面的两个相邻的块级元素可能会发生外边距折叠,创建新的BFC可以解决此种情况。
- 浮动盒的区域不会和BFC重叠
- 计算BFC的高度时,浮动元素也会参与计算
应用
1、自适应两列布局
<div>
<div class="left">left</div>
<div class="right">right</div>
</div>
<style>
.left{
float: left;
width: 100px;
height: 200px;
margin-right: 10px;
background-color: blueviolet;
}
.right{
overflow: hidden;
height: 200px;
background-color: pink;
}
</style>
看一下运行的效果:
这利用了BFC 的「包含浮动元素的影响」(浮动盒的区域不会和BFC重叠)这个特性,右侧的元素开启BFC,不给定宽度,左侧的元素定宽或者不定宽都可以,
- 将左列设为左浮动,使得其他块级元素可以和它占据同一行
- 右侧为块级元素,利用其自身的流特性占满整行
- 右列设置overflow:hidden,触发BFC特性,使其自身与左侧浮动盒隔离开,不占满整行
2、解决margin重叠问题
<div>
<div class="div1">div1</div>
<div class="div2">div2</div>
</div>
我给div1设置下边距10px,div2设置上边距是20px,按代码里面两个div盒子应该上下相距30px才对,但是发生了重叠,会取两个margin’中最大的一个值,并不会相加,至于解决方法,如果用BFC解决的话,可以将两个盒子分别放到不同的BFC中,下面是改进的代码:
其中wrap设置overflow:hidden开启BFC
<div>
<div class="wrap">
<div class="div1">div1</div>
</div>
<div class="wrap">
<div class="div2">div2</div>
</div>
</div>
这利用到了上面BFC特性的第二条----同一个BFC里面的两个相邻的块级元素可能会发生外边距折叠,那就再开启一个BFC就好了。
3、父子元素的外边距重叠的问题
这种情况存在于父元素与其第一个或最后一个子元素之间。
看下代码:
.parent{
width: 200px;
height: 200px;
/* 有没有都一个样 */
margin-top: 10px;
background-color: pink;
}
.son{
width: 100px;
height: 100px;
margin-top: 100px;
background-color: red;
}
解决办法很多,比如给parent触发BFC;给父元素添加border或者将父元素的margin替换成padding
4、还有就是可以清楚浮动,当父元素的子元素设置浮动之后,并且父元素此时还没有设定高度,那此时父元素的高度就只有边框,padding或者margin的高度了,解决办法就是给父元素启用BFC,使得其具有BFC的特性,这利用了BFC特性的第四条-----内部的浮动元素也参与计算。