1. 程式人生 > 實用技巧 >《洛谷CF375D Tree and Queries》

《洛谷CF375D Tree and Queries》

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)的問題,到時你可以查閱一些資料來解決問題。

不要以為floatinline-block比較相似,就以為浮動元素的顯示方式(display)就是inline-block,實際上,浮動元素的顯示方式(display)是block,確切地說是“通常情況下,浮動元素displayblock”,有些情況雖然不是block,比如displaylist-item,本質上也和block差不多。

下圖,span元素本來是內聯元素(displayinline)浮動(floatleft)後,我們通過瀏覽器右鍵的“審查元素”可以看到displayblock

這樣,行內元素(比如span標籤、a標籤)和塊元素(比如div標籤)一旦浮動後都是一樣的效果了,就是說<div style=”float:left;background:#ccc”>浮動元素</div><span style=”float:left;background:#ccc”>浮動元素</span>是完全一樣的。這時再加上display屬性就多餘了,加上display屬性(比如display:inline)瀏覽器也不會採用,純屬畫蛇添足。

有人就問了“多個浮動元素可以水平排列在同一行,而浮動元素display:block就應該獨佔一行呀!,這不是互相矛盾嗎?”,你看到上圖中的那個詞語了嗎?“特殊”的塊元素。因為浮動元素脫離了文件流(標準流),此時的塊元素(displayblock)已不是標準流中的塊元素了,它自收縮(包裹性),不再佔用整行寬度,所以多個浮動元素可以水平排列在同一行。

補充一點,浮動元素“脫離標準流”,這裡的“脫離標準流”和position:absolute脫離標準流不太一樣,float的脫離標準流,在自由度上受限,不是自由翱翔的那種,而absolute脫離標準流是可以滿世界亂跑的那種,自由度很大。所以,有的資料中不認可“浮動元素脫離標準流”的說法。本文不過於追究細節,籠統地說“浮動元素脫離標準流”,讀者可以粗略這麼理解。

2、破壞性

破壞性,就是打破規則,並且影響周圍元素。就像特朗普不斷退群,不斷修改規則,儘管讓別的國家不知所措,對美國心生怨恨,但礙於美國實力,只能忍氣吞聲。

本文第一張圖的第一部分,圖片浮動前和文字基線對齊,在一行顯示,圖片高度比文字高,所以圖片所在的這行跟別的(純文字)行就不一樣,這行顯得很高,其實就是圖片給撐起來的。

圖片浮動(floatleft)後,以往的規則打破了,它像一副軀殼一樣向左移動,它和文字不再基線對齊,打破了原有的規則。破壞性不僅表現在對齊方式的改變,還表現在父元素的高度塌陷上(子元素在浮動前要向父元素彙報高度,父元素把所有子元素的高度收集到後就確定了自己的高度,子元素浮動後,就不再向父元素彙報高度了,因此父元素收集不到子元素的高度就導致自己的高度塌陷)。

(二)浮動規則

1、圖文環繞可以推廣為:行內級內容會被浮動元素推出去(行內級內容包括行內級元素、inline-block元素、塊級元素的文字內容)

行內級內容被浮動元素推出

提示讀者,操作時注意調整瀏覽器的寬度

2、浮動元素只能在當前行中移動(floatleft,從右向左移動 floatright相反),遇到包含塊(父元素)或其他浮動元素的邊界為止。如果水平方向剩餘的空間不夠顯示,浮動元素將向下移動,直到有足夠的空間位置為止。

下面的程式碼

 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>
View Code

在瀏覽器寬度較大時,第一部分文字和第二部分文字都在圖片右側排列

在瀏覽器寬度較小時,第一部分文字在圖片的上方排列

下面的程式碼是幾個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>
View Code

程式碼結構:八個div都是floatleftbox1box8依次,儘管瀏覽器寬度不同時,浮動元素排布的結果不同,但是都遵循一定的規則,請看下圖

為了說明問題,稍微刪減部分divdiv仍然都是floatleftdiv的寬、高有所調整

 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>
View Code

由以上圖可見,浮動元素的排列有相當嚴格的等級制度,後浮動的元素只能與前面的浮動元素在同一水平線上(以頂部為準),前提是後面的空間足夠大。如果後面的空間不夠,就會向下錯位,錯位後如果沒有遇到阻力,還是水平移動(floatleft從右向左移動,floatright相反),移動過程中不會再上移動,水平移動直到遇到阻力,永遠不會出現後面的浮動元素高於前面的浮動元素(以頂部為準)。就是說,後浮動的元素要麼與前面的浮動元素平起平坐(頂部在同一水平線上),前提是後面的空間足夠大;如果後面的空間不夠,後浮動的元素只能處於下層,永遠不會出現“僭越”,等級森嚴!

三、清除浮動

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>
View Code

方法1、增加一個額外的divclearboth

<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可能會退出網頁佈局的歷史舞臺。但那是將來的事,如果你對瀏覽器的相容性有較高要求,你還不得不掌握它的浮動規律。

雖然很相似,但是仔細觀察上圖還是有些差別,比如li之間的縫隙,inline-block中間有縫,float中間沒縫,在實際佈局中,一般都希望中間沒縫,這樣便於計算尺寸。所以,float在這方面有先天優勢(float能去空格,嚴絲合縫適合網頁佈局,通常把float佈局叫做“碼磚頭”)。當然,如果你不介意中間的縫隙,或者採用一些辦法去掉縫隙,也可以採用inline-block,實際情況下,如果程式碼稍微複雜些,inline-block可能還會出現垂直對齊(vertical-align)的問題,到時你可以查閱一些資料來解決問題。

不要以為floatinline-block比較相似,就以為浮動元素的顯示方式(display)就是inline-block,實際上,浮動元素的顯示方式(display)是block,確切地說是“通常情況下,浮動元素displayblock”,有些情況雖然不是block,比如displaylist-item,本質上也和block差不多。

下圖,span元素本來是內聯元素(displayinline)浮動(floatleft)後,我們通過瀏覽器右鍵的“審查元素”可以看到displayblock