初步了解定义
请先耐心阅读BFC的定义和构成前提,然后再看它的作用。
BFC全名:Block Formatting Context,中文解释:块级格式化上下文,MDN文档是https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Block_formatting_context。
一个BFC区域包含创建该上下文元素的所有后代元素(后代元素有自己BFC的除外)。
一个页面如果所有元素没有下文说的那些样式,那么它们就在同一个BFC内,也就是说,它们都在同一个大作用域内,这个BFC是由根元素(<html>)创建的。这也是浏览器渲染的一个基本原则。
什么元素能构成独立BFC?
满足下面随意1个条件,即可构成BFC:
- 根元素(<html>)
- 设置了float为left或right的元素
- 设置了position为absoulte或fixed的元素
- 设置了display为flow-root或inline-block或table家族或flex家族或grid家族的元素
- 设置了overflow为hidden或auto或scroll的元素
我们分析一下:
给元素设置float会带来明显布局变化,设置position会脱离正常布局流,设置display会改变自身或子元素的表现,所以结论是:
-
考虑IE的前提下,设置overflow最安全,比如
overflow: hidden
,具体设置哪个值需要因需要而定。 -
不考虑IE的前提下,设置
display:flow-root
最安全。只不过IE全系列不支持。display:flow-root
是啥?它是为了解决margin、float副作用而专门规定的新属性,表现跟block一样,只是添加了BFC。具体不多说,自己查阅吧。
重点到了,BFC有啥用?
1. 解决margin折叠带来的垂直塌陷
margin垂直塌陷你应该听说见过,两个上下排列的div都设置了margin: 100px
,你以为它们上下间距200px?并不是,它们间距是100px。这就是margin垂直塌陷。
margin垂直塌陷是创世者故意设定的,它不是没有好处的,它的好处就是,如果一列N个div都无脑设置margin: 100px
,它们在父容器里是均匀分布的,就好像flex的justify-content: space-around;
一样,非常美观。
但有时候我们确实不需要这种设定,这时候就可以用BFC,让2个div强行互不影响。
我们扫视构成BFC的前提,就会发现,
2. 解决margin-top折叠带来的包含塌陷
与上文类似,一串父子孙重孙……div,他们的margin也是取最大的那个生效,如果后代某元素的margin-top比祖先的大,那么会把祖先元素撑下来,即便是祖先元素最大,后代元素margin-top等于是不生效。这种设定当然也是创世者故意的,但是很难找到用武之地,怎么避免呢?
办法有很多,比如给父元素设置border或padding,但是,破坏布局的事咱不干,最好的办法是父子元素都设置独立BFC。
3. 解决子元素float导致父元素高度塌陷
我们在玩float的时候经常会看到父元素高度塌陷,这时候一般人的做法是使用清除浮动,即给父元素设一个::after元素,给这个元素设置clear: both
。其实这是最推荐的办法,如果非要炫技,可以给父元素设overflow来形成BFC,也可以用inline-block布局代替float布局,也可以用flex布局来代替float布局。
4. 利用BFC形成弹性左右布局
实现左右布局,左固定宽度、右弹性宽度,办法有很多,比如:
-
左元素float,右元素设margin-left,值是左元素的宽度,然后右元素宽度设100%。
-
flex布局
现在,我们利用BFC,可以优雅的实现又一种左右布局,做法是:左元素设float和宽度,右元素标准流,道理上说,右元素充满父元素,左元素压在右元素的上面。这时候,如果右元素设上overflow,则右元素不再充满父元素,而是被左元素挤到右边了,而且,左元素宽度变化时,右元素也会随之变。从头到尾没有margin-left什么事。
为什么会这样?因为左右元素都是BFC,互相不影响。
几个问题
1. BFC跟脱离正常布局流有什么关系?
正常布局流就是民间说的文档流,MDN:https://developer.mozilla.org/zh-CN/docs/Learn/CSS/CSS_layout/Normal_Flow
脱离正常布局流的方法可以看https://www.zhihu.com/question/24529373,简单说是float:left/right,position: absolute/fixed这几种方法。
所以说,脱离正常布局流一定形成BFC,而BFC不一定脱离正常布局流。
2. BFC出现的概率
正常布局流下BFC出现的概率低,大多数情况下不存在BFC,只有在display非主流的时候(block和inline为主流),和在overflow有值的时候,出现BFC。
在脱离正常布局流下,一定出现BFC。
3. BFC到底是好事还是坏事?
按说,程序员嘴里不应该对技术说出这么感性的评价,但是的确有很多人希望通过“好”和“坏”来深入理解BFC,那么我们就来看一下:
-
margin折叠往往是出乎开发者意料的,“坏”的意义大于“好”的意义,而BFC能解决这个“坏”属性,因此BFC在这里是“正面形象”。
-
float塌陷也是往往出乎开发者意料,“坏”的意义大于“好”的意义,这里注意,塌陷的原因并不是子元素形成BFC的缘故,而是子元素脱离正常布局流,所以BFC不背这个锅。这时候,给父元素设置
overflow
等于将子元素从脱离正常布局流状态强行拉回来,可以看出,BFC威力大于脱离文档流的威力,因此BFC在这也是“正面形象”。
结论
-
正常布局流最重要,不要轻言脱离。当然该脱离还是要脱离。
-
BFC不代表一定脱离,尽量用overflow和flow-root这种不脱离的属性和值。
-
BFC正面形象居多,该用则用,能解决很多问题,主要是margin和float的意外问题。
-
display: flow-root是创建BFC的最优雅方式,其次是overflow。
网友评论