什麼是浮動?html
CSS中的一些元素是塊級元素,表示它們會自動另起一行。web
舉個例子,若是你建立了兩個段落,每一個段落都只有一個單詞。這兩個單詞不會靠在一塊兒,而是會各自佔據一行。瀏覽器
另外一些元素是行內元素,表示它們和前面的內容位於相同的一行。佈局
舉個例子,<a>能夠出如今另外一個元素中,好比<p>,這不會產生多餘的空格或者出現換行。spa
欺騙這種佈局模型的一種方式是使用浮動,浮動可讓一個元素移到它所在行的某一邊,使得其餘內容沿着該元素的邊緣向下流。3d
一個典型的例子是你想要一張圖片和一個段落並排出現,而不是一上一下排列。首先咱們先來建立HTML:code
<img src="http://lorempixum.com/200/200/" /> <p>Lorem ipsum...</p>
單獨這段代碼並不能實現咱們想要的效果。<p>是一個塊級元素,它會獨佔一行,因此圖片和段落是一上一下展示的。 htm
經過讓圖片向右浮動能夠改變這種行爲,以下:blog
img { float: right; margin: 20px; }
這樣,圖片就跑到右邊去了,而段落則沿着圖片的左邊向下流式佈局。圖片
如今發生了一件有趣的事,當這張圖片浮動後,其餘的內容就會想辦法儘量的包圍它。若是咱們resize容器或者瀏覽器窗口,讓它更窄,這段文本就會發生重排(reflow),這樣它就永遠不可能接觸到圖片。
盒模型如何工做
也許你已經對上面所講的知識有了深入的理解。可是,爲了徹底掌握浮動,你須要更加深入的理解兩個元素如何互相做用。舉個例子,若是咱們在段落和圖片之間加一個邊距會發生什麼?
p {margin: 20px;}
可是呢,這麼寫並不會在圖片和段落之間產生額外的空間。實際上,咱們須要給圖片加margin:
img {margin: 20px;}
也許你會問爲何呢?爲何增長<p>的margin不會增長圖片和段落的間距呢?
緣由是咱們沒有理解<p>的盒模型。
若是如今你對佈局產生了一些疑慮,能夠試着加一個或者兩個border,看看會發生什麼。下面給<p>加border:
p {
border: solid 1px black;
}
如你所見,圖片實際上位於<p>盒模型的內部!這就能夠解釋剛纔的margin問題。咱們加到<p>上的margin實際上是做用於圖片的右側,這就是爲何它不能增長圖片和段落之間的距離!
若是咱們想改變這種行爲,使得段落不會包圍圖片,咱們應該讓段落向左浮動,並設置一個寬度(若是不設置,<p>的寬度默認是100%,這樣就不會和圖片緊挨着了,由於若是段落很長,它會跑到下一行)。
img {
float: right;
margin: 20px;
}
p {
float: left;
width: 220px;
margin: 20px;
}
瘋狂的浮動規則
如今你知道什麼是浮動了,而且知道浮動如何影響相關元素的盒模型。接下來要說的也許不少人都不瞭解:如何調整浮動元素的位置。
web開發中不少人會給<li>使用浮動。下面來看一個例子:
<ul> <li><img src=""/>1</li> <li><img src=""/>2</li> <li><img src=""/>3</li> <li><img src=""/>4</li> <li><img src=""/>5</li> <li><img src=""/>6</li> <li><img src=""/>7</li> </ul>
全部<li>默認應該是垂直方向上排列的,這就表示<li>是塊級元素。即便圖片是行內元素,它也會被它的父級塊級元素管理。爲了解決這個問題,咱們讓<li>向左浮動。當一行內的多個<li>被浮動後,它們會產生相似行內元素的流式佈局。然而,正如你即將看到的,它們有一些關鍵的不一樣。
li {
float: left;
margin: 4px;
}
如今,若是全部圖片的高度相同,就會產生下面的效果。
可是,咱們的圖片高度不是同樣的,一些是100px,另外一些是150px。這就引發了一些嚴重的問題!
當我第一次看到這個效果,我蛋疼了。爲何圖片4跑到右邊去了?它不是應該儘量的向左浮動麼?若是咱們放棄浮動而使用display:inline,結果會大不同。
li {
display: inline;
}
這個例子中,圖片默認是垂直居底(bottom)對齊。這和咱們以前的例子不一樣,爲了解決對齊問題,咱們添加一行CSS。
img {
vertical-align: top;
}
由此可知,使用display:inline 能夠更容易猜到<li>的排列結果。當水平方向沒有多餘的空間時,下個元素就會另起一行。
浮動爲何不能實現這種效果呢?
CSS規範對於浮動行爲歸納了9個規則。但問題是,只有規範的做者和那些無聊的人才能理解這些規則。下面摘錄了其中一個規則:
「If the current box is left-floating, and there are any left-floating boxes generated by elements earlier in the source document, then for each such earlier box, either the left outer edge of the current box must be to the right of the right outer edge of the earlier box, or its top must be lower than the bottom of the earlier box. Analogous rules hold for right-floating boxes.」
對於這些規則,也許你比我理解的更深,但說實話,這些規則讓我很是蛋疼。爲了簡化它,Josh Johnson給出了他的9條規則(注:我以爲這位仁兄的9條規則依然很囉嗦,我再給精簡一下):
1. 浮動元素的活動區域
僅限於它的父容器元素,不會超出父容器
2. 浮動元素的位置
水平方向:儘量居左或居右,若是它前面還有浮動元素,會跟在它後面,若是超出該行就會換行
垂直方向:儘量的居頂
關於水平方向的位置,須要注意如下幾點:
1) 向左浮動的元素不會出如今向右浮動的元素的右側
關於垂直方向的位置,須要注意如下幾點:
1) 浮動元素不會比容器的頂部還高
2) 浮動元素不會比前一個塊級元素或浮動元素更高
3) 浮動元素不會比前一個行內元素更高
在佈局時,垂直方向的規則比水平方向的優先級更高
總的來講就是,浮動元素會移到左側或右側。除非該元素前面還有一個浮動元素,這時它就會緊挨着前面的元素。
真正讓人迷惑的是:浮動元素會盡量的居頂,而且垂直定位規則比水平浮動規則的優先級更高。
在前面的例子中,圖片2撐高了該行的高度,因此在放完圖片3後,仍然有足夠的垂直空間放置圖片4。
記住,當你有一個浮動元素(不位於尾行)時,它後面的浮動元素佔用的垂直空間必須大於或等於它纔會觸發換行。
浮動順序
舉個例子,咱們有6張圖片的一個列表。
<ul> <li><img src="http://placehold.it/100x100&text=1"/></li> <li><img src="http://placehold.it/100x100&text=2"/></li> <li><img src="http://placehold.it/100x100&text=3"/></li> <li><img src="http://placehold.it/100x100&text=4"/></li> <li><img src="http://placehold.it/100x100&text=5"/></li> <li><img src="http://placehold.it/100x100&text=6"/></li> </ul>
若是咱們向左浮動圖片,它們就會按照原來的順序排列。但若是向右浮動呢?
能夠發現,第一張圖片佔據了最右的位置。相似的,換行後,第四張圖也佔據了最右的位置。這就是爲何你不多看到導航欄的列表項會向右浮動的緣由。
清除浮動
使用浮動能夠方便的實現一些佈局,好比建立n欄內容。可是呢,一旦使用浮動就會影響文檔正常的流式佈局。好比,剛纔那個例子中,咱們想在列表下方加上一個段落。
這個結果也許不是你想要的。這裏的解決方法是使用 clear 屬性,它的做用是清除該元素某側的浮動。好比,咱們對第二個列表項使用clear:left
ul li:nth-child(2) {
clear: left;
}
這段代碼告訴瀏覽器第二項的頂部必須比它前面的浮動元素的底部更低。若是全部列表項是向右浮動的,則須要使用clear: right
加上段落文本再看
很明顯這依然不是咱們想要的效果,解決方法是給段落使用clear,這會使得段落出如今浮動元素的下方而不是與它們相鄰。
p {
clear: both;
}
其實這裏咱們只須要清除左側的浮動便可,可是當一個開發者爲了確保清除了全部浮動,clear:both是很經常使用的一種方法。
浮動的問題和clearfix
當一個元素只包含浮動元素時,該容器元素會出現高度重疊(和高度爲0的效果同樣,即高度的頂邊和底邊重疊)。爲了演示這個現象,咱們仍是使用剛纔的例子,只是給列表加一個背景色。
ul {
background: gray;
}
若是列表項沒有浮動,能夠看到整個列表都是灰色的,而列表項則是從上到下排列。
如今咱們浮動全部列表項,這時<ul>只包含浮動的元素,因此它的高度重疊了,新手確定會好奇背景色到底哪去了.
解決這個問題有好幾種方法,最簡單的一種是直接給容器元素設置高度。
ul {
height: 300px;
}
這樣背景色又回來了。可是,這種方法經常不能讓咱們滿意,由於當咱們須要容器的高度和內容自適應時,這種方法徹底無效。若是咱們再加上三個列表項,這個高度又不夠了。
召喚clearfix
如今該輪到clearfix登場了,它經過clear屬性解決了高度重疊的問題。
咱們經常會建立一個空元素(一般是div),它和浮動元素同級,而後給它設置class爲「clearfix」。回到CSS,咱們加上這樣一行樣式:
.clearfix {
clear: both;
}
這樣就解決了高度的問題。
說下原理:咱們知道當元素只包含浮動元素時,高度發生重疊(效果和高度爲0同樣),這時該元素有了一個子元素,即便它是個空元素,但它沒有浮動,並且還清除了全部浮動,因此這個空元素會出如今全部元素的下方,從而撐起了容器的高度,因而height:auto恢復正常了。
這種方法的缺點是,HTML中多了一個額外的元素,不符合語義化的思想。
新的解決方法是使用 overflow 屬性,若是你設值爲hidden 或 auto,也能夠解決高度重疊的問題。
ul {
overflow: auto;
}
這種方法更簡單也更優雅,可是還有個問題要說下,若是容器元素必須設置爲overflow: visible,你又該怎麼辦呢?
方法是首先使用 :before 和 :after 在元素內建立一些不浮動的東西,但實際上你並不但願出現任何多餘的東西,因此咱們設置一個空字符串,可是要設置display:table,這樣就建立了一個匿名單元格(是否是想起了<td></td>?),最後使用老辦法,清除浮動。
爲了兼容老版本的IE,使用它特有的zoom:1清除浮動。
/* For modern browsers */
.cf:before,
.cf:after {
content:"";
display:table;
}
.cf:after {
clear:both;
}
/* For IE 6/7 (trigger hasLayout) */
.cf {
zoom:1;
}