css BFC、IFC、GFC、FFC、TFC格式化上下文

395 阅读7分钟

概念

布局流方案

1.普通流 (normal flow)

元素按照其在 HTML 中的先后位置至上而下布局,在这个过程中,行内元素水平排列,直到当行被占满然后换行,块级元素则会被渲染为完整的一个新行,除非另外指定,否则所有元素默认都是普通流定位。

可能存在:

  • 相邻元素margin重叠
  • 子元素margin 影响到父元素

2.浮动流 (float)

在浮动布局中,元素首先按照普通流的位置出现,然后根据浮动的方向尽可能的向左边或右边偏移,其效果与印刷排版中的文本环绕相似。会占据空间,脱离的文档流,导致父级无法计算他的子元素高度。

可能存在:

  • 浮动后的子元素脱离了文档流,父容器无法计算子元素高度。
  • 浮动元素覆盖了相邻的元素

3.定位流(position)

在定位流中,绝对定位元素会整体脱离普通流,因此绝对定位元素不会对其兄弟元素造成影响,而元素具体的位置由绝对定位的坐标决定。

盒子概念

1.块级元素

display:block;

h1,p,ul,ol div, table,form,footer

排版方式:从上到下,每一个都独占一行,垂直排版。

2.行内元素

 display:inline; display:inline-block;

a,i (倾斜),b(加粗),em(倾斜,强调语义),span(定义文档中的节),mark(标记加背景色)code,

排版方式:从左到右,依次紧挨,放不下换行,水平排版。

Formatting Context 格式化上下文

它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。 包含4种

  • BFC : 块级Block-格式化上下文, CSS2.1 标准
  • IFC : 行内级Inline-格式化上下文, CSS2.1 标准
  • TFC : 网格级Table-格式化上下文, CSS2.1 标准
  • FFC : 弹性级Flex-格式化上下文, CSS3 标准
  • GFC : 网格级Grid-格式化上下文, CSS3 标准

1.BFC 块级

1.定义

Block Formatting Context

具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,外部也不会影响内部,并且 BFC 具有普通容器所没有的一些特性。 BFC 理解为一个封闭的大箱子。

注意: 块级有两种情况

  • 做父容器的场景
  • 自己是子元素的场景

2.特征:

父容器:

  • 容器能够包含浮动元素,即浮动元素变回普通流,占用普通流空间。
  • 和其他浮动的子元素产生边界
  • 清除的样式规则只适用与同一个上下文。 子元素:
  • 清除浮动只清除在他前面的元素浮动。

3.布局规则

  • 每个子元素都是垂直布局,独占一行
  • 垂直的高度= 子元素的边框内高度 + 子元素的margin-top + margin-bottom
  • 水平的宽度= 子元素的边框内宽度 + 子元素的margin-left + margin-right
  • 上下的子元素margin-top和bottom会重叠,左右left,right不会重叠。 image.png

3.触发条件:

  • body 根元素
  • 浮动元素:float 除 none 以外的值
  • 绝对定位元素:position 除了默认值static和relative 以外的值 absolute、fixed
  • display 为 inline-block、flex、inline-flex、table、table-cell、table-caption
  • overflow 除了 默认值visible 以外的值 (hidden、auto、scroll)
  • display:flow-root 最新的css语法兼容差

4.解决场景

1. 解决父容器高度坍塌, BFC可以包含计算浮动的元素的高度,

<html>
<head>
    <style> 
      * { margin: 0; padding: *;}
        .outer {   
             border: 2px solid  red;  
        }
        .box {
            width: 100px;
            height: 100px; 
            background-color: gray;
            float: left;
        }
    </style>
</head>
<body>
    <div class="outer">
            <div class="box"></div>   
    </div>
</body>
</html>

image.png 由于容器内元素浮动,脱离了文档流,所以容器只剩下 2px 的边距高度。

如果使触发容器的 BFC,那么容器将会包裹着浮动元素。

.outer {   
     border: 2px solid  red;  
     overflow: hidden;/*打开BFC*/
}

image.png

最优办法

不使用bfc,clear:botn清除浮动 + 添加伪类实现。

.outer:after { 
display: table;
height:0; /*部分浏览器需要指定table高度*/ 
content: "";
clear: both; 
}

2. 两个相邻的元素margin外边距垂直方向-会发生重叠

<html>
<head>
    <style>
        .outer { 
            border: 1px solid green;
        }
        .box {
            width: 100px;
            height: 100px;
            margin: 50px;
        }
        .box1 {
            background-color:  black; 
        } 
        .box2 { 
            background-color:  red;   
        } 
    </style>
</head>
<body>
    <div class="outer">
        <div class="box box1"></div>  
        <div class="box box2"></div>  
    </div>
</body>
</html>

image.png 解决办法,在其中一个box外部包裹一个bfc,

<html>
<head>
    <style>
        .outer { 
            border: 1px solid green;
        }
        .box {
            width: 100px;
            height: 100px;
            margin: 50px; 
        }
        .box1 {
            background-color:  black; 
        } 
        .box2 { 
            background-color:  red;   
        } 
        .outbox { 
            overflow: hidden;/*打开bfc模式 ,两个div都开启bfc模式*/
        } 
    </style>
</head>
<body>
    <div class="outer"> 
        <div class="box box1"></div>   
        <div class="outbox">
            <div class="box box2"></div>  
        </div>
    </div>
</body>
</html>

image.png

最优办法

使用伪类,在父容器outbox通过伪类,在box2前面多添加一个子元素并且设置为bfc。

.outbox { 
} 
.outbox::before { 
    display:table;
    content:""; /*伪类必须设置内容 不然无效*/
} 

3. 父子关系,子元素margin影响父元素的margin

<html>
<head>
    <style> 
      * { margin: 0; padding: *;}
        .outer {  
            width: 300px;
            height: 300px; 
            background-color:  red; 
        }
        .box {
            width: 100px;
            height: 100px; 
            background-color:  black; 
            margin-top: 50px; 
        }
    </style>
</head>
<body>
    <div class="outer">
            <div class="box"></div>   
    </div>
</body>
</html>

image.png 这时候父容器包裹成bfc,这样bfc的变化都不影响外部。

.outer {  
    width: 300px;
    height: 300px; 
    background-color:  red; 
    overflow: hidden;
}

image.png

缺点:如果父容器有其他定位内容需要显示,会被切割。

其他办法

  1. 父容器设置padding-top 代替子元素的margin-top

缺点: 改变了父元素的大小,需要改变IE盒子模型。

.outer {  
    width: 300px;
    height: 300px; 
    background-color:  red; 
    padding-top : 50px;
    box-sizing: border-box; /*改变为IE盒子 content = content + padding +border*/
}
  1. 父容器添加border 添加额外的边框,可以使父容器不被元素影响。

但是而且改变了父元素的大小,而且元素位置也变化了。

image.png

.outer {  
    width: 300px;
    height: 300px; 
    background-color:  red; 
    border: 1px solid transparent; /*设置一个透明的边框*/
    box-sizing: border-box; /*改变为IE盒子 content = content + padding +border*/
}
.box {
    width: 100px;
    height: 100px; 
    background-color:  black; 
    margin-top: 50px; 
    margin-left: -1px;/*修复父容器border的1px*/
}
  1. 父容器多添加一个排第一的子元素
    table 不占用空间,缺点 :多了一个元素
<html>
<head>
    
</head>
<body>
    <div class="outer">
             <table></table>   <!-- 新增一个标签 -->
            <div class="box"></div>   
    </div>
</body>
</html>
  1. 父容器多添加一个排第一的子元素

最优方法

使用伪类,在父容器outer通过伪类,在box前面多添加一个子元素并且设置为bfc。

outer::before {
    display:table;
    content:"";
}

4. 实现两列布局,左边固定,右边自适应,BFC可以阻止元素被浮动元素覆盖,

<html>
<head>
    <style> 
      * { margin: 0; padding: *;}
      .box1 {
        width: 100px;
        height: 100px;
        background: lightblue; 
        float : left;
    }
    .box2 {
        width: 200px;
        height: 200px;
        background: red; 
        overflow: hidden;
    }
    </style>
</head>
<body>
    <div class="box1">我是一个左浮动的元素</div>
    <div class="box2">我是一个没有设置浮动XXXXXXXXXXXXXXXXXXXXXXXXXXXXX</div>
</body>
</html>

image.png

在box2 添加overflow:hidden 打开bfc模式,

.box2 {
   width: 200px;
   height: 200px;
   background: red; 
   overflow: hidden;/*打开BFC*/
}

image.png

2.IFC 行内

定义

行内格式化上下文 Inline Formatting Contexts

在同一个父容器下,多个行内子元素会形成 IFC

line-box

Line box是由一行同级或多级inline或inline-box元素组成的区域

行内框一个接一个地排列,排列顺序和书写方向一致。

  • 能把在一行上的框都完全包含进去的一个矩形区域,被称为该行的行框(line box)。

触发条件:

  • 块级元素中仅包含内联级别元素 display为 inline,inline-block

特点:

  • 内部的盒子会在水平方向,一个个地放置,水平的外边距,内边距,边框是可以有的;
  • 是当 IFC 中有块级元素插入时,会产生两个匿名块将父元素分割开来,产生两个IFC

横向相关

  • IFC 中的行框一般左右边贴紧其包含块,但 float 元素会优先排列;
  • IFC 中盒子的总宽度少于包含它们的行框时,其水平渲染规则由 text-align 属性值来决定;
  • 当一个行内元素超过父元素的宽度时,它会被分割成多个盒子,这些盒子分布在多个行框中。如果子元素未设置强制换行的情况下,行框将不可被分割,将会溢出父元素。
  • float元素会位于IFC与line box之间,使得line box宽度缩短。
  • IFC 的行框的宽度:由包含块和与其中的浮动来决定;

纵向相关

  • IFC 的高度:由最高盒子的高度决定;(不受到竖直方向的padding/margin影响)
  • 当一行不够放置的时候会自动切换到下一行;
  • 根据 vertical-align 属性垂直对齐,middle实现垂直居中。
  • 同个ifc下的多个line box高度会不同。

3.TFC-表格

定义

表格格式化上下文,Flex Formatting Context

触发条件

使用表格嵌套内容+定义表格宽度。

 <style>
    table{
        width: 100%;
    }
</style>
<table>
    <thead>
        <th>标题1</th>
        <th>标题2</th>
    </thead>
    <tbody> 
        <td>aa</td>
        <td>bb</td>
    </tbody>
</table>

特点

上下对齐,左右对齐,文字默认居中

4.FFC-弹性

定义

弹性格式化上下文 Flex Formatting Context

触发条件

display:flex; /*块级元素*/
/*或者*/
display:inline-flex; /*行内元素*/

特点

容器内容自适应伸缩,可以根据设置的flex值 来控制占用空间比重。

5.GFC-网格

定义

网格格式化上下文 GridLayout Formatting Context

触发条件

display:grid;

特点

能有一个独立的渲染区域,可以在网格容器上定义网格行和列,为每一个网格定义位置和空间。