一、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,根据规则第3、4、5条,BFC的区域是独立的,不会与页面其他元素相
互影响,且不会与float元素重叠,因此就可以形成两列自适应布局</main>
</div>
</body>
</html>
4、BFC 能解决什么样的问题?
- bfc 区域不与 float 区域重叠。
- 双边距问题。
- 计算 bfc 高度,浮动元素也参与计算。
- 子集浮动元素,父级 overflow:hidden 具有高度
二、IFC
IFC(Inline Formatting Contexts)直译为"内联格式化上下文"。
1、触发条件
一个块级元素中仅包含内联级别元素
2、IFC布局规则
- 子元素水平方向横向排列,并且垂直方向起点为元素顶部。
- 子元素只计算横向样式空间,padding、border、margin在垂直方向上的样式空间不会被计算。
- 在垂直方向上,子元素会以不同形式来对齐vertical-align
- 能把在一行上的框都完全包含进去的一个矩形区域,被称为该行的行框(line box)。行框的宽度是由包含块(containing box)和与其中的浮动来决定。
- IFC中的“line box”一般左右边贴紧其包含块,但float元素会优先排列。
- IFC中的“line box”高度由 CSS 行高计算规则来确定,同个IFC下的多个line box高度可能会不同。
- 当 inline-level boxes的总宽度少于包含它们的line box时,其水平渲染规则由text-align 属性值来决定。
- 当一个“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 下的子元素不会继承父级容器的宽