BFC
BFC的定义
块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。
BFC的布局规则
内部的box会在垂直方向,一个接一个地放置。
box的垂直方向的距离由margin决定,属于同一个BFC的两个相邻的box的margin会重叠。
BFC的区域不会与float box重叠。
BFC一个独立被隔离的容器,容器中的子元素不会影响到外面的元素,反之亦然。
5.计算BFC高度时,浮动元素也参与计算。
如何创建BFC
下列方式会创建块格式化上下文:
摘抄自(https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Block_formatting_context)
- 根元素(
<html>)
- 浮动元素(元素的
float
不是none
) - 绝对定位元素(元素的
position
为absolute
或fixed
) - 行内块元素(元素的
display
为inline-block
) - 表格单元格(元素的
display
为table-cell
,HTML表格单元格默认为该值) - 表格标题(元素的
display
为table-caption
,HTML表格标题默认为该值) - 匿名表格单元格元素(元素的
display
为table、``table-row
、table-row-group、``table-header-group、``table-footer-group
(分别是HTML table、row、tbody、thead、tfoot 的默认属性)或inline-table
) -
overflow
计算值(Computed)不为visible
的块元素 -
display
值为[flow-root](https://drafts.csswg.org/css-display/#valdef-display-flow-root)
的元素 -
contain
值为layout
、content
或 paint 的元素 - 弹性元素(
display
为flex
或inline-flex
元素的直接子元素) - 网格元素(
display
为grid
或inline-grid
元素的直接子元素) - 多列容器(元素的
column-count
或column-width
<small style="box-sizing: border-box;">(en-US)</small> 不为auto,包括 ``column-count
为1
) -
column-span
为all
的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中(标准变更,Chrome bug)。
利用BFC解决的问题
1.外边距塌陷
问题演示:
<style>
* {
margin: 0;
padding: 0;
}
div {
width: 100px;
height: 100px;
background-color: #0ff;
margin: 20px auto;
}
</style>
<body>
<div class="box1"></div>
<div class="box2"></div>
</body>
结果如下:
两个div之间应该有40px的间距,可是却只有20px。其原因就是两个容器处在同一个BFC在同一个BFC中两个块元素的margin会重叠,而如果我们让这两个box处于两个同的BFC中就解决这一个问题。
解决问题:
<style>
* {
margin: 0;
padding: 0;
}
.box {
width: 100px;
height: 100px;
background-color: #0ff;
margin: 20px auto;
}
.bfc{
overflow: hidden;
}
</style>
<body>
<div class="bfc"><div class="box"></div>
<div class="bfc"><div class="box"></div>
</body>
在box的外层再加上一个div,并用css声明
overflow:hidden;
使得外层的div触发了BFC让两个box处于不同的BFC区域就能实现margin不在重叠的效果。
实现效果:
如果用别的方法触发BFC达到的效果是一样的:
譬如:给.bfc声明display:flex;
与display:grid;
等等能触发BFC的方法同样能达到一样的效果。
2.利用BFC解决包含塌陷
问题演示:
<style>
* {
margin: 0;
padding: 0;
}
.son {
width: 100px;
height: 100px;
background-color: #0ff;
margin-top: 20px;
}
.father{
width: 200px;
height: 200px;
background-color: #ff0;
margin: 0 auto;
}
</style>
<body>
<div class="father"><div class="son"></div>
</body>
效果:
原本只加给子元素的margin值却影响到父元素,使得父元素也具有了20px的上边距,这并不是我们想要的效果。我们要的是让子元素在父元素中拥有20px的上边距,并且对父元素不造成任何影响。所以按照思路我们可以将父元素独立出来形成一个新的BFC区域,这样子元素就不会对父元素又任何的影响。
解决代码:
<style>
* {
margin: 0;
padding: 0;
}
.son {
width: 100px;
height: 100px;
background-color: #0ff;
margin-top: 20px;
}
.father{
width: 200px;
height: 200px;
background-color: #ff0;
margin: 0 auto;
overflow: hidden;
}
</style>
<body>
<div class="father"><div class="son"></div>
</body>
效果:
3.BFC解决浮动带来的高度塌陷
一般情况下一个不设值高度的父元素的高度是由子元素撑开的如下:
<style>
.father {
width: 400px;
background-color: #0ff;
}
.son {
height: 100px;
width: 100px;
background-color: #ff0;
border: 1px solid red;
}
</style>
<body>
<div class="father">
<div class="son"></div>
<div class="son"></div>
<div class="son"></div>
<div class="son"></div>
<div class="son"></div>
</div>
</body>
效果如下:
而如果给所有的子元素加上浮动,则父元素会失去他原本的高度,这就是浮动带来的高度塌陷。
.son {
height: 100px;
width: 100px;
background-color: #ff0;
border: 1px solid red;
float: left;
}
效果如下:
如果想让父元素继续被子元素撑开则要在父元素中创建BFC;例如:给父元素加
overflow:hidden;
.father {
width: 400px;
background-color: #0ff;
overflow: hidden;
}
就可以得到我们想要的效果
同时利用BFC也以避免被浮动起来的盒子覆盖另一个盒子的问题
<style>
.box1 {
width: 100px;
height: 100px;
background-color: #0ff;
float: left;
}
.box2 {
height: 300px;
width: 300px;
background-color: #ff0;
}
</style>
<body>
<div class="box1"></div>
<div class="box2"></div>
</body>
会得到这样的效果:
box1脱离了布局流 并且覆盖了box2的一部分区域,同样的我们可以给.box2添加
overflow:hidden;
给box2创建一个BFC就可以解决这个问题。
清除浮动
浮动会让原本的元素脱离布局流从而打乱网页布局,所以当我们使用了浮动后最好养成清除移动的习惯。
css属性:clear
clear的作用是规定这个元素的哪一侧不允许有浮动元素,clear总共有五个属性。
clear:none;
默认值,允许元素的两侧有浮动。
clear:left;
不允许元素的左侧有浮动。
clear:right;
不允许元素的右侧有浮动。
clear:both;
不允许元素的两侧有浮动。
clear:inherit;
从父元素继承 clear 属性的值。
解决浮动的方法
就拿刚刚高度塌陷的例子来演示:
1.在父元素中的添加最后一个子元素(块级元素),并在其中加clear:both;
<style>
.box1 {
width: 100px;
height: 100px;
background-color: #0ff;
float: left;
}
.clearfix {
height: 0;
overflow: hidden;
clear: both;
}
.box2 {
height: 300px;
width: 300px;
background-color: #ff0;
}
</style>
<body>
<div class="container">
<div class="box1"></div>
<div class="clearfix"></div>
</div>
<div class="box2"></div>
</body>
缺点:造成不必要的浪费
2.给父元素添加overflow:hidden;
这就是之前所说的创建BFC,缺点是父元素超出的部分会被隐藏导致和我们想要的效果有出入,影响网页的布局。
3.伪元素清除法
利用伪元素:after清除浮动
.clearfix::after {
content: '';
display: block;
height: 0;
overflow: hidden;
visibility: hidden;
clear: both;
zoom: 1;
}
在实际操作的过程中再在父元素添加类名clearfix即可。
<style>
.box1 {
width: 100px;
height: 100px;
background-color: #0ff;
float: left;
}
.clearfix::after {
content: '';
display: block;
height: 0;
overflow: hidden;
visibility: hidden;
clear: both;
zoom: 1;
}
.box2 {
height: 300px;
width: 300px;
background-color: #ff0;
}
</style>
<body>
<div class="container clearfix">
<div class="box1"></div>
</div>
<div class="box2"></div>
</body>
这种方法没有什么缺点,也是最常用清除浮动的方法,可以将这个样式写进base.css中导入。