深入理解css BFC 模型
如果要深入理解css布局的各种原理,要在重构页面做得心应手的话,那么你就必须先理解这玩意 “BFC” , BlockFormatting Context(块级格式化上下文);
这里,官方的定义写得有点难以理解,我就大概的讲一下,我个人的理解;
首先它是什么?
看了很多文章后,包括官方的解释,我个人将他理解如下:
它是css2提出来的,它是一个具有规定的渲染、定位等规则的块级元素(或者说成一个环境);大家都知道,盒子box,一个布局中,可以同时存在很多盒子boxes,而盒子只是容器而已,这也就是其不同之处,可以说成是其升级版,具有了一些规则和渲染方式之后就可以变成一个BFC,当然也只有块级元素能参与转化成BFC;
BFC内部的布局规则
1、内部的Box会在垂直方向,一个接一个地放置。
2、同一个BFC内,垂直方向盒子的上下margin会出现重叠
3、每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
4、子BFC的区域不会与float box重叠。
5、BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
6、计算BFC的高度时,浮动元素也参与计算(故也可以达到所谓的清除浮动的效果,只要将包裹层转变给BFC)
行,那么如何将一个块级元素转化成BFC?
官方给出了以下几种方式:
1、具有除了float:none的其它浮动属性值;
2、定位为absolute或者fixed;
3、display为inline-block, table-cell, table-caption, flex, inline-flex
4、overflow不为visible(除非该值已经传播到视口,如html body 会将overflow的值传播到视口,故此情况下,设置该属性不能建立bfc)
拥有以上随便一种属性就满足条件了;
来吧,重点来了!BFC的作用
Example-1 可以运用它来实现自适应两栏布局
<style> *{ margin: 0; } .div1 { width: 100px; height: 150px; float: left; background: yellow; } .div2 { height: 200px; background: green; } </style>
<body> <div class="div1"></div> <div class="div2">演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字</div> </body>
效果如下
到这里,验证了bfc布局规则的第三条:每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
接下来,我们要将div2转变成bfc,从而实现其自适应,而其原理就是:子BFC的区域不会与float box重叠,也即是div2为bfc后,其区域不会和左浮动的div1重叠;我们只需要给div2添加一个属性overflow:hidden,从而将其转化为bfc;
转变后效果如下:
即2个div不重叠了,并且,div2是自适应的
Example-2 边距坍塌margin collapse的解释
相信这个经典的小问题,大家都会遇到过,由于种种原因,可能你会觉得很烦,或者根本不理它了。事实上,这个问题是很好解释和解决的,只要你重视它;
上代码:
<style> *{ margin: 0; } .div1 { background: yellow; margin-bottom: 100px; } .div2 { background: green; margin-top: 100px; } </style> <body> <div class="div1">演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演</div> <div class="div2">演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演示文字演</div> </body>
效果如下
明明div1设置了下边距,div2设置了上边距,但是结果却只显示了1个边距,即重叠了;这里也验证了bfc的布局规则之同一个BFC内,垂直方向盒子的上下margin会出现重叠
那么这个现象,我的建议是其实跟本就没有必要去同时设置上下边距,布局时,对垂直方向上的div,设置统一向下的边距就好了,没必要同时上下设置;
当然,解决方法是有的,就是给div2 套一个包裹的div3,并且将其div3转化为bfc,具体如下:
效果:
为什么会这样呢?这里就是bfc的内部布局原理:BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。通俗的说,就是div3是一个bfc,而bfc不管具有一个特性,就是内部不管怎么样怎么设置都行,外部是不受任何影响的,因此,即使家里的div2多丑多乱,爸爸div3都会将他包容保密,不会将他告诉任何外面的人,这也就导致了div2的上边距存在于div3内,从而效果展示出来的是200px;
Example-3 清除内部浮动
<style> *{ margin: 0; box-sizing: border-box; } ul{ width: 100%; border: 5px solid red; background: green; } li{ float: left; margin-right: 10%; height: 100px; width: 20%; background: yellow; } </style> <body> <ul> <li>1</li> <li>2</li> <li>3</li> </ul> </body>
效果:
这个情况就不多废话了,浮动导致的外层div高度为0;
这个时候,我们除了用伪元素清除浮动,如下
.clearfix{
*zoom: 1;
}
.clearfix:after{
content: "";
display :table;
clear: both;
}
我们还能用bfc来清除浮动,解决这个问题:
将ul转化为一个bfc,如在ul加一个属性overflow: hidden;这个时候,就可以达到以下效果了
效果:
原理是 计算BFC的高度时,浮动元素也参与计算,即计算ul这个bfc高度时,里面的浮动li高度也会加入计算
为了彻底理解这个东西,我花了一天的时间,通过查阅资料,整理思路,动手实验,整理后写下来了这一篇文章,希望大家好好理解,这个东西,平时看不到,也不会去注意,但是如果你花点时间,好好的理解下,肯定是对你有所帮助的。