先说说FC,FC的含义就是Fomatting Context。它是CSS2.1规范中的一个概念。它是页面中的一块渲染 区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。BFC和IFC 都是常见的FC。分别叫做Block Fomatting Context 和Inline Formatting Context。
BFC
BFC(Block Formatting Context)叫做“块级格式化上下文”
BFC的布局规则如下:
1.内部的盒子会在垂直方向,一个个地放置;
2.盒子垂直方向的距离由margin决定,属于同一个BFC的两个相邻Box的上下margin会发生重叠;
3.每个元素的左边,与包含的盒子的左边相接触,即使存在浮动也是如此;
4.BFC的区域不会与float重叠;
5.BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之也如此;
6.计算BFC的高度时,浮动元素也参与计算。
哪些元素会产生BFC:
1.float的属性不为none;
2.position为absolute或fixed;
3.display为inline-block,table-cell,table-caption,flex
;
4.overflow不为visible
BFC的作用:
1.解决margin重叠的问题(添加独立BFC),块级标签之间竖直方向的margin会以大的为准
2.解决浮动高度塌陷的问题(在父级添加overflow:hidden)
首先我们写个demo:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BFC</title>
<style>
.left {
width: 100px;
height: 100px;
background-color: #000;
}
.right {
width: 300px;
height: 300px;
background-color: #f00;
}
</style>
</head>
<body>
<div class="left"></div>
<div class="right"></div>
</body>
</html>
开始的页面:
我们在left盒子加上浮动后:float: left
这正满足了规范的第三条:
每个元素的左边,与包含的盒子的左边相接触,即使存在浮动也是如此。
所以如果我们需要将黑色区域撑到红色的左边,就需要利用规范的第四条:
BFC的区域不会与float重叠。
也就是说我们需要创造BFC区域。我们通过将红色区域即right盒子加上overflow: hidden
来触发BFC:
此时效果图:
这样我们也能够实现了两个块级元素横排的效果了。当我们不给right盒子宽度时,它自动会占据剩余宽度,我们也能实现二栏布局,左侧固定,右侧自适应的效果。
当然三栏布局也是可以实现的,左右定宽,中间内容自适应;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BFC之三栏布局</title>
<style>
body {
font-size: 25px;
}
.left,
.right {
width: 150px;
height: 150px;
}
.left {
background-color: #0f0;
float: left;
}
.center {
background-color: #0ff;
overflow: hidden;
}
.right {
float: right;
background-color: #ff0;
}
</style>
</head>
<body>
<div class="left">左侧固定</div>
<div class="right">右侧固定</div>
<div class="center">中间自适应</div>
</body>
</html>
虽然浮动也能帮我们实现三栏布局,但当我们加上很长很长的文字时,并且没有触发BFC(overflow: hidden;
)时,效果是:
触发BFC时:
再看一个demo:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BFC</title>
<style>
.fa {
width: 300px;
border: 1px solid #f00;
}
.son {
float: left;
width: 100px;
height: 200px;
background-color: #0f0;
}
</style>
</head>
<body>
<div class="fa">
<div class="son"></div>
</div>
</body>
</html>
看初效果:
可以看到,父div压根就没有被撑开
我们再回顾一下BFC规范中的第六条:
计算BFC的高度时,浮动元素也参与计算。
所以我们需要将父div触发为BFC,也就是将其overflow: hidden
:
.fa {
width: 300px;
border: 1px solid #f00;
overflow: hidden;
}
效果图为:
我们可以看到父盒子被成功撑开了
继续,不要停,再看一个不嫌多:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BFC</title>
<style>
.container {
width: 400px;
height: 350px;
background-color: pink;
}
.one,
.two {
width: 200px;
height: 50px;
margin: 50px 0;
}
.one {
background-color: #ff0;
}
.two {
background-color: #0f0;
}
</style>
</head>
<body>
<div class="container">
<div class="one"></div>
<div class="two"></div>
</div>
</body>
</html>
效果图:
为什么?我不是设了两个盒子的上下外边距都为50px吗,为什么还会影响父盒子的位置呢?为什么盒子之间的距离显示是50px而不是100px呢?
我们再看看BFC规范的第二条:
盒子垂直方向的距离由margin决定,属于用一个BFC的两个相邻Box的上下margin会发生重叠。
说明两者属于同一个BFC,所以我们需要两个div不属于同一个BFC。
为第一、二个div都套一个父亲div,然后将其overflow: hidden
来激活一个BFC就可以使margin不再重叠。
<div class="container">
<div class="wrap">
<div class="one"></div>
</div>
<div class="wrap">
<div class="two"></div>
</div>
</div>
.wrap {
overflow: hidden;
}
效果如图:
IFC
IFC(Inline Formatting Contexts)意为“内联格式化上下文”,IFC中,盒子依次水平放置,从包含块的顶部开始。一般都是行内元素比如:input a img span 以及display 属性值为inline-block的元素。
形成IFC的条件:
1.font-size
2.line-height
3.height
4.vertical-align
而行内元素有哪些特点呢?如下列举:
1.水平方向根据direction依次布局。
2.不会在元素前后换行。
3.受white-space属性的影响。
4.margin/padding 在竖直方向无效,水平方向有效的。
5.width/height 对非替换行内元素无效,宽度由元素内容决定。
6.非替换行内元素的行框高由line-height决定而替换行内元素的行框高则是由height,padding,border,margin决定
7.浮动或者绝对定位会转化为block
8.vertical-align属性生效
例如:img、input属于行内替换元素。height/width/padding/margin均可用。效果等于块元素。
a、span等属于非替换行内元素。
IFC布局规则:
1.框会从包含块的顶部开始,一个接一个地水平摆放。
2.摆放这些框的时候,它们在水平方向上的外边距、边框、内边距所占用的空间都会被考虑在内。在垂直方向 上,这些框可能会以不同形式来对齐:它们可能会把底部或顶部对齐,也可能把其内部的文本基线对齐。能把在一行上的框都完全包含进去的一个矩形区域,被称为该行的行框
。水平的margin、padding、border有效,垂直无效。不能指定宽高。
3.行框的宽度是由包含块和存在的浮动来决定,行框的高度至少会高到足以包含他内部的所有框。
4.行框的宽度容纳不下子元素时,子元素会换下一行显示,并且会产生新行框,但是如果设置这个框就不能被分割的话(比如,文字强制不给换行white-space: nowrap
)那么这时候该行内框就会溢出该行的行宽。
5.行框的元素内遵循text-align和vertical-align
容器的高度 height = line-height + vertical-align
当然同理,如果容器的高度被指定了,那么高度则不变,而超出的部分则不影响布局。如果设置 overflow:hidden
,超过的部分则不可见