BFC
BFC(Block Formatting Context),块级格式上下文。
What is BFC ?
BFC 是一块渲染的区域。在这之前,有一块区域叫做 FC 它是默认浏览器支持的渲染区域。
FC:浏览器默认支持的多个盒子之前的排列规则。
BFC:区别于默认浏览器的多个盒子之间的排列规则。
默认 FC 规则
我们先举例,什么是默认的 FC 规则,这样的规则有什么坏处。
外边距塌陷
垂直方向上,当我们设置两个盒子之间都有margin的时候:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style type="text/css">
#green {
margin:10px 10px 10px 10px;
}
#blue {
margin:20px 10px 20px 10px;
}
#red {
margin:30px 10px 30px 10px;
}
</style>
</head>
<body>
<div id="green" style="background:lightgreen;height:100px;width:100px;"></div>
<div id="blue" style="background:lightblue;height:100px;width:100px;"></div>
<div id="red" style="background:pink;height:100px;width:100px;"></div>
</body>
</html>
上下外边距塌陷.png
这与我们想要达到的效果不一致,默认BF盒子排列规则:
两个盒子之间的距离是:(上方盒子的marginBottom + 下方盒子的magrinTop) / 2
浮动子元素父元素的宽高丢失
我们再看一个默认 BF 规则,当同时 float 多个元素的时候。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style type="text/css">
#green {
margin:10px 10px 10px 10px;
float: left;
}
#blue {
margin:10px 10px 10px 10px;
float: left;
}
#red {
margin:10px 10px 10px 10px;
float: left;
}
</style>
</head>
<body>
<div id="Container">
<div id="green" style="background:lightgreen;height:100px;width:100px;"></div>
<div id="blue" style="background:lightblue;height:100px;width:100px;"></div>
<div id="red" style="background:pink;height:100px;width:100px;"></div>
</div>
</body>
</html>
子元素浮动父元素失去宽高.png
当我们查看 DIV#Container 他的宽度为 0,父元素的宽度和高度都已经丢失了;
我们常见的方式是用 清除浮动 来解决,当然,我们也可以采用生成BFC的方式解决。
浮动元素与非浮动元素重叠
当在父元素之内,有两个兄弟元素,一个元素浮动,另一个元素不浮动,就会产生一种状况:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style type="text/css">
#Container {
width: 500px;
}
#green {
float: left;
}
</style>
</head>
<body>
<div id="Container">
<div id="green" style="background:lightgreen;height:100px; width:100px;"></div>
<div id="blue" style="background:lightblue; height:200px; width:200px;"></div>
</div>
</body>
</html>
你能够很明显地看到,两个兄弟元素发生了堆叠,应该如何解决呢?
浮动子元素覆盖兄弟元素.png
我们常用的方式是,将 DIV#blue 也设置为向左浮动,然后用父元素清除浮动;
这样就能够保证父元素的宽度不会丢失,两个元素也不会发生堆叠,另外BFC可以解决这个问题。
使用 BFC 解决以上问题
BFC 的规则就是为了解决 BF 遗留下来的问题,当兄弟盒子上下或左右排列时产生的问题。
生成一个 BFC 规则盒子
- 根元素或包含根元素的元素
- 浮动元素(元素的 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 值不为 visible 的块元素
- display 值为 flow-root 的元素
- contain 值为 layout、content或 strict 的元素
- 弹性元素(display为 flex 或 inline-flex元素的直接子元素)
- 网格元素(display为 grid 或 inline-grid 元素的直接子元素)
- 多列容器(元素的 column-count 或 column-width 不为 auto,包括 column-count 为 1)
- column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中(标准变更,Chrome bug)。
此规则来源于:块格式化上下文 - Web开发者指南 | MDN;
我们无法记住这么多内容,当我们遇到上面的几个问题时,查看BFC文档,然后就可以解决。
解决:外边距塌陷
这里我们采用 overflow: hidden;
来解决这样的问题。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style type="text/css">
#green {
margin:10px 10px 10px 10px;
}
#blueBox {
overflow: hidden;
}
#blue {
margin:20px 10px 20px 10px;
}
#red {
margin:30px 10px 30px 10px;
}
</style>
</head>
<body>
<div id="green" style="background:lightgreen;height:100px;width:100px;"></div>
<div id="blueBox">
<div id="blue" style="background:lightblue;height:100px;width:100px;"></div>
</div>
<div id="red" style="background:pink;height:100px;width:100px;"></div>
</body>
</html>
第一步:我们给 #blue
盒子,添加了一个 #blueBox
的盒子包裹;
第二步:我们将 #blueBox
的盒子,使用overflow: hidden;
,触发BFC渲染。
第三步;解决外边距塌陷的问题。
解决:外边距塌陷.png解决:浮动子元素父元素的宽高丢失
这里我们采用 overflow: hidden;
来解决这样的问题。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style type="text/css">
#Container {
overflow: hidden;
}
#green {
margin:10px 10px 10px 10px;
float: left;
}
#blue {
margin:10px 10px 10px 10px;
float: left;
}
#red {
margin:10px 10px 10px 10px;
float: left;
}
</style>
</head>
<body>
<div id="Container">
<div id="green" style="background:lightgreen;height:100px;width:100px;"></div>
<div id="blue" style="background:lightblue;height:100px;width:100px;"></div>
<div id="red" style="background:pink;height:100px;width:100px;"></div>
</div>
</body>
</html>
第一步:我们将父元素 DIV#Container
设置为 overflow: hidden;
生成BFC的排列规则。
第二步:DIV#Container
就是一个拥有BFC规则的盒子。
解决:浮动元素与非浮动元素重叠
这里我们采用 overflow: hidden;
来解决这样的问题。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style type="text/css">
#Container {
width: 500px;
}
#green {
float: left;
}
#blue {
overflow: hidden;
}
</style>
</head>
<body>
<div id="Container">
<div id="green" style="background:lightgreen;height:100px; width:100px;"></div>
<div id="blue" style="background:lightblue; height:200px; width:200px;"></div>
</div>
</body>
</html>
我们设置 DIV#blue
元素为 overflow: hidden;
,它就成为了一个拥有BFC规则的盒子。
实战:利用BFC完成一份流式网格布局
我们经常会使用 boostrap
等网格系统;
在这里,我根据 skeleton.css
改编,简单完成一份这样的布局结构。
从而,是我们更加深刻地理解,BFC在实际场景中的应用。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>浮动的栅格化布局</title>
<link rel="stylesheet" href="./test.css">
</head>
<body>
<div class="Container">
<div class="row">
<div class="one column">ONE</div>
<div class="eleven columns">ELEVEN</div>
</div>
<div class="row">
<div class="two columns">TWO</div>
<div class="ten columns">TEN</div>
</div>
<div class="row">
<div class="three columns">THREE</div>
<div class="nine columns">NINE</div>
</div>
<div class="row">
<div class="four columns">FOUR</div>
<div class="eight columns">EIGHT</div>
</div>
<div class="row">
<div class="five columns">FIVE</div>
<div class="seven columns">SEVEN</div>
</div>
<div class="row">
<div class="six columns">SIX</div>
<div class="six columns">SIX</div>
</div>
<div class="row">
<div class="seven columns">SEVEN</div>
<div class="five columns">FIVE</div>
</div>
<div class="row">
<div class="eight columns">EIGHT</div>
<div class="four columns">FOUR</div>
</div>
<div class="row">
<div class="nine columns">NINE</div>
<div class="three columns">THREE</div>
</div>
<div class="row">
<div class="ten columns">TEN</div>
<div class="two columns">TWO</div>
</div>
<div class="row">
<div class="eleven columns">ELEVEN</div>
<div class="one column">ONE</div>
</div>
</div>
</body>
</html>
这是基本的页面结构,我们将整体划为12份,根 bootstrap.css
的思维一致。
body {
font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 12px;
}
.Container {
position: relative;
width: 100%;
margin: 0 auto;
padding: 0 20px;
box-sizing: border-box;
-moz-box-sizing: border-box;
overflow: hidden; /* 触发 BFC 规则,避免子元素浮动后的父元素失去宽和高 */
}
.row {
overflow: hidden; /* 触发 BFC 规则,避免子元素浮动后的父元素失去宽和高 */
}
.column,
.columns {
width: 100%;
float: left; /* 触发 BFC 规则 */
box-sizing: border-box;
font-weight: 400;
letter-spacing: .1rem;
margin-bottom: 1%;
background-color: #CCC;
height: 30px;
line-height: 30px;
text-align: center;
border-radius: 5px;
}
.column:first-child,
.columns:first-child {
margin-right: 4%;
}
.one.column,
.one.columns { width: 4.66666666667%; }
.two.columns { width: 13.3333333333%; }
.three.columns { width: 22%; }
.four.columns { width: 30.6666666667%; }
.five.columns { width: 39.3333333333%; }
.six.columns { width: 48%; }
.seven.columns { width: 56.6666666667%; }
.eight.columns { width: 65.3333333333%; }
.nine.columns { width: 74.0%; }
.ten.columns { width: 82.6666666667%; }
.eleven.columns { width: 91.3333333333%; }
.twelve.columns { width: 100%; margin-left: 0; }
.one-third.column { width: 30.6666666667%; }
.two-thirds.column { width: 65.3333333333%; }
浮动流式栅格布局.png
上文中,有多处应用到了BFC的影子,在这里,我就不过多阐述了。
网友评论