在解释BFC之前,先说一下文档流。我们常说的文档流其实分为定位流、浮动流、普通流三种。 普通流(Normal flow)
- 在常规流中,盒一个接着一个排列;
- 在块级格式化上下文里面, 它们竖着排列;
- 在行内格式化上下文里面, 它们横着排列;
- 当position为static或relative,并且float为none时会触发常规流;
- 对于静态定位(static positioning),position: static,盒的位置是常规流布局里的位置;
- 对于相对定位(relative positioning),position: relative,盒偏移位置由top、bottom、left、right属性定义。即使有偏移,仍然保留原有的位置,其它常规流不能占用这个位置。
浮动(Floats)
- 左浮动元素尽量靠左、靠上,右浮动同理
- 这导致常规流环绕在它的周边,除非设置 clear 属性
- 浮动元素不会影响块级元素的布局
- 但浮动元素会影响行内元素的布局,让其围绕在自己周围,撑大父级元素,从而间接影响块级元素布局
- 最高点不会超过当前行的最高点、它前面的浮动元素的最高点
- 不超过它的包含块,除非元素本身已经比包含块更宽
- 行内元素出现在左浮动元素的右边和右浮动元素的左边,左浮动元素的左边和右浮动元素的右边是不会摆放浮动元素的
绝对定位(Absolute positioning)
- 绝对定位方案,盒从常规流中被移除,不影响常规流的布局;
- 它的定位相对于它的包含块,相关CSS属性:top、bottom、left、right;
- 如果元素的属性position为absolute或fixed,它是绝对定位元素;
- 对于position: absolute,元素定位将相对于上级元素中最近的一个relative、fixed、absolute,如果没有则相对于body;
BFC(块级格式化上下文)的概念和应用
定义:理解为某个元素的一个CSS属性,BFC是一个完全独立的空间,让空间里的子元素不回影响到外面的布局,拥有这个属性的元素对内部元素和外部元素会表现出一些特性,这就是BFC。
BFC是页面中的一块渲染区域,有一套渲染规则,决定了其子元素将如何定位,以及和其他元素的关系和相互作用。
满足下列条件之一就会触发BFC
根元素,即HTML元素
元素设置浮动:float除none以外的值
overflow值为:auto、scroll、hidden
display值为:inline-block(行内块元素)、table-cell、table-caption(此元素会作为一个表格标题显示)(类似
<caption>)、flex等
元素设置绝对定位:position:(absolute、fixed)。
BFC的渲染规则
- 垂直方向上,自上而下排列,和文档流的排列方式一致。
- 在BFC中上下相邻的两个容器的margin会发生重叠
- 每个元素的左margin值和容器的左border相接触。
- BFC的区域不会与float box重叠。
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之也如此。
- 计算BFC容器的高度时,需要计算浮动元素的高度。
BFC作用与原理(overflow:hidden)
清除内部浮动
<style>
.par {
border: 5px solid #fcc;
width: 300px;
}
.child {
border: 5px solid #f66;
width:100px;
height: 100px;
float: left;
}
</style>
<body>
<div class="par">
<div class="child"></div>
<div class="child"></div>
</div>
</body>
上述代码出现的情况如下:
解析:出现上述情况的是因为计算BFC的高度时,浮动元素也参与计算
解决:
为达到清除内部浮动,我们在父元素上设置overflow:hidden,触发par生成BFC,那么par在计算高度时,par内部的浮动元素child也会参与计算。
.par {
overflow: hidden;
}
效果如下:
防止margin重叠的问题
<style>
p {
color: #f55;
background: #fcc;
width: 200px;
line-height: 100px;
text-align:center;
margin: 100px;
}
</style>
<body>
<p>Haha</p>
<p>Hehe</p>
</body>
显示效果:
两个p之间的距离为100px,发送了margin重叠。
解决办法:
<style>
.wrap {
overflow: hidden;
}
p {
color: #f55;
background: #fcc;
width: 200px;
line-height: 100px;
text-align:center;
margin: 100px;
}
</style>
<body>
<p>Haha</p>
<div class="wrap">
<p>Hehe</p>
</div>
</body>
实现效果:
自适应两栏布局
<style>
body {
width: 300px;
position: relative;
}
.aside {
width: 100px;
height: 150px;
float: left;
background: #f66;
}
.main {
height: 200px;
background: #fcc;
}
</style>
<body>
<div class="aside"></div>
<div class="main"></div>
</body>
解决方法
我们可以通过设置父元素overflow:hidden,触发main生成BFC, 来实现自适应两栏布局。
.main {
overflow: hidden;
}
当触发main生成BFC后,这个新的BFC不会与浮动的aside重叠。因此会根据包含块的宽度,和aside的宽度,自动变窄。效果如下:
IFC 行内格式化上下文(Inline formatting context)
触发条件
一个块级元素中仅包含内联级别元素。
对于IFC,行内框一个接一个地排列,排列顺序和书写方向一致。
- 水平书写模式,行内框从左边开始水平排列
- 垂直书写模式,行内框从顶部开始水平排列
FFC(自适应格式化上下文)
display值为flex或者inline-flex的元素将会生成自适应容器(flex container)
GFC(网格布局格式化上下文)
当为一个元素设置display值为grid的时候,此元素将会获得一个独立的渲染区域,我们可以通过在网格容器(grid container)上定义网格定义行(grid definition rows)和网格定义列(grid definition columns)属性各在网格项目(grid item)上定义网格行(grid row)和网格列(grid columns)为每一个网格项目(grid item)定义位置和空间。