深入理解float的设计初衷以及float带来的影响

float定义

A floated box is shifted to the left or right until its outer edge touches the containing block edge or the outer edge of another float. If there is a line box, the outer top of the floated box is aligned with the top of the current line box.【出处https://www.w3.org/TR/CSS2/visuren.html#floats

  • 1.浮动的框可以向左或向右移动,直到它的外边缘碰到包含框或另一个浮动框的边框为止。

Since a float is not in the flow, non-positioned block boxes created before and after the float box flow vertically as if the float did not exist.

However, the current and subsequent line boxes created next to the float are shortened as necessary to make room for the margin box of the float.

补充介绍: w3.org/css2/position schemes

CSS有三种基本的定位机制:普通流,浮动(float)和绝对定位(position)

浮动布局是CSS中规定的第二种定位机制。

普通流:正常的文档流,指的是元素排版布局过程中,元素会自动从左往右,从上往下的流式排列; 也即块元素(block)独占一行,内联元素(inline),不独占一行。

https://www.w3.org/TR/CSS21/visuren.html#normal-flow

脱离文档流,也就是将元素从普通的布局排版中拿走,其他盒子在定位的时候,会当做脱离文档流的元素不存在而进行定位。

怎样使元素脱离文档流?

脱离文档流的方式有两种: 浮动和定位 。

有3种方法让元素脱离文档流。

  • 1.position: absoulte;
  • 2.position: fixed;
  • 3.float: left 或者 float: right。

批注: position: static、relative不会使元素脱离文档流。

float和绝对定位的脱离文档流是有区别的。

1.完全脱离文档流

脱离后完全不占空间。

absolute和fixed定位是完全脱离文档流。

使用absolute position脱离文档流的元素,其他盒子与其他盒子内的文本都会无视它。(可以说是完全无视)

2.不彻底的脱离

float虽然脱离了文档流,但是他是不彻底的脱离,他脱离了文档流还存在网页流中。

使用float脱离文档流时,其他盒子会无视这个元素,但其他盒子内的文本依然会为这个元素让出位置,环绕在周围。(可以说是部分无视)

float属性值

/常用3个属性值:/

float: left;
float: right;
float: none;

/* Global values */

float: inherit;
float: initial;
float: unset;

移动到父元素最左和最右是指元素往左或往右移动直到碰到另一个浮动元素或父元素内容区的边界(不包括padding),none是默认的意思是不浮动,inherit是继承父级元素的float值。

float最初的设计初衷

浮动出现的意义,是为了实现图文混排效果,让文字环绕图片,仅此而已。

如今的用法基本上都是为了实现横向排版,虽然是一种“误用”,却往往能达到我们想要的效果。

demo- img & words

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>test</title>
</head>
<style>
.wrap{
	width: 600px;
	padding: 20px;
	margin: 16px auto; 
	line-height: 1.5; 
	font-size: 14px;
	background: #eee;
}
img{
	width: 150px;
	height: 200px;
	float: left;
	margin: 0 10px 5px 0; 
}
</style>
<body>
	<div class="wrap">
		<img src="zly.jpg" alt="">
		<p>赵丽颖,1987年10月16日出生于河北省廊坊市,中国内地影视女演员。</p>

		<p>2006年,因获得雅虎搜星比赛冯小刚组冠军而进入演艺圈;同年,在冯小刚执导的广告片《跪族篇》中担任女主角。2007年,参演个人首部电影《镖行天下之牡丹阁》。2011年,因在古装剧《新还珠格格》中饰演晴儿一角而被观众所认识。2013年,凭借古装剧《陆贞传奇》获得更多的关注。2014年10月,在第10届金鹰电视艺术节举办的投票活动中被选为“金鹰女神”;12月,凭借都市爱情剧《杉杉来了》获得第5届国剧盛典内地最具人气女演员奖。</p>

		<p>2015年,主演的仙侠剧《花千骨》成为中国首部网络播放总量突破200亿的电视剧,并打破中国内地周播剧收视纪录,而其个人则凭借该剧先后获得第6届澳门国际电视节金莲花最佳女主角奖、第6届国剧盛典最具收视号召力演员奖、第22届上海电视节白玉兰奖最佳女主角奖提名、第28届中国电视金鹰奖观众喜爱的女演员奖 。2016年,主演古装玄幻剧《青云志》;同年,担任河北省旅游形象大使。</p>
	</div>
</body>
</html>

result display

float实现图文混排效果原理

浮动的破坏性。
文字之所以会环绕含有float属性的图片时因为浮动破坏了正常的line boxes。
具体如何破坏,待添加。。。

float造成的影响

float对自身元素的影响

包裹性-wrap

块级元素如果不设置float,它默认会撑满整个屏幕,而如果设置了float,则只会包裹住其内容。

demo- float-wrap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>test</title>
</head>
<style>
.box1{
	float: left;
	border: 1px solid #f93;
}
</style>
<body>
	<div class="box1">测试float对块级元素形成的包裹性</div>
</body>
</html>

result display

隐式block化

float对象将被视作块对象(block-level),即display属性等于block。

demo- float-display:block

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>test</title>
</head>
<style>

</style>
<body>

<input type="button" id="btn1" value="btn1未设置浮动">
<input type="button" id="btn2" value="btn2未设置浮动">

<input type="button" id="mybtn" value="获取上述按钮position">
<input type="button" id="btn" value="我来设置btn1浮动">
<script>
	window.onload = function(){
		var btn1 = document.getElementById("btn1");
		var btn2 = document.getElementById("btn2");
		var mybtn = document.getElementById("mybtn");
		var btn = document.getElementById("btn");

		function getDisplay(ele){
			var display = ele.currentStyle ? ele.currentStyle.display : window.getComputedStyle(ele,null).display;
			return display;
		}

		btn.onclick = function(){
			
			btn1.style[this.style.styleFloat ? "styleFloat" : "cssFloat"] = "left";
			btn1.value = "btn1被浮动了";
		}

		mybtn.onclick = function(){
			console.log("btn1的display:" + getDisplay(btn1));
			console.log("btn2的display:" + getDisplay(btn2));
		}
	}
</script>
</body>
</html>

result display

可以看出按钮btn1被float后position属性值由原来的inline-block变成block了。

float对父元素的影响

也即是浮动的破坏性

float的破坏性是指:设置了float的元素会脱离文档流,会导致其父元素出现“坍塌”的现象,不错,这就是它的破坏性。

为什么会出现父元素坍塌的现象呢?原因很简单,因为float的设计初衷就是为了实现文字环绕效果,如果父元素不坍塌,那如何实现环绕效果呢?

domo- float - noheight

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>test</title>
</head>
<style>
*{
	margin:0;
	padding: 0;
}
.wrap{
	padding: 10px;
	border: 10px solid #f93;
}
.test{
	float: left;
	margin-left: 10px;
	background: #9f3;
}
</style>
<body>
	<div class="wrap">
		<p class="test">我来测试浮动带来的破坏性</p>
	</div>
</body>
</html>

result display

float对其兄弟元素的影响

float对其兄弟元素(非浮动)的影响

如果兄弟元素为块级block元素

在现代浏览器和IE8+下,该元素会忽视浮动元素的而占据它的位置,并且元素会处在浮动元素的下层(并且无法通过z-index属性改变他们的层叠位置),但它的内部文字和其他行内元素都会环绕浮动元素。

demo- float

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>test</title>
</head>
<style>
.wrap{
	padding: 10px;
	border: 1px solid #f00;
}
.box1{
	float: left;
	background: #9f3;
}
.box2{
	width: 150px;
	height: 60px;
	background: #39f;
}
</style>
<body>
	<div class="wrap">
		<div class="box1">AAAAAAA</div>
		<div class="box2">BBBBBBB</div>
	</div>
</body>
</html>

result display

需要注意的是,在IE 6、7下则分别都有不同的表现,IE 6、7中,该兄弟元素会紧跟在浮动元素的右侧,并且在IE6中两者之间留有3px的空隙。这就是著名的“IE 3px bug”

如果兄弟元素为内联inline元素

则元素会环绕浮动元素排列。

demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>test</title>
</head>
<style>
.wrap{
	padding: 10px;
	border: 1px solid #f00;
}
.box1{
	float: left;
	background: #9f3;
}
</style>
<body>
	<div class="wrap">
		<div class="box1">AAAAAAA</div>
		<input type="button" value="我的表现如何">
	</div>
</body>
</html>

result display

float对其兄弟元素(浮动)的影响

float还有一个很有用的特性,就是清除空格。

破坏性造成的紧密排列性(去空格化)。

demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>test</title>
</head>
<style>
*{
	margin: 0;
	padding: 0;
}
.wrap{
	border: 1px solid #f00;
}
.wrap input{
	float: left;
}
</style>
<body>
<p>inline元素之间换行产生的空格</p>
	<div class="demo">
		<input type="button" value="btn1">
		<input type="button" value="btn2">
		<input type="button" value="btn3">
		<input type="button" value="btn4">
		<span>hello</span>
	</div>
	<br>
<p>inline元素float能去掉它们之间的空格,所有换行符移到最后一个btn后面</p>
	<div class="wrap">
		<input type="button" value="btn1">
		<input type="button" value="btn2">
		<input type="button" value="btn3">
		<input type="button" value="btn4">
		<span>hello</span>
	</div>
	<br>
	<p>nbsp产生的空格</p>
	<div class="demo">
		<input type="button" value="btn1">&nbsp;<input type="button" value="btn2">&nbsp;<input type="button" value="btn3">&nbsp;<input type="button" value="btn4"><span>hello</span>
	</div>
	<br>
	<p>float将所有nbsp产生的空格移到最后一个btn后面</p>
	<div class="wrap">
		<input type="button" value="btn1">&nbsp;<input type="button" value="btn2">&nbsp;<input type="button" value="btn3">&nbsp;<input type="button" value="btn4"><span>hello</span>
	</div>
</body>
</html>

result display

1.元素float后,会去掉inline元素之间enter键产生的空格,但由于enter键对网页表现不会产生任何影响,所以即使btn4后面有enter键产生的空格,也是无法影响后面span元素的表现;
2.元素float后,也会去掉nbsp产生的空格,由于nbsp本身也是文本,所以所有nbsp挪位到btn4后面,产生3个nbsp;挤压span元素到后面去了。

float对子元素的影响

我们知道当一个元素浮动时,在没有清楚浮动的情况下,它无法撑开其父元素,但它设置float后,可以让自己的浮动子元素撑开它自身,并且在没有定义具体宽度情况下,使自身的宽度从100%变为自适应(浮动元素display:block)。其高度和宽度均为浮动元素高度和非浮动元素高度之间的最大值。

demo- 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>test</title>
</head>
<style>
.wrap{
	border: 1px solid #f00;
}
.main{
	float: left;
	border: 5px solid #9f3;
}
.box3{
	background: yellow;
}
</style>
<body>
	<div class="wrap">
		<div class="main">
			<div class="box1" id="box1">11111</div>
			<span class="box2" id="box2">22222</span>
			<div class="box3">33</div>
		</div>
	</div>
</body>
</html>

result display

当子元素(block)不float时,子元素且没有设置float,可以把子元素由原来的块状(width占据100%)包裹起来,其高度和宽度均为浮动元素高度和非浮动元素高度之间的最大值。

demo- 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>test</title>
</head>
<style>
.wrap{
	border: 1px solid #f00;
}
.main{
	float: left;
	border: 5px solid #9f3;
}
.box1,.box2{
	float: left;
	border: 1px solid blue;
	background: #f60;
}
.box3{
	float: left;
	width: 40px;
	height: 40px;
	background: yellow;
}
</style>
<body>
	<div class="wrap">
		<div class="main">
			<div class="box1" id="box1">11111</div>
			<span class="box2" id="box2">22222</span>
			<div class="box3">33</div>
		</div>
	</div>
</body>
</html>

result display

当它的子元素都浮动时,它能浮动自身,撑起高度,避免塌陷。

float对父元素之外的元素的影响

父元素之外的非浮动元素-float

从上面可知,当一个元素浮动时,在没有清除浮动的情况下,它无法撑开其父元素,也就是父元素的宽高都为0。并且其父元素之外的非浮动元素也会无视该浮动元素,浮动元素仿佛到了另外一个世界里。

demo- 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>test</title>
</head>
<style>
.wrap{
	border: 2px solid black;
}
.main{
	float: left;
	border: 5px solid #9f3;
}
.outer{
	background: #93f;
}
</style>
<body>
	<div class="wrap">
		<div class="main">aaaaaa</div>
	</div>
	<div class="outer">bbbbb</div>
</body>
</html>

result display

float对父元素之外的浮动元素

当浮动元素的父元素之外的元素为浮动元素时,他们仿佛去到了同一个世界里。

两个元素的浮动方向相同时:

demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>test</title>
</head>
<style>
.wrap{
	border: 2px solid black;
}
.main{
	float: left;
	width: 100px;
	height: 100px;
	background: #9f3;
}
.outer{
	float: left;
	width: 100px;
	height: 120px;
	background: #93f;
}
</style>
<body>
	<div class="wrap">
		<div class="main">aaaaaa</div>
	</div>
	<div class="outer">bbbbb</div>
</body>
</html>

result display

两个元素的浮动方向相反时:

demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>test</title>
</head>
<style>
.wrap{
	width: 300px;
	border: 2px solid black;
}
.main{
	float: left;
	width: 100px;
	height: 100px;
	background: #9f3;
}
.outer{
	float: right;
	width: 100px;
	height: 120px;
	background: #93f;
}
</style>
<body>
	<div class="wrap">
		<div class="main">aaaaaa</div>
	</div>
	<div class="outer">bbbbb</div>
</body>
</html>

result display

float与JavaScript

原因是在JavaScript中”float”是一个保留字,不能使用element.style.float="left";这样的句子 来改变CSS的float属性。 因为同样的原因,”class”被改成了”className” 、”for”被改成了”htmlFor”.

IE浏览器:

element.style.styleFloat = "left";

其他浏览器:

element.style.cssFloat = "left";

float 的一些规则

float规则一
1.浮动元素在浮动的时候,其margin不会超过包含块的padding。例子见上demo-img & words
PS:如果想要元素超出,可以设置margin属性。

float规则二
1.如果有多个浮动元素,浮动元素会按顺序排下来而不会发生重叠的现象。

2.包含块的宽度小于两个浮动元素的宽度总和,后面的浮动元素将会向下浮动,其顶端是前面浮动元素的底端。

3.如果有多个浮动元素,下一个浮动元素的顶端不会超过上一个浮动元素的底端。

demo-1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>test</title>
</head>
<style>
*{
	margin:0;
	padding: 0;
}
.wrap{
	width: 600px;
	height: 600px;
	margin: 0 auto;
	border: 1px solid #f93;
}
.box1{
	float: left;
	width: 300px;
	height: 150px;
	background: #9f3;
}
.box2{
	float: left;
	width: 200px;
	height: 120px;
	background: #93f;
}
.box3{
	float: left;
	width: 80px;
	height: 100px;
	background: #f39;
}
.box4{
	float: left;
	width: 150px;
	height: 60px;
	background: #f93;
}
.box5{
	float: right;
	width: 50px;
	height: 50px;
	background: #3f9;
}
</style>
<body>
	<div class="wrap">
		<div class="box1">1.float:left</div>
		<div class="box2">2.float:left</div>
		<div class="box3">3.float:left</div>
		<div class="box4">4.float:left</div>
		<div class="box5">5.float:right</div>
	</div>	

</body>
</html>

result display

4的移动过程发生卡主现象。

总结浮动元素同时浮动的规律(个人观点,不准确):

1.多个浮动元素,同时浮动的规律,后一个浮动元素(无论浮动方向是否与前一个元素浮动方向相同),浮动查找要待的位置,都从前一个元素的top线找起,同时俩元素top齐平,若有它待的地儿,就乖乖待着;

2.接上1的条件,即使有它的上方也有够它待的地方,后一个元素的top线也不会高与前一个元素的top线,不会顶上去,哈哈,先来的是老大,不能爬到它上头去;看看元素5的的表现就明白了。

3.接上1的条件,如果没有后一个元素能待的地方,它就从前一个元素的bottom线开始查找地方,如果还没找到够大的地儿,就继续一层一层往下找,功夫不负有心人,总会找到的嘛;

4.接上3的条件,找到地儿之后干嘛,还要继续它的本职工作,朝着它需要的方向浮动,前进呀,要是运气不好有绊脚石的话,就会被卡住,比如元素4就被1卡住了;

5.接上4的条件,如果它运气好,一路畅通无阻,它又能当下一行的排头老大了,如下demo中的元素3,但悲催的是还是被前面先来的浮动元素压抑着,不能冒皮皮。

demo-2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>test</title>
</head>
<style>
*{
	margin:0;
	padding: 0;
}
.wrap{
	width: 600px;
	height: 600px;
	margin: 0 auto;
	border: 1px solid #f93;
}
.box1{
	float: left;
	width: 300px;
	height: 50px;
	background: #9f3;
}
.box2{
	float: left;
	width: 100px;
	height: 100px;
	background: #93f;
}
.box3{
	float: left;
	width: 250px;
	height: 120px;
	background: #f39;
}
.box4{
	float: right;
	width: 120px;
	height: 120px;
	background: #f93;
}
</style>
<body>
	<div class="wrap">
		<div class="box1">1.float:left</div>
		<div class="box2">2.float:left</div>
		<div class="box3">3.float:left</div>
		<div class="box4">4.float:right</div>
	</div>	

</body>
</html>

result display

float特殊情况

float浮动元素的延伸性

我们将span元素放在p元素内,并将其高度设置成高于p元素并且左浮动,这个例子的关键在浮动元素高度高于父元素。

demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>test</title>
</head>
<style>
*{
	margin:0;
	padding: 0;
}
p { 
	width: 500px; 
	margin-top: 20px; 
	margin-bottom: 20px; 
	background-color: #00ff21; 
}
 .high-float { 
 	float: left; 
 	height: 80px; 
 	line-height: 80px; 
 	background-color: orangered; 
 }
</style>
<body>
	<p>在浮动元素之前在浮动元素之前,在浮动元素之前,在浮动元素之前,在浮动元素之前,在浮动元素之前,在浮动元素之前,在浮动元素之前,
    	<span class="high-float">浮动元素比父级元素高</span>
    </p>
     <p>在浮动元素之后在浮动元素之后在浮动元素之后在浮动元素之后在浮动元素之后在浮动元素之后在浮动元素之后在浮动元素之后在浮动元素之后在浮动元素之后在浮动元素之后</p>
</body>
</html>

result display

1.浮动元素浮动到的位置是由当前它处于行数决定,浮到它当前行(或者它的下一行)的左右两端,而不是最顶端。
2.浮动元素高度高于父元素,可以看到浮动元素超出了父元素的底端。
2的这种情况要怎么解决呢,只要将父元素也设置成浮动即可,我们将第一个p元素设置成左浮动,效果如下

以上代码添加样式

p:nth-child(1){
	float: left;
}
p:nth-child(2){
	background-color: #f39; 
}

result display

浮动元素延伸性
将父元素p设置成float:left后,浮动元素就会被包含到父元素里面,我们将这个特性成为浮动元素的延伸性。
浮动元素的延伸性是什么呢,我们可以将其理解为元素被设置成浮动后,该元素会进行延伸进而包含其所有浮动的子元素

浮动元素超出父级元素的padding

(1)负maring的浮动元素
将margin-left设置成负数之后,浮动的子元素明显超出了父元素的内边界。

(2)浮动元素宽度大于父级元素宽度
如果我们将浮动元素的宽度设置大于父级元素,效果会如何呢?

将浮动元素左浮动,并且宽度超出父级元素时,由于浮动元素宽度较大,它会超过父级元素的右内边界; 设置成右浮动后,会超出父级元素的左内边界。

float重叠问题

重叠问题是指两个元素再同一个位置,会出现上下重叠的问题。浮动元素如果和普通文档流发生重叠会怎么样呢?

1、行内元素与浮动元素发生重叠,其边框,背景和内容都会显示在浮动元素之上
2、块级元素与浮动元素发生重叠时,边框和背景会显示在浮动元素之下,内容会显示在浮动元素之上

更多-more