4.0格式化上下文系列——IFC、BFC、TFC、GFC 、FFC、RFC(6种)

340 阅读6分钟

本人已参与新人「创作礼活动」,一起开启掘金创作之路。

格式化上下文:元素在页面上水平或垂直排布时彼此之间有何种影响;对此,CSS有几套不同的规则。本文主要介绍 IFC、BFC

一、IFC (inline formatting content) 内联格式化上下文

IFC的line box(线框)高度由其包含行内元素中最高的实际高度计算而来(不受到竖直方向的padding/margin影响)

1.1 IFC常见用途:

水平居中:当一个块要在环境中水平居中时,设置其为inline-block则会在外层产生IFC,通过text-align则可以使其水平居中。

垂直居中:创建一个IFC,用其中一个元素撑开父元素的高度,然后设置其vertical-align:middle,其他行内元素则可以在此父元素下垂直居中。

1.2 布局规则

  1. 排版:IFC中的元素会在一行中从左到右排列;且在每一行都会形成一个新的行框;行框的元素内遵循text-align和vertical-align
  2. 不可变大小:对行内盒子设置宽度、高度不起作用;行内盒子文本的垂直方向上的间距不受其垂直方向上的内边距、边框、外边距的影响; 尤其是外边距根本无任何作用,边框、内边距在多行文本中,下面文本的会遮挡上面的文本内容; 每行文本都有上下边框、内边距,而左右边框仅存在于行内盒子的开始和结尾处
  3. 可变大小:行框的高度为包含框的高度,高度为行框中最高元素的高度; 垂直方向可以通过修改行高 line-height(决定一个内联元素的真实占行高度) 水平方向可通过修改内边距、边框、外边距的大小;
  4. 行盒子缩短:浮动的元素不会在行框中,并且浮动元素会压缩行框的宽度;

image.png

.box {
    width: 450px;
    height: 300px;
    border: 1px solid red;
}
span {
    line-height: 24px;
    padding: 5px 20px;
    /* 上下外边距不起任何作用 */
    margin: 20px 20px;
    border: 3px solid green;
    background-color: pink;
    font-size: 16px;
}

<div class="box">
    <span>1. 行内盒子沿文本流水平排列,也会随文本换行儿换行</span>
    <span>
        2. 行内盒子的大小:设置宽度、高度不起作用;
           可以通过修改行高 line-height(决定一个内联元素的真实占行高度) 
           或者水平方向的内边距、边框、外边距
    </span>
    <span>
        3. 行内盒子文本的垂直间距不受其垂直方向上的内边距、边框、外边距的影响;
           同时,外边根本无任何作用,而边框、内边距会在多行文本中,下面文本的会遮挡上面的文本内容;
           每行文本都有上下边框、内边距,而左右边框仅存在于行内盒子的开始和结尾处。
    </span>
</div>

二、BFC (Block Formatting Contexts) 块格式化上下文

块级格式化上下文,形成一个独立的渲染区域来规定内部如何布局,且与这个区域外部毫不相干。

2.1 触发BFC的几种方式

注意: 这几种方式,不一定在任何情况下都能得到你想要的结果!!!在某些场景下,使用下面的某个方式会起作用;在其他场景下,使用另外的方式才会起作用;不能进行粗犷的统一论断,要想彻底吃透需要下功夫进行细扣、深思和研究

1. 根元素,即HTML元素
2. float 非 none
3. position 非 relative和static
4. overflow 非 visible
5. dispaly: inline-block、block、table-cell、flex、inline-flex;
其他方式

2.2 BFC的3种用途

1. 自适应多栏布局
2. 防止高度塌陷 (即高度包住浮动元素)
3. 防止垂直方向上margin折叠 (折叠条件:只发生在常规文档流中块级盒子的垂直方向上!!!)

1)自适应多栏布局 (注意两个浮动的img要写在前,且给非浮动元素使用左右margin是从父盒子的左右边开始的;可以选择给浮动元素设置margin)

image.png

image.png

.box { width: 300px; border: 1px solid blue; }
.img1 { float: left; width: 100px; }
/* .img1 { float: left; width: 100px; margin-right: 10px; } */
.img2 { float: right; width: 100px; }
/* .img2 { float: right; width: 100px;  margin-left: 10px; } */
.box2 { background-color: pink; overflow: auto; }

<div class="box">
    <img class="img1" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fdesk-fd.zol-img.com.cn%2Ft_s960x600c5%2Fg2%2FM00%2F00%2F0B%2FChMlWl6yKqyILFoCACn-5rom2uIAAO4DgEODxAAKf7-298.jpg" alt="">
    <img class="img2" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fdesk-fd.zol-img.com.cn%2Ft_s960x600c5%2Fg2%2FM00%2F00%2F0B%2FChMlWl6yKqyILFoCACn-5rom2uIAAO4DgEODxAAKf7-298.jpg" alt="">
    <div class="box2">
        创建自己的块级格式化上下文,形成一个独立的渲染区域来规定内部如何布局,且与这个区域外部毫不相干
    </div>
</div>

2)防止高度塌陷

外边距重叠时边距计算规则:

符号参与运算
1) margin同正,则取最大值;
2) margin同负,则取最小值;
3) margin一正一负,则取二者之和。
  • 普通情况对比

image.png

.box { width: 300px; border: 1px solid blue;}
.img1 { float: left; width: 100px; }
.box2 { background-color: pink;}

<div class="box">
    <img class="img1" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fdesk-fd.zol-img.com.cn%2Ft_s960x600c5%2Fg2%2FM00%2F00%2F0B%2FChMlWl6yKqyILFoCACn-5rom2uIAAO4DgEODxAAKf7-298.jpg" alt="">
    <div class="box2">
        创建自己的块级格式化上下文
    </div>
</div>

image.png

.box { width: 300px; border: 1px solid blue; overflow: auto; }

3)防止垂直方向上margin折叠

  • 折叠条件: 只发生在常规文档流中块级盒子的垂直方向上

  • 折叠分类:

    • 父子元素之间 —— 仅限给父元素设置内边距、边框、::before伪元素(必须带height属性且值大于零)来分割外边距;overflow: hidden 触发BFC;提示:outeline不可以,只是装饰线,不占实际空间,会遮挡周围元素。
    • 兄弟元素之间 —— 外层元素margin边距用padding代替display: inline-flex, display: inline-block,注意此时的flex | block是不起作用的
    • 空元素自身 —— 增加文本(如123)、内边距、边框、::before|after伪元素(带height属性且值大于零)来分割外边距; overflow: hidden 触发BFC
    • 递归折叠 —— 折叠后的外边距又碰到了其他元素的外边距,还会继续折叠

image.png

image.png

* { padding: 0; margin: 0;}
body { background-color: palegreen;}
/* .box { width: 300px; background-color: pink; margin-top: 30px; } */
.box { width: 300px; background-color: pink; margin-top: 30px; overflow: hidden; }
.box1 { width: 100px; height: 100px; background-color: red; margin-top: 20px; }
        
<div class="box">
    <div class="box1"></div>
</div>

image.png

.box { width: 300px; background-color: pink; }
.box1 { width: 100px; height: 100px; background-color: red; padding-bottom: 30px; background-clip: content-box; border: 1px solid goldenrod;}
.box2 { width: 100px; height: 100px; background-color: red; padding-top: 20px; background-clip: content-box; border: 1px solid goldenrod;}
   
<div class="box">
    <div class="box1"></div>
    <div class="box2"></div>
</div>

image.png

image.png

image.png

.box { width: 300px; background-color: pink; }
.box1 { width: 100px; height: 100px; background-color: red;}
/* .box2 { margin: 20px; } */
/* .box2 { margin: 20px; overflow: hidden; } */
.box2 { margin: 20px; border: 1px solid red; }
.box3 { width: 100px; height: 100px; background-color: gold; }

<div class="box">
    <div class="box1"></div>
    <div class="box2"></div>
    <div class="box3"></div>
</div>

三、TFC (Table Formatting Contexts) 表格式化上下文

四、GFC (Grid Formatting Contexts) 网格格式化上下文

GFC将改变传统的布局模式,他将让布局从一维布局变成了二维布局。简单的说,有了GFC之后,布局不再局限于单个维度了。这个时候你要实现类似九宫格,拼图之类的布局效果显得格外的容易。

五、FFC (Flex Formatting Contexts) 弹性格式化上下文

整体来说,FFC与BFC有点儿类似,但有以下几点区别:

  1. Flexbox 不支持 ::first-line 和 ::first-letter 这两种伪元素。
  2. vertical-align对Flexbox中的子元素是没有效果的。
  3. float 和 clear 属性对Flexbox中的子元素是没有效果的,也不会使子元素脱离文档流(但是对Flexbox 是有效果的!)。
  4. 多栏布局(column-*) 在 Flexbox 中也是失效的,就是说我们不能使用多栏布局在Flexbox 排列其下的子元素。
  5. Flexbox 下的子元素不会继承父级容器的宽度。

六、RFC (Region Formatting Contexts) 区域格式化上下文