1. 程式人生 > >css的浮動以及如何清除浮動

css的浮動以及如何清除浮動

css的浮動是經常會在實際中運用到,之前我對浮動的理解就是使用float,除此之外沒有深入理解,後來發現對於浮動還是有必要深入理解一下。

css浮動

css的浮動是float屬性,該屬性沒有繼承性,預設值為none,該屬性有四個值,以下一一解釋:

1)right:向右浮動

2)left:向左浮動

3)none:沒有浮動

4)inherit:規定繼承父元素的浮動

css的浮動實際上就是打破標準流,如果說沒有浮動的元素是在一個標準流裡,那麼浮動的元素將脫離原本的標準流浮動。

元素的浮動效果

例子:以下四個div並沒有進行浮動設定

<!DOCTYPE html>
<html>
<head>
	<title>測試</title>
	<meta charset="utf-8"/>
	<style type="text/css">
		.div1{width:1000px;height:100px;background:red;}
		.div2{width:200px;height:100px;background:yellow;}
		.div3{width:800px;height:100px;background:green;}
		.div4{width:700px;height:100px;background:blue;}
	</style>
</head>

<body>
<div class="div1">div1</div>
<div class="div2">div2</div>
<div class="div3">div3</div>
<div class="div4">div4</div>

</body>
</html>

我們來看一下下面的3d檢視,就會發現這四個div處於同一個標準流,相對於body層另起一層,下方紫色的邊緣白色底的是body層,白色邊白色底為html層,為了看得更清晰,我調整了角度。

由於每個div獨佔一行,根據標準流div1、div2、div3、div4自上而下進行排列!

下面我們將css改動一下對div1進行右浮動,為了讓例子更明顯,將div2的height改為200px,且div的width改為1500px,具體如下:

		.div1{width:1500px;height:100px;background:red;float:right}
		.div2{width:200px;height:200px;background:yellow;}
		.div3{width:800px;height:100px;background:green;}
		.div4{width:700px;height:100px;background:blue;}
在看3d檢視前我們先來看普通的頁面顯示:

在頁面顯示裡我們看得出div1右浮動,導致div1浮到了最右邊,而且div2上浮動了,div1位於div2的所在的層的上方覆蓋了div2的一部分,可以證實div1和div2、div3、div4不是在一個標準流上,div1打破了原先的標準流,進行了浮動,因此div2取代了之前div1的標準流代替了div1原先的位置,下面我們來看看3d檢視就能更清晰的瞭解到這一點:


自此我們可以得出結論,沒有設定浮動屬性的元素皆為同一個標準流上,浮動的屬性會相對於浮動的物件漂浮在上方,而且會放棄原本沒有浮動所佔的標準流位置,這就是為什麼div1浮動後,div2會跑到上面來的原因,因為原先div1所佔的位置清空了,原先的標準流被破壞並進行了重新配置,所以div2向上移動到原先div1所佔的位置!

那麼還有一個問題,為什麼是div1遮蓋div2,不是div2遮蓋div1呢?因為浮動的元素總會位於原先所處的標準流上方!這個非常重要,這裡div1、div2、div3、div4原本是同一個標準流,但是div1浮動後打破了原先的標準流,因此div1總會位於這個破壞重新建構的標準流上方!這樣就很好理解了。

下面為了能更熟悉浮動的這種理論模式,我們多看一個例子,便於更好的理解:

		.div1{width:1500px;height:400px;background:red;float:right;}
		.div2{width:200px;height:200px;background:yellow;}
		.div3{width:800px;height:100px;background:green;float:left}
		.div4{width:700px;height:100px;background:blue;}
先來看看頁面渲染的結果:

我們看上面的css程式碼,改動的地方為div1的height為400,div3改為了左浮動,那麼div2和div4是沒有浮動的,它們在一個標準流裡,並且因為div1和div3已經浮動了,所以以前佔據的空間已經清空,原先的標準流被打破並且重新建構,因此div2和div4重新佈局頂替了原先div1和div3的位置,而div1和div3之前都是在同一個標準流,所以浮動 後它們位於同一個流裡,雖然都在div2和div4上方,但是div1和div3會按照新的標準流從上而下排列,而不會互相覆蓋!因此如上圖那樣。

下面是3d檢視,可以更好的理解一下:


下面我們來看一個這樣的例子:

我們給上面的例子的div1中加一個class為divn1的div,顏色為粉紅,為左浮動,具體css如下:

		.divn1{width:800px;height:100px;float:left;background:pink;}
<div class="div1">
	<div class="divn1">divn1</div>
	div1
</div>
<div class="div2">div2</div>
<div class="div3">div3</div>
<div class="div4">div4</div>
頁面渲染如下:


這裡相信很多人都會混亂起來,其實分析一下就很好理解,沒有浮動前,div1、div2、div3、div4位於同一個標準流,之後div1和div3進行了右浮動和左浮動,而兩者位於之前打破過的標準流上方,所以會覆蓋之前的div2和div4,同時div1和div3構建了新的標準流,因此不會互相覆蓋,而是由上往下進行排列,到這裡都很好理解,和上面的解釋一致,這裡改變的是div1內部增加了一個divn1,divn1進行了右浮動,並且在div1內建立了一個屬於自己的層,同時也建立了一個自己的標準流,它所位於的層高於div1,從3d檢視中可以看出來,這個時候的div1、div2、div3、div4是同一個層,這裡一定不要搞錯,但是渲染的情況是,div3覆蓋了divn1,這是為什麼呢?

以下為3d檢視:

其實這是因為divn1不管有沒有浮動,都會如此渲染,這個是由於divn1對於div1來講是一個內部的新的層,這個層是在div1內部,它的高度過高,導致了溢位,它能覆蓋div1,是因為divn1的層比div1高,並不是浮動導致的,但它的覆蓋權利在div1內部,因為它的層在div1內部,這就是為什麼無法覆蓋div2的原因。

能突破上面的只有進行position處理,position可以改變divn1的層所處的範圍,因此可以打破覆蓋權利範圍,例如上面divn1加上position:relative;top:0px;就會變成如下圖:


這是因為position打破了原本divn1的限制範圍,它的權利範圍不再限定於div1內部,而它的層位於div1上方,而div1和div3位於同一個層,因此可以覆蓋div3!

元素浮動對文字的影響:文字環繞效果

浮動不僅僅是有打破標準流的效果,還有文字環繞效果,這點需要注意!因為這個很容易被忽略。

首先我來看看以下這個例子:

<div style="width:300px;height:auto;background:red">
	<div style="width:100px;height:100px;background:blue;">內部div1</div>
	測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試
	<div style="width:100px;height:100px;background:yellow;">內部div2</div>
</div>



可以看出div內部存在一個div1和一個div2,這兩個div會在外部div內部新建一個層,這個層高於外面的div,因此會覆蓋紅色背景的外部div,由於沒有浮動,因此根據標準流自上而下的排列,要注意div內部的文字也是標準流的一部分,因此也是由上而下進行排列,排列順序為div1、文字、div2,因此渲染成上圖的樣子,下面是3d檢視!


下面對div1和div2進行浮動,div1為左浮動,div2為右浮動。打破了原先的標準流,div1和div2將會位於原先標準流的上方,但是由於文字是文字流,和文件流的標準流不一樣,文字流雖然因為div1的左浮動破壞了原先文件流和文字流之間標準流的排列,但是文字流和文件流不一樣的是它不是完全上移,而是環繞在周圍,也就是文字環繞!下方的div2是右浮動,由於受到文字流的擠壓會移到最右邊的下方沒有文字的地方進行排列!具體如下圖顯示:


元素的浮動效果對文字的影響主要體現在文字環繞上面,雖然div1和div2的浮動打破了原先的標準流,從標準流中脫離了出來,但是依然受到了文字的擠壓,這就是為什麼div2無法上浮到最上方的右側的原因,之所以浮動的元素依然會受到文字擠壓而不是完全脫離標準流覆蓋div內的文字,是由於原本浮動的設定一開始就是為了進行環繞效果的實現,後來進行拓展才成了今天的允許全部元素進行浮動,同時衍生了浮動脫離標準流的定義,但文字環繞的效果依然進行了保留,並沒有完全脫離標準流。

如果要完全脫離標準流,需要使用position:absolute進行絕對定位,這樣就會完全覆蓋文字,而不會環繞!

清除浮動clear

之前過年休息了一段時間,現在繼續補充之前沒寫完的內容,clear可以對抗浮動,但只能對自身起作用!顧名思義就是某元素如果設定了clear該屬性的話,該元素可以根據clear的值抗浮動,該css屬性沒有繼承性,有以下幾個值,很多網站的解釋我感覺有一些歧義,所以重新做了解釋:

left:設定了該屬性值的元素的盒子的左側邊不能與浮動元素相鄰

right:設定了該屬性值的元素的盒子的右側邊不能與浮動元素相鄰

both:設定了該屬性值的元素的盒子的兩側邊不能與浮動元素相鄰

none:預設值,允許該元素的盒子邊左右兩側與浮動元素相鄰

inherit:繼承父元素的clear屬性

例子1,先來看left值的情況,具體如下:

程式碼:

<!DOCTYPE html>
<html>
<head>
<title>測試</title>
<meta charset="utf-8"/>
<style type="text/css">
.div1{width:300px;height:150px;background:red;float:left}
.div2{width:300px;height:150px;background:green;float:left}
.div3{width:400px;height:300px;background:blue;}
</style>
<body>
<div class="div1">div1</div>
<div class="div2">div2</div>
<div class="div3">div3</div>
</body>
</html>

渲染圖:


首先來分析一下,div1是height=150的紅色色塊,div2是height=150的綠色色塊,都有float:left的設定,因此div1和div2都脫離了原先的標準流向左側擠壓,而div3是height=300的藍色色塊,由於div3沒有設定float的浮動屬性,因此div3還是原來的標準流,但是由於div1和div2從原來的標準流裡分離了,因此重新生成了標準流,div3會佔據原先div1和div2的標準流位置,因此div3位置上移,變成如圖的情況。

下面我們來給div3設定clear屬性,屬性值為left,這個時候頁面渲染情況如下:

css如下:

		.div1{width:300px;height:150px;background:red;float:left;}
		.div2{width:300px;height:150px;background:green;float:left;}
		.div3{width:400px;height:300px;background:blue;clear:left;}


渲染圖:

可以看出div3採用clear屬性值為left後位置下移了,這是為什麼呢?

分析結果:上面已經說明了clear屬性值設定為left,那麼div3的盒子模型左邊是不能接浮動元素的,但我們回到上面沒有clear設定的圖看一下,藍色色塊也就是div3就在div1的下面,div1紅色色塊浮動覆蓋在div3上面,所以等於是div1浮動元素和div3的左邊是緊鄰的,這就符合了clear的起效條件,於是clear抗div1的浮動,於是下移到上圖的位置,確保了div3的盒子模型左邊沒有與浮動元素相鄰。

很多人認為是div1的浮動被清除了,這點是有歧義的,div3的clear屬性只對自身起效,因此僅僅是為了抗浮動改變了div3,沒有權力去更改div1,這點一定要明確!

所以如果上面的div3的clear值改為right,就會出現下面的渲染頁面,clear並沒有起作用,因為div3的右邊並沒有緊鄰浮動元素,因此div1無須做任何改變。


下面我們再來看看clear:right的例子,首先我們先不用clear屬性,看情況是如何的:

程式碼:

<!DOCTYPE html>
<html>
<head>
	<title>測試</title>
	<meta charset="utf-8"/>
	<style type="text/css">
		.div1{width:300px;height:150px;background:red;float:left;}
		.div2{width:1400px;height:150px;background:green;float:right;}
		.div3{width:400px;height:300px;background:blue;}
	</style>
<body>
<div class="div1">div1</div>
<div class="div2">div2</div>
<div class="div3">div3</div>
</body>
</html>

渲染結果;


分析:div1左浮動,div2右浮動,div3沒有浮動,因此div1和div2脫離原本的標準流,div1和div2形成新的標準流,由於div2右浮動被div1擠壓了,所以自上而下div2排列在div1下,div3取代之前div1和div2的位置形成新的標準流,所以div3在div1和div2的下面被其兩個div覆蓋。

如果div3這個時候新增clea屬性r的right值會怎麼樣,先不看渲染結果進行分析:

由於div3有clear的right設定,因此div3的盒子模型右邊不能與浮動元素相鄰,但是上面div3的右邊與div2相鄰,因此div3的clear屬性開始起效,這會導致div3為了避免與div2的相鄰下移到div2下以此達到目的。

下面我們來看下渲染結果對不對:

程式碼:

<!DOCTYPE html>
<html>
<head>
	<title>測試</title>
	<meta charset="utf-8"/>
	<style type="text/css">
		.div1{width:300px;height:150px;background:red;float:left;}
		.div2{width:1400px;height:150px;background:green;float:right;}
		.div3{width:400px;height:300px;background:blue;clear:right;}
	</style>
<body>
<div class="div1">div1</div>
<div class="div2">div2</div>
<div class="div3">div3</div>
</body>
</html>

渲染結果如下,和我們分析的結果一致:


再來我們把div3的clear屬性值換成both又會發生什麼呢?分析一下:

首先我們看沒有設定clear屬性的值會發現,div3的左邊還有右邊都與浮動元素相鄰,因此clear啟動功效,但由於div1和div2的位置已經確定,div1左浮動在左側,而div2被div1擠壓到下方右浮動,因此為了避免div3與兩者相鄰,div3只需要位於div2下方即可,還是和clear值為left時一樣的渲染結果,下圖就是此種情況的渲染圖:


最後我們看到這裡會發現其實clear是幫助自身元素抗拒浮動元素的影響,根據自身的值幫助自身元素不與浮動元素相鄰!只是啟動這些效果的時候看上去很像清除了其他元素的浮動,其實並沒有,這裡很容易產生歧義,一定要重點理解!能起到這種效果的不僅僅是clear而已,還有很多其他的方法,但本篇部落格暫時到這裡結束,以後另外另寫一篇進行總結。