目录
关于浮动
通过 float 属性可以实现元素的浮动并指定浮动的方向,无论元素本身是否为块级元素,浮动的元素都会形成一个块框(类似行内块级元素的特性)。浮动元素脱离文档流
向左或向右移动,直到它的外边缘碰到其包含框或另一个浮动框的边框为止。由于元素脱离文档流之后不占据空间
,正常文档流中的其它块框表现得就像浮动框不存在一样,占据浮动框原来的空间,但是行内框会围绕浮动元素
,表现得像是给它留出了空间。
<style>
#Box {
width: 400px;
background-color: wheat;
}
#Box div {
margin: 10px;
color: seashell;
text-align: center;
}
#box1 {
width: 140px;
height: 140px;
line-height: 140px;
background-color: yellowgreen;
}
#box2 {
width: 200px;
height: 120px;
line-height: 120px;
background-color: blueviolet;
}
#box3 {
width: 100px;
height: 100px;
line-height: 100px;
background-color: chocolate;
}
</style>
<div id="Box">
<div id="box1">Box1</div>
<div id="box2">Box2</div>
<div id="box3">Box3</div>
</div>
上图是正常文档流中的元素框排列,来看看将 Box2 向右浮动后的效果
<style>
#box2 {
float: right;
}
</style>
Box2 脱离文档流(垂直上升)向右移动,直到右边缘碰到了包含框 Box 的右边框。Box1 不受任何影响,原本紧跟其后的 Box3 元素补上了 Box2 原来的位置。
如果让 Box1 向左浮动又会是什么效果呢?
<style>
#box1 {
float: left;
}
</style>
Box1 脱离文档流向左移动,直到左边缘碰到了包含框 Box 的左边框。 Box2 与 Box3 元素补上了 Box1 原来的位置,此时 Box1 在视觉上遮挡了 Box2 和 Box3。但是我们注意到 Box2 和 Box3 中的文字都没有被 Box1 覆盖,而是围绕着浮动元素 Box1。
如果让三个子元素都浮动又会是什么效果呢?
<style>
#Box {
border: 1px solid wheat;
}
#box1, #box2, #box3 {
float: left;
}
</style>
首先是 Box1 向左移动直到左边缘抵达 Box 的左边框;紧接着 Box2 脱离文档流向左移动,直到左边缘抵达同样是浮动元素的 Box1 的右边缘;接着 Box3 也要浮动了,但是 Box 的宽度不足以在同一行再放下 Box3 了,所以另起一行,Box3 向左移动,在遇到了 Box1 的右边缘时停下。而且此时父元素 Box 的高度为零,发生了高度塌陷。
浮动的影响
通过以上示例,我们发现浮动元素会影响自己以及其之后盒子的布局
,但不影响前面盒子的布局
,主要的影响有如下几点。
行盒围绕浮动元素
正常文档流中所有的行内元素以及行内块状元素都会围绕在浮动元素周围,就像是给浮动元素留出了空间,这也是浮动设计的初衷——实现文字环绕效果。
父元素高度塌陷
在正常文档流中,一个没有设置高度的父元素,它的高度是由子元素撑开的。但是如果它的子元素浮动了,子元素脱离文档流不占据空间,导致父元素无法自动获取高度,这个现象就是高度塌陷。高度塌陷的元素还有许多不正常显示比如:背景无法显示、边框不能撑开、margin 以及 padding 不正常显示等等。
遮挡同级兄弟盒子
浮动元素脱离文档流之后,紧随其后的处于正常文档流中的块级盒子会直接占据浮动元素本来的空间,这样导致浮动元素与之后的块级盒子重叠在一起,虽然行盒的内容不会被遮挡,但是我们在实际开发中有时候并希望这种情况发生。
清除浮动
因为浮动会带来一些我们并不希望出现的效果,我们常常需要清除浮动。清除浮动的本质是为了清除浮动元素给其他元素带来的影响
,并非清除元素本身的浮动效果,主要有以下几种方法。
父元素设置高度
我们知道了如果父级元素没有定义高度,父元素的高度完全由子元素撑开。那么我们可以为父元素手动定义height,就解决了父元素无法自动获取到高度的问题。
优点:简单、代码少
缺点:只适合高度固定的布局,要给出精确的高度,不适合做响应式布局
额外标签法 + clear 属性
在需要清除浮动的浮动元素之后加一个空的块级元素,并设置 clear 属性。clear 属性的作用是清除浮动对该元素的影响,也就是浮动元素脱离文档流而使未浮动元素上移,在页面中显示的效果就是浮动元素将未浮动元素遮住,清除浮动之后未浮动元素就会放置于浮动元素的下方。
<style>
#Box {
border: 1px solid wheat;
}
#box1 {
float: left;
}
.clearFloat {
clear: both;
}
</style>
<div id="Box">
<div id="box1">Box1</div>
<div class="clearFloat"></div>
<div id="box2">Box2</div>
<div id="box3">Box3</div>
</div>
// Box1 是浮动元素,未清除浮动时 Box2 会往上占据 Box1 原来的位置,导致 Box1 遮挡了 Box2
// 在 Box1 后面加了一个空元素设置 clear:both 之后,呈现出了正常文档流的布局
// 当然也可以直接给 Box2 设置 clear 属性不允许它两侧出现浮动元素
优点:简单、代码少、兼容性好、不会出现其它问题
缺点:如果多处浮动需要清除,这种方法可能会增加许多空标签
利用 BFC 避免高度塌陷
BFC 可以解决子元素浮动导致父元素高度塌陷的问题,因为在BFC的渲染规则中,浮动元素也参与高度计算,所以我们只需要激活父元素的 BFC 即可
<style>
#Box {
border: 1px solid wheat;
overflow: auto;
/* hidden 会隐藏溢出的文字,可以加上 word-wrap 属性让文字换行 */
/* overflow: hidden;
word-wrap: break-word; */
}
#box1, #box2, #box3 {
float: left;
}
</style>
<div id="Box">
<div id="box1">Box1</div>
<div id="box2">Box2</div>
<div id="box3">Box3</div>
</div>
// 激活 BFC 最简单的方法就是给父元素设置overflow: auto
优点:简单、代码少、兼容性好
缺点:激活BFC有多种方法,overflow: auto/hidden会出现滚动条或者文字被裁剪的情况;也可以给父元素设置浮动,但这样会产生新的浮动问题;利用 display: table 属性,将父元素变成表格,表格不受浮动影响,但也可能出现别的问题
伪元素 after 与 before + clear 属性
利用伪元素清除浮动是使用最广泛的方法,原理与额外标签法一样,都是利用 clear 属性清除浮动,但是伪元素不会添加额外的标签,不会影响文档结构且兼容性很好。
::after 伪元素是在元素的末尾添加一个子元素,::before 伪元素是在元素的开头添加一个子元素(添加的元素并不真实存在于DOM中)
<style>
.clearFloat::after {
clear: both;
/* 伪元素中content属性必须设置,指定要插入的内容 */
content: "";
/* display必须是 block/flex/grid/table等块级元素 */
display: block;
visibility: hidden;
height: 0;
}
.clearFloat {
/* 设置或检索对象的缩放比例,触发IE浏览器的haslayout属性 */
zoom: 1;
}
#box1, #box2, #box3 {
float: left;
}
</style>
<div id="Box" class="clearFloat">
<div id="box1">Box1</div>
<div id="box2">Box2</div>
<div id="box3">Box3</div>
</div>
优点:兼容性好、不会影响文档结构
缺点:代码多
haslayout 是 IE7- 浏览器的特有属性。hasLayout 是一种只读属性,有两种状态:true 或 false。当其为 true 时,代表该元素有自己的布局,否则代表该元素的布局继承于父元素。
可以触发 hasLayout 的有如下CSS属性:
- display: inline-block
- height/width: 除了auto
- float: left/right
- position: absolute
- writing-mode(IE专有属性,设置文本的垂直显示):tb-rl
- zoom(IE专有属性,设置或检索对象的缩放比例): 除了normal
IE7专有的触发 hasLayout 的CSS属性:
- min-height/max-height/min-width/max-width: 除none
- overflow\overflow-x\overflow-y: 除visible
- position: fixed
总结
从上面的例子来看,清除浮动总的来说就是两种方法,一个是激活父元素的 BFC,让浮动的子元素参与高度计算,另一个方法就是利用 clear 属性,不允许元素两侧出现浮动元素,这样来清除浮动元素对该元素的影响