你歷來沒了解過的CSS浮動 | Design Shack

浮動究竟是作什麼呢?他們是如何影響相關元素的盒模型的呢?浮動的元素與內聯元素有什麼不一樣呢?制定浮動元素的位置的具體規則是什麼?clear屬性是如何工做的,而且它的做用是什麼?css

即便是經驗豐富的開發者也會在浮動上出錯,因此理解浮動的行爲能幫你擺脫面對CSS的不少困擾。即便你認爲你已經瞭解了關於浮動的全部知識,咱們也會深刻到你可能會學習到新知識的地步。瀏覽器

什麼是浮動?

在CSS中一些元素是塊級元素,他們會自動啓用新的一行。例如,若是你建立2個單獨的單詞段落元素,它們不會相互流入而會各自出如今單獨的一行。另外一種元素是內聯元素,它們會與以前的內容保持顯示在「一行」。舉個例子,有個錨標籤,它能夠出如今像段落這個元素以內並且不會形成任何額外的空白,也不會另起一行。佈局

改變這種佈局模型的一種方式是使用浮動,它容許給定的元素挪動到它那一行的一側,而且其餘內容向下流動。一個右浮動的元素將被推進直到它的容器的右側,而且內容會沿着它的左側向下流動,一個有浮動的元素會被挪動到左側,內容會沿着它的右側向下流動。學習

有一個經典的例子是當你將一張圖片放進一段落裏,而且想讓二者並排出現而不是堆疊。首先,咱們用HTML建立兩個元素:spa

<img src="http://lorempixum.com/200/200/" />
<p>Lorem ipsum...</p>複製代碼

僅僅這樣並不能出現咱們想要的效果。段落元素是一個塊級元素,它會獨自佔一行,因此段落和圖片會顯示在正常的文檔流。翻譯


咱們能夠經過將圖片浮動到右邊來改變顯示。這種CSS很是基礎:3d

img {
    float: right;
    margin: 20px;
}複製代碼

有了這段代碼,咱們的圖片會被挪到它這一行的右邊,段落文字會在它的左邊向下流動。code


有趣的是,這張圖片在被浮動時,咱們其餘的內容將會盡量的嘗試圍繞它出現。若是改變咱們容器的大小或者將瀏覽器窗口變窄,文本只是簡單的自我重排而不會觸碰到圖片。
cdn


這種盒子是怎麼工做的

可能你對這種行爲已經有了很好的理解。然而,爲了更充分利用浮動,你須要更深層次的理解這兩個元素之間的交互。例如,咱們怎麼在段落和圖片之間添加額外的空白?你可能認爲這樣可行xml

p {margin: 20px;}複製代碼

然而,這不會在圖片和段落之間產生甚至一像素額外的空白。相反,咱們爲圖片應用了這些空白:

img {margin: 20px;}複製代碼


你應該問本身一個問題,「爲何?」爲何增長段落的margin不會在圖片和段落之間增長空白?由於咱們沒有掌握屬於段落的盒模型。

若是你曾懷疑你的佈局是怎麼在基本層面上工做的,試着應用一兩個邊框來看看將發生什麼。若是咱們在這個段落上這樣作,結果可能會讓你驚訝,

p {
    border: solid 1px black;
}複製代碼


正如你所看到的,圖片實際上在段落的盒子裏面!這解開了咱們的邊界空白疑惑。咱們給段落添加的任何空白都被應用到了圖片的右邊,這就是爲何在圖片和段落之間不會增長空白。

若是咱們想改變這種行爲,讓段落再也不圍繞圖片,咱們可讓段落浮動到左邊,並給他指定寬度(沒有表示寬度,段落將會是100%的寬,將不會佈置在圖片旁邊)。


瘋狂的浮動規則

如今咱們知道了浮動是作什麼的,以及它是怎麼影響所涉及的元素的盒子的。讓咱們繼續討論另外一塊可能不少開發者都不瞭解的信息:控制浮動元素位置的規則。

一般在圖片集或者特徵列表中開發人員會用浮動來控制列表項的位置。咱們建立一個簡單的純圖片的列表來看看這是怎麼工做的。

<ul>
  <li><img src="http://placehold.it/100x100&text=1"/></li>
  <li><img src="http://placehold.it/100x150&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/100x150&text=6"/></li>
  <li><img src="http://placehold.it/100x100&text=7"/></li>
</ul>複製代碼

默認狀況下,全部的列表項都顯示在一個大的垂直棧裏,這意味着它們是塊級元素。即便圖片是內聯元素,它們也被它們的父塊級元素列表項控制。爲了解決這種問題,咱們要使列表項左浮動。當一行中多個元素被浮動,它們會產生同內聯元素的流相似的效果。然而,正如咱們所看到的,有一些關鍵的區別。

li {
    float: left;
    margin: 4px;
}複製代碼

如今,若是咱們全部的圖片都是一樣的高度,這只是一個很是普通的例子。這個結果看起來就像是一個簡單的從左到右按順序排列的圖片集:


然而,咱們的圖片並非一樣的高度,一些高100px,其餘的高150px。這會形成很是古怪的結果。


我第一次看到這種結果的時候感到很困惑。這裏的世界到底發生了什麼?爲何圖片4會像那樣在右邊?難道它不該該本身試着儘量讓本身浮動到左邊?若是咱們去掉這些列表項的浮動,用display:inline來替代,結果是大相徑庭的。

li {
  display: inline;
}複製代碼


跟最開始相比,這個例子的不一樣之處在於圖片的默認狀態是沿着它們的底部邊緣垂直對齊。這會使它們同以前的例子看起來很是不同,可是咱們可使用一行CSS來解決這個問題:

img{
    vertical-align: top;
}複製代碼

如今看起來比較像浮動示例了,只會顯示有一個可預測順序的內聯列表項。當x軸沒有下一項的空間時,它會返回到下一行的左側。


因此,咱們的浮動圖片集爲何沒有像這樣顯示呢?爲何浮動的列表項被奇怪的巫術控制?

九條規則

事實證實,CSS規範列出了九條規則來規定浮動的行爲。這個清單的問題在於即便是被寫出來了,也只有無聊的人才能去理解它。這裏是一個從其中一個規則中引用的:

「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將浮動表現翻譯成英文並總結了九條規則,看起來更簡單一點。

  1. 浮動元素會被推到他的容器的邊緣。
  2. 任何浮動元素都會出如今他以前的浮動元素的旁邊或是下方。若是元素都是左浮動,那麼第二個元素將會出如今第一個元素的右邊,若是都是右浮動,第二個元素會出如今第一個元素的左邊。
  3. 左浮動的盒子不能出如今右浮動盒子的右邊。
  4. 浮動元素不能高過他的容器的上邊緣(當涉及到塌陷的邊距這將會更復雜,請參考最初的規則)。
  5. 浮動元素不能比前一個塊級元素或浮動元素高。
  6. 浮動元素不能高過前一行內聯元素。
  7. 靠着另外一個浮動元素的浮動元素不能超出本身的父容器邊緣。
  8. 一個浮動的盒子必須儘量的高的放置。
  9. 一個左浮動的盒子必須儘量左的放置,一個右浮動的盒子要儘量的右的放置。儘量高的位置的優先級比左右高。

咱們能夠看作這些大多數都是常識,但他們也要被明確聲明出來以便每一個人在每一個瀏覽器上看到一樣的頁面。基本上來講,這種狀況的要點就是浮動元素會被指定到具體的邊緣(左或者右),沒有過多的要求。除非在他以前有另外一個浮動元素,他就會與那個浮動元素相鄰。

真正讓咱們感到困惑的是最後的規則,它代表了浮動元素儘量的保持高的位置,而且垂直定位規則比水平的左右規則在將元素推到邊緣時優先級更高。

在咱們以前的例子中,數字2的圖片把行的高度撐開了,以致於在數字3圖片以後仍然有一些垂直的空間使得數字4圖片擠了進去。即便是考慮到這些規則,這種模式也不容易被預測到。

請記住,當你有一個浮動元素時,後面緊接着的浮動元素至少要佔據與以前一樣或者更多的垂直高度來打破這一行使得流動下移。


浮動順序

關於咱們在這裏提出的規則的最後一點。第2條規則會對那些浮動元素產生有趣的影響。假設,咱們有六張從一到六的數字圖片,以下:

<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>複製代碼

若是咱們將這些圖片浮動到左邊,他們會按順序出現,從一開始直到六,從左到右,從上到下。可是,若是咱們將這些圖片右浮動。


正如你所看到的,第一張圖片被放到了最右邊的位置。相似的,在換行時,第四張圖片也被放置到了右邊。這就是爲何你不多看到有人將導航元素右浮動。弄出了這樣螺旋狀的順序就須要HTML結構作出不受歡迎的改變來解決。

清除浮動

浮動對於完成一些相似於創造內容列這樣的佈局頗有用。可是,一旦浮動被聲明,他們就會對剩下的文檔的產生一些或許你喜歡或者不喜歡的影響。例如,咱們想在咱們以前說起的那種左浮動的列表塊以後加一個段落。


結果或許並非你所指望的:

這裏的結果是使用clear屬性,讓沒有浮動的元素能夠出如今他所應用的元素給定的一側。例如,好比咱們在咱們的小圖庫列表的第二項添加clear: left.

ul li:nth-child(2) {
  clear: left;
}複製代碼

這段代碼告訴瀏覽器,第二項的頂部必須位於他以前的任意左浮動項的底部之下(在這個例子中,是第一項)。若是咱們將全部元素都右浮動,咱們就要使用clear: right。


請注意,在此以後,剩下的浮動元素都會保持他們的位置。由於他們仍然被設置的左浮動,清除屬性並無取消他們的表現。這意味着咱們的問題不能經過清除列表任意項的浮動來解決。


相反,必須被清除的是段落元素,他是一個沒有被浮動的塊級元素。這將確保他會出如今浮動元素的下面而不是旁邊。

p {
    clear: both;
}複製代碼

從技術上來說,咱們只須要清除這裏的左浮動,可是當一個開發者想要確保清除全部浮動時,一般會看到clear的值被設置爲both。這個變化能很是好的解決咱們的問題。


浮動的怪癖和清除浮動

當一個給定的元素只包含浮動元素時會產生奇怪的現象:父元素的高度會坍塌。舉例說明,假設咱們想在全部示例中的無序列表給定背景色。若是列表的元素沒有被浮動,咱們就只須要應用一下CSS來添加背景。

ul {
    background: gray;
}複製代碼

正如你所看到的,定義的無序列表的框已經變成了灰色,而且列表中的每一項都堆疊在一塊兒。


然而,在第二個例子中,咱們浮動了全部列表項,UL只包含了浮動的元素,致使它的高度坍塌,這會讓新手開發者驚訝它的背景色到底發生了啥。


有一些方法能夠解決這個問題,最簡單容易的方法是爲無序列表的父元素明確指定高度。

ul {
  height: 300px;
}複製代碼


正如你所看到的,這的確能讓咱們的背景從新被填滿。然而,從長遠來看這並非一個可取的辦法,若是高度是基於內容自動計算的話。若是咱們要添加三個或者更多的圖片到列表庫裏,高度就會不足。

爲了解決而清除浮動

這裏術語clear fix,也叫clearfix,就開始發揮做用啦。清除浮動經過使用clear屬性來解決高度坍塌的問題。

開發者在他們的HTML中建立一個跟浮動元素同級的空元素(經常是一個div),而後給空容器添加一個命名爲clearfix的class。咱們回到CSS中,給clearfix添加清除浮動的屬性。

.clearfix {
  clear: both;
}複製代碼

馬上就解決了高度坍塌的問題:


根據咱們已經學過的能夠知道爲何這個方法能夠解決咱們的問題。高度坍塌的緣由是由於父元素只包含了浮動元素的,如今他有了一個子元素,儘管這個子元素是空的,可是它沒有浮動,因此高度會再次跟預期同樣自動生成。

這個方法有個問題是,沒有人喜歡HTML中額外的醜陋的元素。它根本不是語義的,意味着它不能清晰的傳遞頁面的層次結構。

新的解決方案是利用overflow屬性,這個屬性控制了超出其包含框邊界的內容的功能。若是你將父項目的overflow設置爲hidden或者auto,也能解決高度坍塌。

ul {
  overflow: auto;
}複製代碼


這絕對是解決高度坍塌問題的最簡單、最優雅的方案,也應該是你的方案。雖然這麼說,那在某種狀況,你想將元素的overflow設置爲visible,你又應該怎麼作呢?

這樣的結果可使用Nick Gallagher的微型清除浮動hack,他使用了一下天才般的CSS來解決這個問題。首先,他是使用的:before以及:after來添加一些內容,咱們能夠用來爲父元素建立一些不浮動的元素。然而,你不想在這裏使用真實的內容,因此咱們使它爲空而且設置display爲table來建立一個匿名框(空的並且不佔空間)最後使用咱們的老朋友clear。它建立了一個不可見的塊級元素來解決高度坍塌的問題而且沒有添加額外的HTML。IE的老版本須要本身修復。

/* For modern browsers */
.cf:before,
.cf:after {
    content:"";
    display:table;
}

.cf:after {
    clear:both;
}

/* For IE 6/7 (trigger hasLayout) */
.cf {
    zoom:1;
}複製代碼

結論

文章中,咱們討論了大量的信息,包括基礎和複雜的。咱們從最開始討論如何浮動,以及他們在基本層級是如何工做的,而後是如何設置元素的浮動來影響元素所涉及的盒子邊框,讓你找出怎麼樣工做才能根據你想的那樣得到邊距。

接着,咱們討論了浮動元素的基本規則,並得出了一些有趣的結論,就是不一樣高度的浮動元素如何定位,以及右浮動的元素怎麼以相反的順序出現。

若是在閱讀本篇文章以前,浮動讓你感受到很困惑,那麼開始閱讀吧。它們最開始就迷惑了咱們。但願你如今以及瞭解了浮動是怎麼工做的,以及知道如何使用它們來實現你想要的佈局。若是你以爲這些信息有幫助,請在下面留下評論讓咱們知道。

相關文章
相關標籤/搜索