一、理解BFC
1、Box:css布局的基本单位
box是css布局的对象和基本单位几个,直观点说,就是一个页面由很多到 box组成,元素的类型和display属性,决定了box类型,不同类型的box会参与不同的formatting context(决定如何渲染文档的容器),因此box内的元素会以不同的方式渲染。
几个常见的盒子:
block-level box:display属性为block,list-item,table的元素,会生成block-level box,并且参与BFC;
inline-level box:display属性为inline,inline-block,inline-table的元素,会生成inline-level box .并且参与 inline formatting context;
2、Formatting context
Formatting context是指页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及与其他元素的关系和相互作用,最常见的Formatting contexty有 Block fomatting context (简称 BFC )和 Inline formatting context (简称 IFC )。
3、**BFC **:块级格式化上下文
BFC 是指一个独立的块级渲染区域,只有Block-level Box参与,该区域拥有一套渲染规则来约束块级盒子的布局,且与区域外部无关。
BFC就是一种布局方式,可以理解为一个作用范围,即在一个BFC里的布局与其之外的布局不相关或者说不相互影响。
举一个形象的例子:
可以把一个页面想象成大的集装箱,这个集装箱里装的货物就是html元素。在现实生活中为了避免不同人的货物相互混淆,都是把货物打好包装再装入集装箱,这样的话无论你包装里面的货物怎么摆放,都不会影响到其他人的货物。那么这个包装就可以被想象成 Block Formatting Context。
4.为什么要用BFC?
使用一定的CSS声明可以生成BFC,浏览器对生成的BFC有一系列的渲染规则,利用这些渲染规则我们可以达到一定的布局效果,为了达到特定的布局效果我们让元素生成BFC。
二、哪些元素会生成BFC?
当一个HTML元素满足下面条件的任何一点,都可以产生 Block Formatting Context
根元素
float的值不为none;
overflow的值不为visible(可以为hidden,scroll,auto);
display的值为inline-block,table-cell,table-caption,flex,inline-flex中的任何一个;
position的值为absolute,fixed(不为static,relative中的任何一个);
display:table也认为可以生成BFC,其实这里的主要原因在于table会默认生成一个匿名的table-cell,正是这个匿名的table-cell生成了BFC。
常用的用来触发BFC的CSS样式:
overflow: scroll,overflow: hidden,display: flex,float: left,display: table
其中可能产生的一些问题
display:table—— 可能会产生一些问题
overflow:scroll—— 可能会显示不必要的滚动条
overflow:hidden—— 将会剪切掉溢出的元素
float:left—— 将会把元素置于容器的左边,其他元素环绕着它
三、BFC的布局规则
1、内部的Box会在垂直方向上一个接一个的放置;
2、垂直方向上的距离有margin决定。(完整的说法是:属于同一个BFC的两个相邻的Box的margin会发生重叠,与方向无关)
3、每个盒子的左外边框紧挨着包含块的左边框(从右到左的格式,则为紧挨右边框),即使浮动元素也是如此。(这说明BFC中的子元素不会超出它的包含块)
4、BFC的区域不会与float的元素区域重叠
5、计算BFC的高度时,浮动子元素也参与计算;
6、BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然;
四、BFC的作用及原理
(1)自适应两栏布局
效果如下
根据BFC布局规则 第3条:* 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反),即使存在浮动也是如此。
根据BFC布局规则第四条:* BFC的区域不会与floatbox重叠。
改变方法:我们可以通过触发right 生成BFC, 来实现自适应两栏布局,当触发right 生成BFC后,这个新的BFC不会与浮动的 aside 重叠,right会根据包含块的宽度,和 left 的宽度,自动变窄。(一个盒子的边框会由于浮动而收缩,盒子本身将会变得更窄)
.right { overflow: hidden;}//或者利用上述其他方式为它生成 BFC
(2)清除n内部浮动
根据BFC布局规则第五条:* 计算BFC的高度时,浮动元素也参与计算
**改变方法:**为达到清除内部浮动,我们可以触发 section 生成BFC,那么 section 在计算高度时,section 内部的浮动元素 child 也会参与计算。
section{overflow:hidden}
(3)防止垂直 margin 重叠
根据BFC布局规则第二条:Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
现象:两个p之间的距离为100px,发送了margin重叠。
修改:
我们可以在p外面包裹一层容器,并触发该容器生成一个BFC。那么两个P便不属于同一个BFC,就不会发生margin重叠了
其实以上的几个例子都体现了BFC布局规则第六条:BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
解释:
因为BFC内部的元素和外部的元素绝对不会互相影响;
因此,** 当BFC外部存在浮动时,它不应该影响BFC内部Box的布局,BFC会通过变窄,而不与浮动有重叠;
同样的,
当BFC内部有浮动时**,为了不影响外部元素的布局,BFC计算高度时会包括浮动的高度;避免margin重叠也是这样的一个道理
五、详细分析 margin 折叠
1、产生的原因
这些margin都处于普通流中,并在同一个BFC中
这些margin没有被非空内容、padding、border或clear分隔开
这些margin在垂直方向上是毗邻的
2、包含的情况:
一个box的margin-top与第一个子box的margin-top
一个box的margin-bottom与最后一个子box的margin-bottom,但须在该box的height:auto的情况下
一个box的margin-bottom与紧接着的下一个box的margin-top
一个box的margin-top与其自身的margin-bottom,但须满足没创建BFC
注:另一篇CSS盒子对这些情况有图解
3、折叠边距的计算
当两个margin都是正值的时候,取两者的最大值;
当 margin 都是负值的时候,取的是其中绝对值较大的,然后,从 0 位置,负向位移;
当有正有负的时候,先取出负 margin 中绝对值中最大的,然后,和正 margin 值中最大的 margin 相加。
NOTE:所有毗邻的margin要一起参与运算,不能分步进行。
4、举个例子:
1)用 浮动布局 显示成两行两列 ——(为了解决浮动布局里的一个问题:元素浮动不换行怎么办?)
我们可以看到四个盒子最终都处在一列里面,为了达到我们的目的,可以**在其中一个外层盒子建立一个BFC**
2、实现多栏布局的一种方式
根据BFC布局规则第四条:* BFC的区域不会与floatbox重叠。(与浮动元素相邻的已生成BFC的元素不能与浮动元素互相覆盖)