8.8 KiB
BFC的概念及案例
BFC的概念
BFC(Block formatting context)直译为“块级格式化上下文”。它是一个独立的渲染区域,只有Block-level box(块)参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。
BFC的布局规则
- 内部的Box会在垂直方向,一个接一个地放置。
- Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
- 每个元素的margin box的左边, 与包含块border box的左边相接触
- BFC的区域不会与float box重叠。
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。
- 计算BFC的高度时,浮动元素也参与计算,所以会清除浮动。
哪些元素或属性能触发BFC
- 根元素 html
- float属性不为none
- position为absolute或fixed
- display为inline-block, table-cell, table-caption, flex, inline-flex
- overflow不为visible
案例一:两栏布局
要求:左边固定宽度,右边宽度可变。
方式一:
思路:左边固定宽度,浮动;右边不设置宽度,设置margin-left空出左边的宽度。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.dv1 {
width: 200px;
height: 500px;
background-color: pink;
float: left;
}
.dv2 {
margin-left: 200px;
height: 500px;
background-color: peru;
}
</style>
</head>
<body>
<div class="dv1"></div>
<div class="dv2"></div>
</body>
</html>
方式二:
思路:BFC的区域不会与float box重叠。所以将右边设置为BFC区域。
这里是有 absolute 绝对定位。
body {
position: relative;
}
.dv1 {
width: 200px;
height: 500px;
background-color: pink;
float: left;
}
.dv2 {
height: 500px;
background-color: peru;
position: absolute;
left: 200px;
right: 0;
}
注意:右边一定要加 right:0;
方式三:
思路:使用 overflow不为visible 将右边设置为BFC区域。
.dv1 {
width: 200px;
height: 500px;
background-color: pink;
float: left;
}
.dv2 {
height: 500px;
background-color: peru;
overflow: hidden;
}
案例二:三栏布局
要求:左边固定宽度,右边固定宽度,中间宽度自适应。
方案一:
思路:使用两栏布局的方案一
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.dv1 {
width: 200px;
height: 500px;
background-color: pink;
float: left;
}
.dv2 {
height: 500px;
background-color: peru;
margin-left: 200px;
margin-right: 200px;
}
.dv3 {
width: 200px;
height: 500px;
background-color: pink;
float: right;
}
</style>
</head>
<body>
<div class="dv1"></div>
<div class="dv2"></div>
<div class="dv3"></div>
</body>
</html>
可以看到 dv3 掉了下来???
为什么呢?因为dv2是块级元素,单独占一行,所以dv3只能显示在下一行。
怎么办呢?我们将dv2和dv3的顺序调换一下,就好了:
<div class="dv1"></div>
<div class="dv3"></div>
<div class="dv2"></div>
方案二:
思路:使用两栏布局的方案二
body {
position: relative;
}
.dv1 {
width: 200px;
height: 500px;
background-color: pink;
float: left;
}
.dv2 {
height: 500px;
background-color: peru;
position: absolute;
left: 200px;
right: 200px;
}
.dv3 {
width: 200px;
height: 500px;
background-color: pink;
float: right;
}
方案三:
思路:使用两栏布局的方案三
.dv1 {
width: 200px;
height: 500px;
background-color: pink;
float: left;
}
.dv2 {
height: 500px;
background-color: peru;
overflow: hidden;
}
.dv3 {
width: 200px;
height: 500px;
background-color: pink;
float: right;
}
结果也是dv3 被挤了下来。调换dv2和dv3的顺序即可。
方案四:
思路:使用弹性布局
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
display: flex;
}
.dv1 {
width: 200px;
height: 500px;
background-color: pink;
}
.dv2 {
width: 100%;
height: 500px;
background-color: red;
flex: 1;
}
.dv3 {
width: 200px;
height: 500px;
background-color: pink;
}
</style>
</head>
<body>
<div class="dv1"></div>
<div class="dv2"></div>
<div class="dv3"></div>
</body>
</html>
案例三:解决父元素与子元素之间的margin-top问题
原文链接:https://www.cnblogs.com/ranyonsue/p/5461749.html
问题描述
父元素的盒子包含一个子元素盒子,给子元素盒子一个垂直外边距margin-top的时候,父元素盒子也会往下走margin-top的值,而子元素和父元素的边距则没有发生变化,如下图:
源代码:
<!DOCTYPE html>
<html lang="en">
<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>Document</title>
<style>
body,
html {
padding: 0;
margin: 0;
}
.parent {
width: 200px;
height: 200px;
background-color: #aaa;
}
.children {
width: 100px;
height: 100px;
background-color: yellow;
margin-top: 50px;
}
</style>
</head>
<body>
<div class="parent">
<div class="children"></div>
</div>
</body>
</html>
原文分析
官方介绍:
In this specification, the expression collapsing margins means that adjoining margins (no non-empty content, padding or border areas or clearance separate them) of two or more boxes (which may be next to one another or nested) combine to form a single margin.
所有毗邻的两个或更多盒元素的margin将会合并为一个margin共享之。
毗邻的定义为:同级或者嵌套的盒元素,并且它们之间没有非空内容、Padding或Border分隔。
这就是原因了。“嵌套”的盒元素也算“毗邻”,也会 Collapsing Margins。这个合并Margin其实很常见,就是文章段落元素<p/>
,并列很多个的时候,每一个都有上下1em的margin,但相邻的<p/>
之间只会显示1em的间隔而不是相加的2em。
解决办法
这个问题的避免方法很多,只要破坏它出现的条件就行。给 Outer Div 加上 padding/border,或者给 Outer Div / Inner Div 设置为 float/position:absolute(CSS2.1规定浮动元素和绝对定位元素不参与Margin折叠)。
1、修改父元素的高度,增加 padding-top 样式模拟(padding-top:1px;常用)
2、为父元素添加 overflow: hidden;样式即可(完美)
3、为父元素或者子元素声明浮动(float:left;可用)
4、为父元素添加 border-top(border-top: 1px solid transparent; 可用)
5、为父元素或者子元素声明绝对定位 。
案例四:清除浮动
来自笔记:CSS/03-链接伪类、背景、行高、盒子模型、浮动
清除浮动不是不用浮动,清除浮动产生的问题。
问题:当父盒子没有定义高度,嵌套的盒子浮动之后,下边的元素发生位置错误(占据父盒子的位置)。
方法一
**额外标签法:**在最后一个浮动元素后添加标签。
clear: left | right | both /*用的最多的是clear:both;*/
方法二
给浮动元素的父集元素使用overflow:hidden;
注意:如果有内容出了盒子,不能使用这个方法。
方法三(推荐使用)
伪元素清除浮动。
: after 相当于在当前盒子后加了一个盒子。
清除浮动总结:
- 给父元素高度,缺点:高度无法自适应
- 父元素加 overflow:hidden; 缺点:超出会被隐藏
- 父元素加定位,absolute/fixed,缺点:脱离文档流。
- 父元素加浮动,缺点:可能父元素的父元素继续塌陷
- 父元素加inline-block,缺点:行内块的缺点。
- 浮动元素的最后加一个额外标签,标签使用clear:both; 缺点:结果冗余
- 万能清除法,伪元素清除浮动。
content: ".";
display: block;
height: 0;
visibility: hidden;
clear:both;
overflow: hidden;