介绍下BFC,IFC,GFC和FFC

一、BFC

BFC(Block Formatting Contexts)直译为"块级格式化上下文"。Block Formatting Contexts就是页面上的一个隔离的渲染区域,容器里面的子元素不会在布局上影响到外面的元素,反之也是如此。

1、BFC 由以下之一创建

  • 根元素;(body就是根元素)
  • float 的值不为 none。
  • position 的值为 absolute 和 fixed。
  • 非块级元素具有 display: inline-block,table-cell,table-caption,flex, inline-flex
  • 块级元素具有 overflow,且值不是 visible。

2、BFC布局规则:

2.1、内部的 Box 会在垂直方向,一个接一个地放置。

就是块级元素默认的排放方式。

2.2、Box 垂直方向的距离由 margin 决定。属于同一个 BFC 的两个相邻 Box 的 margin 会发生重叠。

让两个box属于不同 BFC,margin 方向上就不会重叠

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠</title>
		<style>
			.wrap {
				overflow: hidden;
			}
			.box {
				width: 300px;
				height: 50px;
				margin-top: 40px;
				background-color: red;
				overflow: hidden;
			}
		</style>
	</head>
	<body>
		<div class="box">Box垂直方向的距离由margin决定。</div>
		<div class="wrap">
			<div class="box">属于同一个BFC的两个相邻Box的margin会发生重叠。</div>
		</div>
	</body>
</html>

2.3、每个元素的左外边缘(margin-left), 与包含块的左边(contain box left)相接触(对于从左往右的格式化,否则相反),即使存在浮动也是如此。除非这个元素自己形成了一个新的 BFC。

2.4、BFC 的区域不会与 float box 重叠。

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>BFC的区域不会与float box重叠。</title>
		<style>
			.wrap{
				width: 300px;
				height: 300px;
				border: 1px solid red;
				overflow: hidden;
			}
			.box{
				width: 100px;
				height: 100px;
				float: left; // 没有overflow: hidden;两个盒子会重叠
				border: 1px solid green;
			}
		</style>
	</head>
	<body>
		<div class="wrap">aside</div>
		<div class="box">main</div>
	</body>
</html>

2.5、BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。

2.6、计算 BFC 的高度时,浮动元素也参与计算。

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>计算BFC的高度时,浮动元素也参与计算</title>
		<style>
			.wrap {
				border: 1px solid black;
				width: 300px;
				overflow: hidden;
			}
			.box {
				border: 1px solid red;
				width: 100px;
				height: 100px;
				float: left;
			}
		</style>
	</head>
	<body>
		<div class="wrap">
			<div class="box">计算BFC的高度时,浮动元素也参与计算</div>
		</div>
	</body>
</html>

3、BFC 的用处

3.1、防止 margin 发生重叠

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>防止垂直margin合并</title>
		<style>
			section {
				background-color: pink;
				margin-bottom: 100px;
				width: 100px;
				height: 100px;
			}
			.bottom {
				margin-top: 100px;
			}
		</style>
	</head>
	<body>
		<section class="top">防止垂直margin合并</section >
		<section class="bottom">2</section >
	</body>
</html>

可以看到,明明 .top 和 .bottom 中间加起来有 200px 的 margin 值,但是我们只能看到 100px。这是因为他们的外边距相遇发⽣了合并。之所以发⽣外边距折叠,是因为他们 同属于 body 这个根元素,所以我们需要让它们不属于同⼀个 BFC,就能避免外边距折叠.
怎样解决:为其中⼀个元素的外⾯包裹⼀层元素。并为这个外层元素设置 overflow: hidden;,使其形成BFC。因为 BFC 内部是⼀个独⽴的容器,所以不会与外部相互影响,可以防⽌ margin 合并。

<section class="top">1</section>
<div class="wrap">
	<section class="bottom">2</section>
</div>
.wrap {
  overflow: hidden;
 }

3.2、防止发生因浮动导致的高度塌陷

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>清除浮动</title>
		<style>
			.wrap {
				border: 2px solid yellow;
				width: 250px;
				overflow: hidden; 
			}
			section {
				background-color: pink;
				float: left;
				width: 100px;
				height: 100px;
			}
		</style>
	</head>
	<body>
		<div class="wrap">
			<section>加上 overflow: hidden;使其形成BFC,根据BFC规则第六条,计算⾼度时就会计算float的元素的⾼度,达到清除浮动影响的效果。</section>
			<section>2</section>
		</div>
	</body>
</html>

3.3、自适应布局等

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>清除浮动</title>
		<style>
			aside {
				background-color: yellow;
				float: left;
				width: 100px;
				height: 50px;
			}
			main {
				width: 200px;
				background-color: pink;
				overflow: hidden;
			}
		</style>
	</head>
	<body>
		<div class="wrap">
			<aside></aside>
			<main>设置 overflow: hidden; 触发main元素的BFC,根据规则第345条,BFC的区域是独立的,不会与页面其他元素相
				互影响,且不会与float元素重叠,因此就可以形成两列自适应布局</main>
		</div>
	</body>
</html>

4、BFC 能解决什么样的问题?

  • bfc 区域不与 float 区域重叠。
  • 双边距问题。
  • 计算 bfc 高度,浮动元素也参与计算。
  • 子集浮动元素,父级 overflow:hidden 具有高度

二、IFC

IFC(Inline Formatting Contexts)直译为"内联格式化上下文"。

1、触发条件

一个块级元素中仅包含内联级别元素

2、IFC布局规则

  1. 子元素水平方向横向排列,并且垂直方向起点为元素顶部。
  2. 子元素只计算横向样式空间,padding、border、margin在垂直方向上的样式空间不会被计算。
  3. 在垂直方向上,子元素会以不同形式来对齐vertical-align
  4. 能把在一行上的框都完全包含进去的一个矩形区域,被称为该行的行框(line box)。行框的宽度是由包含块(containing box)和与其中的浮动来决定。
  5. IFC中的“line box”一般左右边贴紧其包含块,但float元素会优先排列。
  6. IFC中的“line box”高度由 CSS 行高计算规则来确定,同个IFC下的多个line box高度可能会不同。
  7. 当 inline-level boxes的总宽度少于包含它们的line box时,其水平渲染规则由text-align 属性值来决定。
  8. 当一个“inline box”超过父元素的宽度时,它会被分割成多个boxes,这些 boxes 分布在多个“line box”中。如果子元素未设置强制换行的情况下,“inline box”将不可被分割,将会溢出父元素。

3、IFC 一般有什么用呢?

水平居中:当一个块要在环境中水平居中时,设置其为 inline-block 则会在外层产生 IFC,通过 text-align则可以使其水平居中。
垂直居中:创建一个 IFC,用其中一个元素撑开父元素的高度,然后设置其 vertical-align:middle,其他行内元素则可以在此父元素下垂直居中。

4、主要影响IFC布局的css

  • font-size
  • line-height
  • height
  • vertical-align
  • text-align

5、例子

5.1、垂直间距不生效

<style>
    .wrap {
        border: 1px solid black; 
        display: inline-block;
    }
    .text {
        background: red;
        margin: 30px; // 给子元素加上一个四个方向的margin属性,垂直间距不生效
    }
</style>
<div class = "wrap">
<!-- 布局规则第2条:子元素只会计算横向样式空间,padding、border、margin在垂直方向上的样式空间不会被计算。 -->
    <span class = "text">文本一</span>
    <span class = "text">文本二</span>
</div>

5.2、多个元素水平居中

<style>
   .wrap {
        border: 1px solid black; 
        width: 200px;
        text-align: center;
    }
    .text {
        background: red;
    }
</style>
<div class = "wrap">
<!-- 布局规则第7条:当 inline-level boxes的总宽度少于包含它们的line box时,其水平渲染规则由text-align 属性值来决定。 -->
    <span class = "text">文本一</span>
    <span class = "text">文本二</span>
</div>

5.3、浮动元素优先排列

<style>
   .warp {
       width: 400px;
       border: 1px solid red;
   }
   img {
    float: left;
   }
</style>
<div class="warp">
<!-- 布局规则第4条:行框的宽度是由包含块和与其中的浮动来决定: -->
   <img src = "./img/blue.png">
   Lorem ipsum dolor sit amet, consectetur adipisicing elit.
   Voluptate voluptates culpa nihil officiis ducimus atque maiores
   architecto eligendi veritatis omnis quisquam, nobis, 
   quae a ut totam nesciunt repudiandae ex repellendus.
</div>

5.4、元素垂直居中

<style>
	.father {
	    border: 2px solid red;
	    display: inline-block;
	}
	.pic {
	    height: 100px;
	    /* vertical-align: baseline; 默认值 */
	    vertical-align: middle;
	}
</style>
<div class = "father">
<!-- 布局规则第3条:在垂直方向上,子元素会以不同形式来对齐vertical-align -->
    <img class = "pic" src = "头像.jpeg">
    <span>eryayayaya</span>
</div>

三、GFC

GFC(GridLayout Formatting Contexts)直译为"网格布局格式化上下文"。

1、触发条件

当为一个元素设置 display 值为 grid 的时候,此元素将会获得一个独立的渲染区域,

2、布局规则

通过在网格容器(grid container)上定义网格定义行(grid definition rows)和网格定义列(grid definition columns)属性各在网格项目(grid item)上定义网格行(grid row)和网格列(grid columns)为每一个网格项目(grid item)定义位置和空间。

3、那么GFC有什么用呢,和 table 又有什么区别呢?

首先同样是一个二维的表格,但 GridLayout 会有更加丰富的属性来控制行列,控制对齐以及更为精细的渲染语义和控制。

4、示例

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>GFC网格布局格式化上下文</title>
		<style>
			div {
				margin: 5px;
			}
			.layout {
				display: grid;
				width: 500px;
				height: 400px;
				grid-template-areas:
					"header header header"
					"sidebar content content"
					"footer footer footer";
			}
			.header {
				grid-area: header;
				background: chocolate;
			}
			.aside {
				grid-area: sidebar;
				background: crimson;
			}
			.main {
				grid-area: content;
				background: darkgreen;
			}
			.footer {
				grid-area: footer;
				background: blue;
			}
		</style>
	</head>
	<body>
		<div class="layout">
			<div class="header">头部</div>
			<div class="aside">侧边栏</div>
			<div class="main">内容</div>
			<div class="footer">底部</div>
		</div>
	</body>
</html>

Grid 布局可参考:

四、FFC

FFC(Flex Formatting Contexts)直译为"自适应格式化上下文"。

1、触发条件

display 值为 flex 或者 inline-flex 的元素将会生成自适应容器(flex container),只有谷歌和火狐支持,不过在移动端也足够了,至少safari和chrome还是OK的,毕竟这俩在移动端才是王道。
Flex Box 由伸缩容器和伸缩项目组成。通过设置元素的 display 属性为 flex 或 inline-flex 可以得到一个伸缩容器。

2、布局规则

  • 设置为 flex 的容器被渲染为一个块级元素;
  • 设置为 inline-flex 的容器则渲染为一个行内元素。
  • 伸缩容器中的每一个子元素都是一个伸缩项目。伸缩项目可以是任意数量的。伸缩容器外和伸缩项目内的一切元素都不受影响。简单地说,Flexbox 定义了伸缩容器内伸缩项目该如何布局。

3、应用场景

1、自动撑开页面高度,底栏总是出现在页面的底部

<style>
	.wrap {
		display: flex;
		flex-direction: column;
	    text-align: center;
	    min-height:100vh;
	}
	.header {
	    height: 50px;
	    background-color: rgb(0, 131, 0);
	}
	.main {
	    flex: 1; 
	}
	.footer {
	    height: 30px;
	    background-color: rgb(124, 124, 124);
	}
</style>
<div class = "wrap">
    <div class = "header">顶部导航栏</div>
    <div class = "main">内容</div>
    <div class = "footer">底部</div>
</div>

Flex 布局可参考:

五、FFC与BFC的区别

FFC与BFC有点儿类似,但仍有以下几点区别:

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

版权声明:本文为t13965688123原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。