正常文档流和脱离文档流
正常文档流
文档流:元素在页面中出现的先后顺序。正常文档流:普通(文档)流,将页面从上到下分成一行一行的,其中块元素独占一行,相邻行内元素在每一行中按照从左到右排列,直到该行排满的布局情况,即默认情况下页面元素的布局情况。
<body>
<div></div>
<span></span><span></span>
<p></p>
<span></span><i></i>
<img />
<hr />
</body>
脱离文档流
脱离正常文档流,使用浮动或是定位。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style type="text/css">
/*定义父元素样式*/
#father {
width: 500px;
background-color: #0C6A9D;
border: 1px solid silver;
}
/*定义子元素样式*/
#father div {
padding: 20px;
margin: 15px;
border: 2px dashed red;
background-color: #FCD568;
text-align: center;
}
</style>
</head>
<body>
<div id="father">
<div id="son1">box1</div>
<div id="son2">box2</div>
<div id="son3">box3</div>
</div>
</body>
</html>
上面定义了 3 个 div 元素。对于这个 HTML 来说,正常文档流,指的就是从上到下依次显示这 3 个 div 元素。由于 div 是块元素,因此每个 div 元素独占一行。
设置浮动
#son3,#son2
{
float: left;
}
在正常文档流的情况下,div 是块元素,会独占一行。但是由于设置了浮动,第 2 个、第 3 个 div 元素并列一行,并且跑到父元素之外,跟正常文档流不一样。也就是说,设置浮动使得元素脱离了正常文档流。
设置定位
#son3
{
position: absolute;
left: 400px;
top: 50px;
}
由于设置了定位,第 3 个 div 元素就跑到父元素的上面去了。也就是说,设置了定位使得元素 脱离了正常文档流。
深入浮动
正常文档流情况下,块元素都是一行一行的,如果把多个块元素并排到一行,可以使用浮动将块元素脱离正常文档流来实现。
浮动使得元素移动到左边或者右边,并且允许后边的文字或元素环绕它,常用于实现水平方向上的并排布局,而不是垂直方向的布局。
两个重要特点
首先,当元素定义为 float 之后,不管之前是什么类型,都会变成 block 类型, 也就是说,浮动元素会表现为块元素效果,然后可以定义 width、height、padding 和 margin。使用 margin-left/right 来定义浮动元素与其他元素之间的间距。
其次,当一个元素定义了 float 时,这个元素就会脱离文档流,后面元素会紧跟着填上空缺的位置。
浮动的影响
对自身的影响
元素设置为 float 之后成为块元素,可以设置宽高,padding,margin。
对父元素的影响
已知元素设置浮动之后就会脱离正常文档流,如果浮动元素的 height 大于父元素的高度 height,或者父元素没有定义高度,此时父元素不能把子元素包起来,浮动元素就会脱离父元素,这就是所谓的“父元素高度塌陷”。
对兄弟元素的影响
兄弟元素是浮动元素
这里要注意两点,首先是兄弟元素的浮动效果,另外就是父元素的宽高。
同一方向的兄弟元素
当一个浮动元素碰到同一个方向的兄弟元素时,这些元素会从左到右,从上到下,一个接一个紧挨着排列。排列方式与父元素的宽高有关。
相反方向的兄弟元素
两个元素移向两边。
兄弟元素不是浮动元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style type="text/css">
div {
width: 600px;
height: 300px;
border: 1px solid black;
background-color: antiquewhite;
float: left;
margin: 50px;
}
span
{
float: none;
width: 200px;
height: 200px;
border: 1px solid black;
margin: 10px;
text-align: center;
background-color: aquamarine;
}
#d1 {
float: left;
}
#d2
{
float: right;
}
</style>
</head>
<body>
<div>
<div id="d3">div no-float</div>
<span id="d1">span float-left</span>
<div id="d3">div no-float</div>
</div>
<div>
<span id="d1">span float-left</span>
<div id="d3">div no-float</div>
<span id="d1">span float-left</span>
</div>
<div>
<span id="d1">span float-left</span>
<div id="d3">div no-float</div>
<div id="d3">div no-float</div>
</div>
<div>
<span id="d1">span float-left</span>
<span id="d1">span float-left</span>
<div id="d3">div no-float</div>
</div>
</body>
</html>
浮动元素对原来的元素有着覆盖效果,可见其对布局的影响非常大,因此在实际开发时,使用了浮动之后要注意清除浮动。
对子元素的影响
当父元素没有定义 height,浮动元素会脱离父元 素,造成父元素高度塌陷。但是当父元素同时也是一个浮动元素的时候,这个父元素会自适应地包含该子元素。
浮动布局的副作用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style type="text/css">
#father {
width: 300px;
overflow: hidden; 隐藏溢出
border: 1px solid black;
background-color: lightskyblue;
}
#first,
#second {
width: 100px;
height: 50px;
border: 1px solid red;
}
#first {
float: left;
}
#second {
float: right;
}
</style>
</head>
<body>
<div id="father">
<div id="first"></div>
<div id="second"></div>
</div>
</body>
</html>
这里为父元素添加 overflow:hidden 清除浮动,使边框能够撑开。由上文可知,另一种方式是在父元素添加 flow:left,不过最终效果不同。
用法解释:https://www.jianshu.com/p/d07048762efa
清除浮动
清除浮动,其实就是清除元素被定义浮动之后带来的脱离文档流的影响。我们知道,浮动可以使元素移到左边或者右边,然后后面的文字或元素会环绕着这个浮动元素。如果我们不想浮动元素后面的元素环绕着它,希望后面的元素回归到正常文档流中去,这个时候我们可以清除浮动。
clear:both
在 CSS 中,我们可以使用 clear 属性来清除浮动。clear 属性取值有 3 种:left、right 和 both。一般情况下使用 clear:both 来清除所有浮动。clear 属性不是应用于浮动元素本身,而是应用于浮动元素后面的元素。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style type="text/css">
#father
{
width:300px;
border: 1px solid black;
}
#first,#second
{
width:100px;
height:50px;
border:1px solid red;
}
#first{float:left;}
#second{float:right;}
/*关键代码,清除浮动*/
.clear{clear:both;}
</style>
</head>
<body>
<div id="father">
<div id="first"></div>
<div id="second"></div>
<div class="clear"></div>
</div>
</body>
</html>
使用 clear:both 来清除浮动,往往会多添加一个 div 标签。这个 div 标签仅仅是为了清除浮动而添加的,没有任何其他意义。这种方法并不太好,因为它会增加多余的标签,还会破坏 HTML 代码的语义。如果页面要清除多次浮动,就会无缘无故添加很多多余的 div 标签。
overflow:hidden
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style type="text/css">
#father
{
overflow:hidden; /*关键代码,清除浮动*/
width:300px;
border:1px solid black;
}
#first,#second
{
width:100px;
height:50px;
border:1px solid red;
}
#first{float:left;}
#second{float:right;}
</style>
</head>
<body>
<div id="father">
<div id="first"></div>
<div id="second"></div>
</div>
</body>
</html>
注意 overflow:hidden 应用于浮动元素的父元素,而不是当前的浮动元素。
::after 元素
.clearfix{*zoom:1;}
.clearfix::after
{
clear:both;
content:"";
display:block;
height:0;
visibility:hidden;
}
对于使用 ::after 伪元素结合 clear:both 来清除浮动,推荐把这个样式定义成一个公共的 class,这个 class 一般取名为“.clearfix”然后对这个类进行全局引用,这样可以减少重复的 CSS 代码。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style type="text/css">
.clearfix::after {
clear: both;
content: "";
display: block;
height: 0;
visibility: hidden;
}
#father {
width: 300px;
border: 1px solid black;
}
#first,
#second {
width: 80px;
height: 40px;
border: 1px solid red;
}
#first {
float: left;
}
#second {
float: right;
}
</style>
</head>
<body>
<div id="father" class="clearfix">
<div id="first"></div>
<div id="second"></div>
</div>
</body>
</html>
使用 clear:both 清除浮动会增加多余的标签,使用 overflow:hidden 清除浮动会使超出父元素的部分被隐藏。使用 ::after 伪元素来清除浮动,则不会有这些缺点。