在前端学习中,接触到了BFC,IFC,FFC,GFC等这样的概念,在看了无数博客后,发现大家对它们的理解有偏差,于是想着记录一下,以免大家和我 一样走很多弯路~~(如有理解错误的地方,敬请斧正,避免我误人子弟!)
写在前面的一些概念:
1. BFC,IFC,FFC,GFC它们都是为了描述浏览器如何处理或渲染文档树而 定义 的一种context,分别代表其内部的元素的布局某种规则;
2. 文档中元素的布局受限于以下参数。而BFC等处于“定位机制”下的常规流中;
--盒子的尺寸与类型(inline-blobk ,flex ,block 等);
--定位机制(常规流、浮动、绝对定位);
--文档树中元素之间的关系;
--外部信息(例如:viewport的尺寸、图片元素的固有大小,等)
3. 块级元素(block-level elements)是从文档中被渲染出来时候呈块状的元素(display为block , list-item , table的元素);
块级盒子(block-level boxes)是会参与BFC的盒子。每个块级元素都会生成一个块级盒子。
块容器盒子(block container box)要么只容纳块级盒子的盒子,要么会在内部建立一个IFC从而只容纳行级盒子(inline-level boxes);
所有的块级盒子都是块容器盒子,但反之不成立!
4.在CSS2.2中,盒子可能会用以下定位机制来布局:
--常规流(normal flow)。在CSS2.2中包含:block formatting,inline formatting,以及它们两的相对定位;
--浮动(floats)。在浮动模型中,盒子先按常规流布局,然后把它从流中取出。后面的内容会沿着这个浮动盒子的 左/右 边界,进入其原来的位置;
--绝对定位(absolute positioning)。(display为absolute或fixed)在绝对定位中,盒子会从流中完全移出,它们的margin不会重叠;
理解BFC、IFC、GFC 和 FFC
*FC即 * Formatting Contexts,可以直译为"XX格式化上下文",理解为某种形式的渲染环境。
BFC的布局规则
BFC内部的盒子将从其容器的顶部开始,一个接一个地垂直布局; 两个相邻盒子之间的垂直距离将由margin属性来决定,并且属性值会合并,只保留最大的;每个盒子的左外缘将与其容器的左边界接触(在从右到左的渲染模式下是右接触),即使在浮动元素参与其中的情况下它也适用(虽然盒子会因float而收缩宽度),除非这个盒子内建立一个新的BFC(在这种情况下盒子本身会因有浮动兄弟变得更窄)。
如何使元素内部建立BFC?
浮动元素、绝对定位元素、非块级盒子的块容器盒子(例如display为inline-block、table-cell、table-caption)、overflow属性不为visible(除非它的值已经传播到viewport中)的块级盒子
IFC的布局规则
IFC内部的盒子将从其容器的顶部开始,被一个接一个地水平布局,它们水平方向上的边距、边框、内边距都互不影响,包含这些盒子的矩形区渲染成一个行,称为行盒子(line box)。行盒子的宽度是根据其容器与浮动情况来决定的,高度是根据“行高计算规则”来决定的,并且它的高度永远足够容纳它包含的内容。
当若干个行级盒子无法放在同一个行盒子中时,它们会被分布到两个或多个垂直堆叠的行盒子中。 一个<p></p>可以理解为若干个垂直堆叠的行盒子。 堆叠的行盒子不垂直分离(有例外)也不垂直重叠。
一般情况下,行盒子的左边界与其容器的左边界接触(在从右到左的渲染模式下是右接触)。 但是,浮动的盒子将阻碍它们的接触。 因此,虽然通常在同一个inline渲染环境下的行盒子都有相同的宽度(就是其容器的宽度),但在有效水平空间因float的存在而减少时,它们的的宽度也会发生变化。 同一个IFC中的行盒子一般在高度上变化(比如一行中有一个很高的图片,但是其它行只有文字)。
当inline级盒子的总宽度小于容纳它们的行盒子的宽度时,它们在这行中水平分布的方式根据text-align属性来定义。 如果该属性设置了justify这个值,浏览器可以在行盒子中展开空白区域和单词(不用于inline-table和inline-block)。 当一个inline盒子的宽度超出了整行的宽度,它将被切成若干个盒子并跨行分布。 如果一个inline盒子无法被切开(例如,如果一个inline盒子只包含一个字符,或特定语言的单词在切割规则中不允许被切开,或这个inline盒子受white-space属性值nowrap、pre的影响),那么这个inline盒子将溢出所在的行盒子。当一个inline盒子被切开时,在切口处margin、border、padding都没有视觉效果。
如何使元素内部建立IFC?
当一个块容器盒子不包含块级盒子的时候,其内部的渲染环境为IFC;
GFC的布局规则
在GFC中,可以通过在网格容器(grid container)上定义网格定义行(grid definition rows)和网格定义列(grid definition columns)属性,在网格项目(grid item)上定义网格行(grid row)和网格列(grid columns),并为每一个网格项目(grid item)定义位置和空间。
如何使元素内部建立GFC?
当为一个元素设置display值为grid的时候,此元素将会获得一个独立的渲染区域GFC。
FFC的布局规则
FFC中的每一个子元素都是一个伸缩项目;伸缩项目可以是任意数量的;伸缩容器外和伸缩项目内的一切元素都不受影响。其容器有相关属性定义内部的伸缩项目如何布局。
如何使元素内部建立GFC?
当为一个元素的display值为flex或者inline-flex的时候,此元素将会获得一个独立的渲染区域GFC;设置为 flex 的容器被渲染为一个块级元素,而设置为 inline-flex 的容器则渲染为一个行内元素。
比较常见的误解
1.display值为block,其内部就为BFC;值为inline-block,其内部为IFC;
首先display为inline-block的元素,其内部渲染环境为BFC,但他自己参与IFC。那什么叫参与呢?回忆下IFC的建立机制就明白,一旦元素内部拥有块级元素,该元素内部就不可能为IFC。从而也能得到display为block的元素,内部的渲染环境取决于子元素的类型。
2.BFC内的行内元素特殊,不是按照所说的布局,从上向下垂直堆叠的。
先从一个简单的例子入手:
<div><span> span的文字 </span><p> p的文字 </p></div>
这个例子中的,浏览器展现的是“span的文字”一行,“p的文字”一行,可以理解为该span外层包裹了一个隐性(匿名)的块容器盒子。官方的解释如下图:
注意下红框中的“To make it easier to define the formatting”。它们都是后面为了统一说明、规划而出现的定义... (这也是在概念一中,我把“为了描述”、“定义”加黑的原因)
也就是说,行内元素在BFC中,应该理解为外面有一个内部渲染方式为IFC的块级元素,或者说相应个行盒子。
3.定位机制就这几种(常规流中的BFC,IFC,GFC,FFC、绝对定位、浮动等),是非此即彼的关系。
再次强调,这些概念只是用来描述、规范浏览器的布局的。第一点:在W3C的官网里面原话是
In CSS 2.2, a box may be laid out according to three positioning schemes:
注意,它这里用的是“may”;第二点:在说明书里面至少还提到了TFC(Table formatting contexts)
参考网站:
https://www.w3.org/TR/CSS22/Overview.html#minitoc
https://juejin.im/entry/5938daf7a0bb9f006b2295db?utm_medium=hao.caibaojian.com&utm_source=hao.caibaojian.com
网友评论