最近在前端群上面看到有人提出了一个概念:BFC,没听懂是什么意思,于是找了一些资料来看看。
Formatting Context:指页面中的一个渲染区域,并且拥有一套渲染规则,他决定了其子元素如何定位,以及与其他元素的相互关系和作用。
首先来讲解一些常用的概念:
1.普通流
普通流就是元素按照其出现的顺序至上而下进行布局,行内元素水平排列,至到本行已经排满了就再续在下一行进行排列。而块级元素则会自己出现新的一行。也就是说,普通流是按照其出现的顺序而决定它的位置的。
当position为static或relative,并且没有设置float或float为none的时候会触发普通流。
相对于静态定位,position:static,盒的位置是普通流布局里面的位置。
相对于相对定位,position:relative,盒偏移位置由top\bottom\left\right来定义,仍然保留原有的位置,其他普通流的元素不能占用这个偏移的位置。
2.float
设置了float的元素,首先按照普通流的位置进行布局,然后根据float的方向进行向左或者向右进行偏移。会导致普通流环绕在它的周边,除非设置clear属性。
ok这里我又疑惑了,到底float脱不脱离文档流,既然脱离,为什么普通流会环绕在它周边?也就是说它为什么还占有普通流的空间?
float是半脱离,在文档流中会占有一定的位置,使用float脱离文档流时,其他盒子会无视这个元素,但其他盒子内的文本仍然会为这个元素让出位置,环绕在周边,
可以见到其他元素在布局的时候,是占有了float的位置的,但是!其他元素内部的元素是会给他让出一个位置的!!除非设置了clear,这样其他元素就会在下一行进行布局。
3.绝对定位设置了绝对定位的元素,它就不在普通流的位置,而是自己在另一层。
它的定位相对于它的包含块。元素定位将相对于最近的一个relative、fixed或absolute的父元素,如果没有则相对于body;
那么什么是BFC,BFC就是block formatting contexts(块级格式化上下文),怎么理解这句话呢?
具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性。
也就是说,只要设定为BFC的元素,那么它无论怎么变化都不会影响普通流上面的元素。
所以怎么样设置就是BFC呢?
具有以下特性的元素就是BFC
-
body的根元素(就是body元素)
-
浮动元素
-
绝对定位元素(position值为absolute或者fixed)
-
行内块(display为inline-block)
-
表格单元格(display:table-cell)或者表格里面的单元格
-
overflow除了visible以外的值。
-
弹性盒(flex ,display:flex)
一个BFC包含创建该上下文元素的所有子元素,但不包括创建了新BFC的子元素的内部元素。
<div id='div_1' class='BFC'>
<div id='div_2'>
<div id='div_3'></div>
<div id='div_4'></div>
</div>
<div id='div_5' class='BFC'>
<div id='div_6'></div>
<div id='div_7'></div>
</div>
</div>
在上面的代码中,div1创建了一个bfc,那么其所有的子元素都是bfc,但是,因为div5又创建了新的bfc,所以div6,div7是属于div5的bfc。
也就是说,div1,2,3,4,5是一个bfc,67是一个bfc
也就是说一个元素不能同时存在于两个bfc中。
BFC的一个最重要的效果是,让处于BFC内部的元素与外部的元素相互隔离,使内外元素的定位不会相互影响。这是利用BFC清除浮动所利用的特性,关于清除浮动将在后面讲述。
BFC元素的一些特点
1.同一个BFC下,外边距会发生重叠
打开浏览器可以看到,上面的div的下边距和下面div的上边距重叠在一起了。
如果不想像上面那样,边距重叠在一起,可以将其放在不同的 BFC 容器中如
2.BFC元素可以包含浮动元素(清除浮动)
因为浮动元素是会脱离普通文档流,所以如果在一个普通流里面包含一个浮动流,那么这个浮动流的高度是不在普通流里面的,例如
<div style="border: 1px solid #000;">
<div style="width: 100px;height: 100px;background: #eee;float: left;"></div>
</div>
可以看到外层div元素它的高度只是border的高度,并不包含float元素所设置的高度。
但是如果将这个外层元素设置为BFC,可以看到,浮动元素就会被包含进去了。
<div style="border: 1px solid #000; overflow: hidden">
<div style="width: 100px;height: 100px;background: #eee;float: left;"></div>
</div>
3.BFC 可以阻止元素被浮动元素覆盖
可以看到此时第一个元素将第二个元素所覆盖流,此时将第二个元素设置为BFC元素就会变成两个独立的块元素。
那么,BFC是如何进行布局的呢?
1. 内部的Box会在垂直方向上一个接一个的放置
2. 垂直方向上的距离由margin决定。(完整的说法是:属于同一个BFC的两个相邻Box的margin会发生重叠,与方向无关。)
3. 每个元素的左外边距与包含块的左边界相接触(从左向右),即使浮动元素也是如此。(这说明BFC中子元素不会超出他的包含块,而position为absolute的元素可以超出他的包含块边界)
4. BFC的区域不会与float的元素区域重叠
5. 计算BFC的高度时,浮动子元素也参与计算
6. BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面元素,反之亦然