float属性,会使元素向左或向右移动,其周围的元素也会重新排列。float不仅自己飘忽不定,还对周围元素有影响,这种影响力不容小觑。他捉摸不定(浮动规律不好把握),他干涉他国内政(对周围元素有影响),这些特点就像今天的美国总统特朗普(别名“特不靠谱”)。学习float就得了解它的前世今生,它的本质,掌握它的规律才能降妖除魔,为我所用。
一、float的前世今生
float设计之初,目的就是图文环绕
如果float一直踏踏实实、本本分分的干好本职工作,那他就是一个“好人”。float本该“不忘初心,牢记使命”,就像我们党开展的教育活动那样,可是他后来忘记了自己的初衷,竟参与到网页布局中,一度还乐此不疲,甚至受到一些程序员青睐。
最早的网页布局很简单,元素的排列就是靠table、tr、td这样一些标签,页面很简单,float就是用来做图文环绕的,但是后来程序员发现float用在布局上也不错,打破了tabel(tr、td)标签死板的布局方式,float布局更加灵活多样。这样float就开始了“华丽转身”,正式成为网页布局中的一员大将。
其实,float有很多毛病,他的浮动规律让很多人摸不着头脑,而且周围元素经常受到影响,稍有不慎原有的排布会支离破碎,所以有人说他是“魔鬼”,说他是“混球”,说他是“不务正业”,说他“跨界太大”,一点也不为过。
随着浏览器版本的升级,float在布局方面的作用逐渐被取代,但是,由于float的兼容性好,尽管他有很多问题,人们还是(不得不)包容他,在研究浮动规律的基础上,驾驭他、降伏他、利用他。
二、float的浮动规律
(一)float的本质
1、包裹性(与inline-block\block对比)
包裹性就是在未设定宽度的情况下,根据内容自适应(也可以叫“自收缩”)。如下图:
具有包裹性的还有display:inline-block、position:absolute、position:fixed等。
在布局上float与inline-block很相似,如下图:
虽然很相似,但是仔细观察上图还是有些差别,比如li之间的缝隙,inline-block中间有缝,float中间没缝,在实际布局中,一般都希望中间没缝,这样便于计算尺寸。所以,float在这方面有先天优势(float能去空格,严丝合缝适合网页布局,通常把float布局叫做“码砖头”)。当然,如果你不介意中间的缝隙,或者采用一些办法去掉缝隙,也可以采用inline-block,实际情况下,如果代码稍微复杂些,inline-block可能还会出现垂直对齐(vertical-align)的问题,到时你可以查阅一些资料来解决问题。
不要以为float和inline-block比较相似,就以为浮动元素的显示方式(display)就是inline-block,实际上,浮动元素的显示方式(display)是block,确切地说是“通常情况下,浮动元素display:block”,有些情况虽然不是block,比如display:list-item,本质上也和block差不多。
下图,span元素本来是内联元素(display:inline)浮动(float:left)后,我们通过浏览器右键的“审查元素”可以看到display:block
这样,行内元素(比如span标签、a标签)和块元素(比如div标签)一旦浮动后都是一样的效果了,就是说<div style=”float:left;background:#ccc”>浮动元素</div>与<span style=”float:left;background:#ccc”>浮动元素</span>是完全一样的。这时再加上display属性就多余了,加上display属性(比如display:inline)浏览器也不会采用,纯属画蛇添足。
有人就问了“多个浮动元素可以水平排列在同一行,而浮动元素display:block就应该独占一行呀!,这不是互相矛盾吗?”,你看到上图中的那个词语了吗?“特殊”的块元素。因为浮动元素脱离了文档流(标准流),此时的块元素(display:block)已不是标准流中的块元素了,它自收缩(包裹性),不再占用整行宽度,所以多个浮动元素可以水平排列在同一行。
补充一点,浮动元素“脱离标准流”,这里的“脱离标准流”和position:absolute脱离标准流不太一样,float的脱离标准流,在自由度上受限,不是自由翱翔的那种,而absolute脱离标准流是可以满世界乱跑的那种,自由度很大。所以,有的资料中不认可“浮动元素脱离标准流”的说法。本文不过于追究细节,笼统地说“浮动元素脱离标准流”,读者可以粗略这么理解。
2、破坏性
破坏性,就是打破规则,并且影响周围元素。就像特朗普不断退群,不断修改规则,尽管让别的国家不知所措,对美国心生怨恨,但碍于美国实力,只能忍气吞声。
本文第一张图的第一部分,图片浮动前和文字基线对齐,在一行显示,图片高度比文字高,所以图片所在的这行跟别的(纯文字)行就不一样,这行显得很高,其实就是图片给撑起来的。
图片浮动(float:left)后,以往的规则打破了,它像一副躯壳一样向左移动,它和文字不再基线对齐,打破了原有的规则。破坏性不仅表现在对齐方式的改变,还表现在父元素的高度塌陷上(子元素在浮动前要向父元素汇报高度,父元素把所有子元素的高度收集到后就确定了自己的高度,子元素浮动后,就不再向父元素汇报高度了,因此父元素收集不到子元素的高度就导致自己的高度塌陷)。
(二)浮动规则
1、图文环绕可以推广为:行内级内容会被浮动元素推出去(行内级内容包括行内级元素、inline-block元素、块级元素的文字内容)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 7 <title>test</title> 8 </head> 9 <style> 10 .floatDiv{ 11 float:left;width:200px;height:200px;background:purple;color:#fff; 12 } 13 .inlineElement{ 14 background:orange;padding:0 10px; 15 } 16 .inlineBlockElement{ 17 display:inline-block;background:red;height:30px;width:130px; 18 } 19 </style> 20 <body> 21 <div class="floatDiv">浮动元素</div> 22 23 <span class="inlineElement">行内元素</span> 24 <span class="inlineElement">行内元素</span> 25 <span class="inlineElement">行内元素</span> 26 <span class="inlineElement">行内元素</span> 27 <span class="inlineElement">行内元素</span> 28 <span class="inlineElement">行内元素</span> 29 <span class="inlineElement">行内元素</span> 30 <span class="inlineElement">行内元素</span> 31 <span class="inlineElement">行内元素</span> 32 <span class="inlineElement">行内元素</span> 33 34 <div class="inlineBlockElement">inline-block元素</div> 35 <div class="inlineBlockElement">inline-block元素</div> 36 <div class="inlineBlockElement">inline-block元素</div> 37 <div class="inlineBlockElement">inline-block元素</div> 38 <div class="inlineBlockElement">inline-block元素</div> 39 <div class="inlineBlockElement">inline-block元素</div> 40 <div class="inlineBlockElement">inline-block元素</div> 41 42 <div style="background:green;width:800px;height:400px;"> 43 浮动元素脱离文档流,div(块元素)与浮动元素有重叠,但是div(块元素)里的文字,依然环绕在浮动元素周围。 44 浮动元素脱离文档流,div(块元素)与浮动元素有重叠,但是div(块元素)里的文字,依然环绕在浮动元素周围。 浮动元素脱离文档流,div(块元素)与浮动元素有重叠,但是div(块元素)里的文字,依然环绕在浮动元素周围。 45 </div> 46 </body> 47 </html>
提示读者,操作时注意调整浏览器的宽度
2、浮动元素只能在当前行中移动(float:left,从右向左移动 float:right相反),遇到包含块(父元素)或其他浮动元素的边界为止。如果水平方向剩余的空间不够显示,浮动元素将向下移动,直到有足够的空间位置为止。
下面的代码
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <meta http-equiv="X-UA-Compatible" content="ie=edge">
7 <title>code2</title>
8 </head>
9
10 <body>
11 这是第一部分文字,如果浏览器的宽度较小,这段文字会在图片的上方
12 <img src="img/pic1.jpg" style="float:left;">
13 <span style="color:#000;">第二部分文字,其他内容,其他内容,其他内容,其他内容(更多内容在此省略)</span>
14 </body>
15 </html>
在浏览器宽度较大时,第一部分文字和第二部分文字都在图片右侧排列
在浏览器宽度较小时,第一部分文字在图片的上方排列
下面的代码是几个div浮动后排布的情况
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <meta http-equiv="X-UA-Compatible" content="ie=edge">
7 <title>test</title>
8 </head>
9 <style>
10 .box1{width:200px;height:400px;background:blue;}
11 .box2{width:300px;height:300px;background:yellow;}
12 .box3{width:400px;height:200px;background:purple;}
13 .box4{width:100px;height:500px;background:red;}
14 .box5{width:500px;height:400px;background:green;}
15 .box6{width:500px;height:100px;background:gray;}
16 .box7{width:100px;height:400px;background:orange;}
17 .box8{width:400px;height:400px;background:#ccc;}
18 div{float:left;}
19 </style>
20 <body>
21 <div class="box1">box1</div>
22 <div class="box2">box2</div>
23 <div class="box3">box3</div>
24 <div class="box4">box4</div>
25 <div class="box5">box5</div>
26 <div class="box6">box6</div>
27 <div class="box7">box7</div>
28 <div class="box8">box8</div>
29
30 </body>
31 </html>
代码结构:八个div都是float:left,box1至box8依次,尽管浏览器宽度不同时,浮动元素排布的结果不同,但是都遵循一定的规则,请看下图
为了说明问题,稍微删减部分div,div仍然都是float:left,div的宽、高有所调整
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <meta http-equiv="X-UA-Compatible" content="ie=edge">
7 <title>code4</title>
8 </head>
9 <style>
10 .box1{width:400px;height:100px;background:blue;}
11 .box2{width:100px;height:500px;background:yellow;}
12 .box3{width:300px;height:200px;background:purple;}
13 .box4{width:300px;height:300px;background:red;}
14 .box5{width:300px;height:300px;background:green;}
15 div{float:left;}
16 </style>
17 <body>
18 <div class="box1">box1</div>
19 <div class="box2">box2</div>
20 <div class="box3">box3</div>
21 <div class="box4">box4</div>
22 <div class="box5">box5</div>
23
24 </body>
25 </html>
由以上图可见,浮动元素的排列有相当严格的等级制度,后浮动的元素只能与前面的浮动元素在同一水平线上(以顶部为准),前提是后面的空间足够大。如果后面的空间不够,就会向下错位,错位后如果没有遇到阻力,还是水平移动(float:left从右向左移动,float:right相反),移动过程中不会再上移动,水平移动直到遇到阻力,永远不会出现后面的浮动元素高于前面的浮动元素(以顶部为准)。就是说,后浮动的元素要么与前面的浮动元素平起平坐(顶部在同一水平线上),前提是后面的空间足够大;如果后面的空间不够,后浮动的元素只能处于下层,永远不会出现“僭越”,等级森严!
三、清除浮动
float是魔鬼,是混球,是黑恶势力,清除浮动就是“降妖除魔”,就是“扫黑除恶”。
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <meta http-equiv="X-UA-Compatible" content="ie=edge">
7 <title>code5</title>
8 </head>
9 <style>
10 .wrap{background:red;}
11 .wrap:after{display:block;content:'';clear:both;}
12 .content{float:left;width:300px;height:100px;}
13 .content1{background:lightblue;}
14 .content2{background:lightgreen;}
15 .content3{background:darkblue;}
16
17
18 .footer{height:50px;background:#ccc;}
19 </style>
20 <body>
21 <div class="wrap">
22 <div class="content content1"></div>
23 <div class="content content2"></div>
24 <div class="content content3"></div>
25 </div>
26 <div class="footer">footer</div>
27 </body>
28 </html>
方法1、增加一个额外的div(clear:both)
<div class="wrap">
<div class="content content1"></div>
<div class="content content2"></div>
<div class="content content3"></div>
<div style=”clear:both;”></div>
</div>
<div class="footer">footer</div>
这种方法就是相当于加了一个防火墙(防魔墙),打了一个隔板,但是因为增加了额外标签,可读性不强,所以不怎么推荐。
方法2、在父元素(class=”wrap”)填加属性overflow:hidden
.wrap{overflow:hidden;}
这种方法的解释,很难用一句话两句哈说清楚,所以本文不解释理由,这种方法兼容性也还可以,所以推荐使用。
方法3、使用父元素的伪类选择器
.wrap:after{display:block;content:””;clear:both;}
这跟方法1的道理差不多,但是没有增加额外标签,兼容性也还可以,所以推荐使用。
四、float的未来命运
我们使用float浮动做了很多其本职工作以外的事情。目前用float实现的不管是分栏布局,还是列表排列,我们都可以用其他一些CSS属性代替实现,唯一一个实现不了的就是“文字环绕图片”。未来,float可能会再回到老本行,只做图文环绕,把网页布局交给其他属性,也就是说float可能会退出网页布局的历史舞台。但那是将来的事,如果你对浏览器的兼容性有较高要求,你还不得不掌握它的浮动规律。