水平有限,如果存在问题欢迎大家访问我的博客批评指正.
首先,'FC’肯定不是开封菜,而是Formatting context
的简称.而在理解BFC等等概念之前,先让我们了解一下’FC’与’Box’是什么?
-Formatting context
是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。最常见的 Formatting context 有 Block fomatting context (简称BFC)和 Inline formatting context (简称IFC)以及Flex formatting contexts(简称FFC),最后还有一个GridLayout Formatting Contexts(GFC)。
Box
是 CSS 布局的对象和基本单位, 直观点来说,就是一个页面是由很多个 Box 组成的。元素的类型和 display 属性,决定了这个 Box 的类型。 不同类型的 Box, 会参与不同的 Formatting Context(一个决定如何渲染文档的容器),因此Box内的元素会以不同的方式渲染。让我们看看有哪些盒子:
在我们一些使用场景触发BFC是为了清除浮动(我此次是因为清除浮动才引起的整体学习),所以我还得先讲讲清除浮动.
清除浮动主要是为了解决,父元素因为子级元素浮动引起的内部高度为0的问题
1.如下,我给父div设置一个边框,内部放两个div一个left 一个right,不设置浮动,则他们会默认撑开父盒子
left
right
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VlLxL0CR-1589337556619)(/api/file/getImage?fileId=5eb564d86d54b1000b000046)]
2.当我给内部两个div加上float属性的时候
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EM9yrzgA-1589337556621)(/api/file/getImage?fileId=5eb564c36d54b1000b000045)]
两个div左右浮动了,而父div因为没高度,只剩下黑色边框了.红色的footer元素也到最上边去了.
那么:
当父元素没有高度的时候,如果子元素不浮动,就回按照子元素高度默认撑开.但是当子元素浮动的时候,父元素就不会自动撑开了.(ps:那么一个浮动,一个不浮动呢?)
父组件没了高度这就是高度坍塌
,要解决这个问题,我们首先就会想到clear
属性,利用clear:both
来解决坍塌问题.
clear 属性定义了元素的哪边上不允许出现浮动元素
但是具体清除浮动的方式,我们也有好多种思路:
1. 标签法(不推荐)
left
right
我是一个标签
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CzkU49dJ-1589337556623)(/api/file/getImage?fileId=5eb5684e6d54b1000b000047)]
当我们的clear元素内容为空时,就可以借助它不允许两边有浮动元素,那么只能放左右div下边的限制来解决高度坍塌的问题.
所以不推荐
2.父级添加overflow属性(不推荐)
通过触发BFC方式,实现清除浮动.
.fahter{
width: 60vw;
border: 5px solid #000;
overflow: hidden;
}
这种方式明眼一看很简单,但是会在有些操作时如果不自动换行会直接隐藏掉,最简单的例子比如文字.
未设置overflow
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2xWyfzAS-1589337556626)(/api/file/getImage?fileId=5eb56b3c6d54b1000b000048)]
设置overflow
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GglwMr2b-1589337556628)(/api/file/getImage?fileId=5eb56b516d54b1000b000049)]
所以也不推荐
3.使用after伪元素(推荐)
.father:after{
content: "";
display: block;
clear:both;
}
.father{
...
zoom: 1
}
优点:符合闭合浮动思想,结构语义化正确
缺点:ie6-7不支持伪元素:after,使用zoom:1触发hasLayout.
4.使用before和after双伪元素(推荐)
.father:after,.father:before{
content: "";
display: table;
}
.father:after{
clear: both;
}
.father{
...
zoom: 1;
}
优点:代码更简洁
缺点:用zoom:1触发hasLayout.
上面清除浮动的方法里面隐约提到触发BFC来达到目的,但是为什么触发BFC就能清除掉浮动呢.
不急,就让我们从Formatting context
来慢慢展开.
BFC全称是 block formatting context
,也就是 块级格式化上下文,是用于布局块级盒的一块 渲染区域。
这一点其实很好理解.一个接着一个往下排列.
我们看个案例。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vj2k2zVU-1589337556630)(/api/file/getImage?fileId=5eaeb60e6d54b1000b00000a)]
按样式代码来看,红块和蓝块之间间距应该是40px。但实际上是20px。这就是BFC渲染规则的第二点(margin重叠)。
因为BFC的触发条件之一就是根元素
,所以body
就是一个BFC容器,红块和蓝块是同在body
下的相邻块级元素,其margin会生重叠,所以红块和蓝块之间间距只有20px。
第三点规则比较难理解我详细解释一下。首先要先理解包含块的含义。
包含块不是一个完整的box,一个完整的box包含margin包含块,border包含块,padding包含块,content包含块。
包含块有可能是box的content包含块,也可能是box的padding包含块。这取决于被包含块所包含的元素的position
属性。
例如,如果某个元素position
属性是absolute
,包含块就是由它的最近的position
的值不是 static
的父级元素的padding包含块组成。
再例如,如果某个元素的position
属性是static
或relative
,包含块就是由它的父级元素的content包含块。
如果某个元素的position
属性是fixed
,包含块就是视口。
那么。BFC中的元素应该与其自身的包含块相接触,而非与BFC相接触,这个包含块有可能是BFC中的一部分,也有可能和bfc无关。
正常元素都是从左往右的格式化,那么对元素的position属性是absolute,right为0,或者元素的float的属性为right,那么就是从右往左的格式化,元素的右边缘和包含块的右边缘接触。
元素H触发生成BFC,其中有两个元素A和元素B,元素A的float的属性为left,那么元素A的左边缘和元素H(也是元素A的包含块)左边缘接触,如果元素B的float的属性也为left,元素B的左边缘不和元素H的左边缘接触,而是和元素A的右边缘接触。这种情况就可以用规则中的“即使包含块中的元素存在浮动也是如此,除非其中元素再生成一个BFC”来解释,元素的float的属性不为none会触发生成BFC,所以这种情况是不矛盾的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AnfFX9x8-1589337556630)(/api/file/getImage?fileId=5eaeb6bb6d54b1000b00000b)]
还是举个例子:
元素A
元素B
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iV0jfLyQ-1589337556631)(/api/file/getImage?fileId=5ebb3d566d54b1000b000027)]
当你元素A添加float属性后,元素A脱离文档流。
元素A
元素B
正常情况下,后面元知素B会与前道面的元素A重叠(因为float导致A元素脱离文档流不再占据原来的位置,后面元素会占据前面的位置,如图)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ESdSCq99-1589337556632)(/api/file/getImage?fileId=5ebb3db56d54b1000b000028)]
这个时候给元素B加上overflow:hidden触发BFC;
元素A
于是元素B 产生了BFC效果导致元素B收缩,不在占据元素A位置,如图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ImIVy1Ht-1589337556635)(/api/file/getImage?fileId=5ebb3e2f6d54b1000b000029)]
两栏自适应问题的解决方案,有没有!
这个规则,可以用来解决内部元素浮动,导致父级元素的高度坍塌问题。其实很好理解,内部元素与外部元素互不影响.
也很好理解,高度坍塌问题都解决了,浮动元素的高度肯定要参与BFC的高度计算.
在文章最初,提到用clear:both来清除浮动,我们也可以根据BFC的渲染规则第6点(计算BFC容器的高度时,浮动元素也参与计算)来清除浮动,解决高度坍塌的问题。
我们利用BFC渲染规则第2点(属于同一个BFC的两个相邻块级元素的margin会发生重叠),那么不属于同一个BFC的两个相邻块级元素的margin就不会发生重叠。
那么我们在第二个div元素用一个div元素包裹起来,并用overflow:auto触发其BFC。再看一下效果是不是不重叠了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-loHaxuuA-1589337556636)(/api/file/getImage?fileId=5eaebb986d54b1000b00000c)]
自适应两栏布局,是一个主内容区域和一个侧边栏区域组成,两个区域的宽度都可以随窗口大小自适应。我们就可以利用BFC的规则四来实现这个需求.
详见规则四案例.
有时候我们在body上设置"display:hidden"不能触发BFC.为什么呢?
w3c规定如果overflow不是visible的块级元素将创建BFC。
但是又有一句提醒除非该值已经扩散到了视口
。
而w3c对于overflow也有定义:
分析:
所以
所以只能先将html元素的overflow属性设置为hidden,再把body元素的overflow属性设置为hidden,才能使body触发BFC 。
IFC全称是inline formatting context
,也就是 内联格式化上下文,是用于布局内联元素盒子的一块 渲染区域。
IFC的形成条件非常简单,块级元素中仅包含内联级别元素,需要注意的是当IFC中有块级元素插入时,会产生两个匿名块将父元素分割开来,产生两个IFC。
FFC全称是flex formatting context
, 也就是 灵活格式化上下文,是用于布局弹性容器的一块 渲染区域。
父级元素设置display:flex或者`display:inline-flex
可以看阮一峰的Flex 布局教程:语法篇,讲的非常详细。
要注意一点。生成FFC后,其子元素的float、clear和vertical-align属性将失效。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-daNOWq4D-1589337556637)(/api/file/getImage?fileId=5eaebc236d54b1000b00000f)]
头部
内容
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XDKzkQAx-1589337556638)(/api/file/getImage?fileId=5eaebc356d54b1000b000010)]
头部
内容区
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DSNm3po0-1589337556639)(/api/file/getImage?fileId=5eaebc486d54b1000b000011)]
GFC全称是gridLayout formatting context
,也就是 网格布局格式上下文,是用于布局网格容器的一块 渲染区域。
当为一个元素设置display值为grid的时候,此元素将会获得一个独立的渲染区域,我们可以通过在网格容器(grid container)上定义网格定义行(grid definition rows)和网格定义列(grid definition columns)属性各在网格项目(grid item)上定义网格行(grid row)和网格列(grid columns)为每一个网格项目(grid item)定义位置和空间。
那么GFC有什么用呢,和table又有什么区别呢?首先同样是一个的表格,但GridLayout会有更加丰富的属性来控制行列,控制对齐以及更为精细的渲染语义和控制。
最后:关于zoom知识的扩展
zoom:1是针对ie的属性,可以激活hasLayout属性,关于hasLayout
haslayout 是Windows Internet Explorer渲染引擎的一个内部组成部分。在InternetExplorer中,一个元素要么自己对自身的内容进行计算大小和组织,要么依赖于父元素来计算尺寸和组织内容。为了调节这两个不同的概念,渲染引擎采用了 hasLayout 的属性,属性值可以为true或false。当一个元素的 hasLayout属性值为true时,我们说这个元素有一个布局(layout)
要想更好的理解 css, 尤其是 IE 下对 css 的渲染,haslayout 是一个非常有必要彻底弄清楚的概念。大多IE下的显示错误,就是源于 haslayout。如果它设置成了true,它就不得不去渲染它自己,因此元素不得不扩展去包含它的流出的内容。例如浮动或者很长很长的没有截断的单词,如果haslayout没有被设置成true,那么元素得依靠某个祖先元素来渲染它。这就是很多的ie bugs诞生的地方。
参考文章:
红尘炼心-四年前端在CSS面试上跪了