CSS布局总结--BFC
小知识点(暖场):
overflow
属性:规定当内容溢出元素框时发生的事情。
-
visible
:默认值,内容不会被裁减,但是会显示在元素框外 -
hidden
:内容会被裁减,其他的内容是不可见的 -
scroll
:内容会被裁减,但是浏览器可以显示滚动条来显示余下的内容 -
auto
:如果内容被裁减,浏览器会显示滚动条来方便查看余下的内容 -
inherit
:规定应该从父元素继承overflow
属性的值
display
属性:规定元素应该生成框的类型
-
none
:此元素不会被显示 -
block
:此元素显示为块级元素,元素后面默认有换行符 -
inline
:默认。此元素会被显示为行内元素,元素后默认 -
list-item
:此元素作为列表显示 -
run-in
:此元素会根据上下文作为块级元素或是行内元素显示 -
compact
:css
值中有compact
,不过由于缺乏广泛支持,已删除 -
marker
:css
值中有marker
,不过由于缺乏广泛支持,已删除 -
table
:此元素会作为块级表格来显示,表格的前后会带有换行符,类似<table>
-inline-table
:此元素会作为内联表格显示,表格前后没有换行符,类似<table>
-
table-row-group
:此元素会作为一个或是多个分组来显示,类似<tbody>
-
table-header-group
: 此元素会作为一个或多个行的分组来显示,类似<thead>
-
table-footer-group
:此元素会作为一个或多个行的分组来显,类似<tfoot>
-
table-row
:此元素会作为一个表格行显示,类似<tr>
-
table-column-group
:此元素会作为一个或多个列的分组来显,类似<colgroup>
-
table-column
:此元素会作为一个单元格列显示,类似<col>
-
table-cell
:此元素会作为一个表格单元格显示,类似<td>
和<th>
-
table-caption
:此元素会作为一个表格标题显示,类似<caption>
-
inherit
:规定应该从父元素继承display
属性的值。
position
属性:属性规定元素的定位类型
-
absolute
:生成绝对定位,相对于static定位以外的第一个父元素进行定位,元素位置通过left、right、top、bottom属性进行规定 -
fixed
:生成绝对定位的元素,相对浏览器的窗口进行定位,元素位置通过left
、right
、top
、bottom
属性进行规定 -
relative
:生成相对定位的元素,相对于其正常位置进行定位,因此left:20
会向元素的左边添加20像素
-
static
:默认值,没有定位,元素出现在正常流中(忽略top
等属性) -
inherit
:规定从父级继承的position
的位置
BFC简介
BFC
:块级格式化上下文,它是指一个独立的块级渲染区域,只有Block-level
盒子参与,该区域拥有一套渲染规则来约束块级盒子的布局,且与区域外部无关。
BFC的生成
对于HTML
文件来说,只要满足下面CSS
声明中的一个就会产生BFC
- 为根元素
-
float
的值不为none
-
overflow
值不为visible
-
display
的值为inline-block
、table-cell
、table-caption
-
position
的值为fixed
、absolute
创建BFC的约束
- 生成
BFC
元素的子元素会一个接一个的进行放置。垂直方向上他们的奇点是一个包含块的顶部,两个相邻子元素之间的垂直距离取决于margin
特性,在BFC
中相邻的块级元素的外边距会重叠 - 生成
BFC
元素的子元素中,每一个子元素做外边距与包含块的左边界相接触,即使是浮动元素也是如此,除非这个子元素也创建一个新的BFC
详细描述:
- 内部的盒子会在垂直的方向上一个接一个的放置。
- 垂直方向上距离由
margin
决定(属于同一个BFC
的两个相邻的box
的margin
会发生重叠,与方向无关) - 每个元素的左边框与包含块的左边界接触(布局为从左到右),浮动元素也是这样的,也就是说
BFC
中元素不会超出他的包含块,而position
为absolute
布局的元素可以超出包含块边界。 -
BFC
的区域不会和float
元素区域重合 - 计算
BFC
高度的时候,浮动子元素也要参与到计算中 -
BFC
就是页面上面的隔离的独立容器,容器中的子元素不会影响到外面的元素,同时外面的元素也不会影响容器里面的元素。
BFC的应用
放置margin的重叠
在同一个BFC
中,两个相邻的Box
才会发生重叠与方向没有关系,我们很少可以看到在水平方向的margin
的重叠,但是在IE
浏览器中,可以设置write-mode
来实现水平方向的布局。
#green{
margin:10px 10px 10px 10px;
background:lightgreen;
height:100px;
width:100px;
}
#blue{
margin:10px 10px 10px 10px;
background:lightblue;
height:100px;
width:100px;
}
#red{
margin:10px 10px 10px 10px;
background:pink;
height:100px;
width:100px;
}
body {
writing-mode:tb-rl;
}
<body>
<div id="green"></div>
<div id="blue"></div>
<div id="red"></div>
</body>
现在两个盒子之间的margin
值是10px
而不是我们想象中的20px
。

如果我们希望阻止margin
重叠的出现,就要将2个元素分别放在一个BFC
中即可,但是在在上面的情景中阻止重叠看上去没有什么意义,我们主要将其用在嵌套。
html, body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
.first{
margin:20px;
background:lightgreen;
width:100px;
height:100px;
}
ul{
margin:10px;
background:lightblue;
}
li{
margin:25px;
}
<div class="first"></div>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>

我们发现上面的黄框区域的为25px
,也就是说将ul的margin的值覆盖掉了,此时div与ul之间的垂直距离,取div
、ul
、li
三者之间的最大外边距。。我们如果要阻止元素的重叠,就要让url
生成BFC
即可
html, body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
.first{
margin:20px;
background:lightgreen;
width:100px;
height:100px;
}
ul{
display: inline-block;
margin:10px;
background:lightblue;
}
li{
margin:25px;
}
html, body { height: 100%; width: 100%; margin: 0; padding: 0; }
.first{
margin:20px;
background:lightgreen;
border: 2px solid lightgreen;
}
ul{
overflow:hidden;
margin:10px;
background:lightblue;
width:100px;
height:200px;
float: left;
}
li{
margin:25px;
}

ps:如果为ul设置了border或padding,那元素的margin便会被包含在父元素的盒式模型内,不会与外部div重叠。
浮动问题
我们的父元素包含子元素,常见的方式是为父元素设置overflow:hidden
或是浮动父级元素,根本原因在于创建BFC
元素,子浮动元素也参与了高度的计算,就不会产生高度塌陷的问题,实际上只要让父级元素生成BFC
就可以。也就是说浮动元素是会脱离文档流的(绝对定位元素会脱离文档流)。如果一个没有高度或者height
是auto
的容器的子元素是浮动元素,则该容器的高度是不会被撑开的。
所以我们解决的代码是
html, body { height: 100%; width: 100%; margin: 0; padding: 0; }
.first{
margin:20px;
background:lightgreen;
border: 2px solid lightgreen;
/*这四条代码都可以解决上面的问题*/
display:inline-block;
overflow:hidden;
float: left;
position:absolute;
}
ul{
overflow:hidden;
margin:10px;
background:lightblue;
width:100px;
height:200px;
float: left;
}
li{
margin:25px;
}
多栏布局的实现
我们在上面已经总结了一条规律:与浮动元素相邻的已生成的BFC
的元素不能和浮动元素之间相互覆盖,所以我们利用这个特性作为多栏布局的一种实现方式。
html, body { height: 100%; width: 100%; margin: 0; padding: 0; }
.left{
background:pink;
float: left;
width:180px;
}
.center{
background:lightyellow;
overflow:hidden;
}
.right{
background: lightblue;
width:180px;
float:right;
}
<div class="container">
<div class="left">
<pre>
.left{
background:pink;
float: left;
width:180px;
}
</pre>
</div>
<div class="right">
<pre>
.right{
background:lightblue;
width:180px;
float:right;
}
</pre>
</div>
<div class="center">
<pre>
.center{
background:lightyellow;
overflow:hidden;
height:116px;
}
</pre>
</div>
</div>

这种布局的特点在于左右两栏宽度固定,中间栏可以根据浏览器宽度自适应。