多是最全面最易懂的解析前端浮動的文章

寫在最前

習慣性去谷歌翻譯看了看float的解釋: css

image
其中有一句這樣寫的:

she relaxed, floating gently in the waterhtml

瞬間浮想聯翩,一個女神,輕輕地漂浮在水中。開心的拍打着水花,哇靠。。。前端

不想了,人間不值得,步入正題吧,上面美妙的畫面中,咱們能夠看到,女神仍是擠佔了水的空間,女神是浮動的。那麼來,好了,編不下去了,直接開題吧。。。api

我以爲不少人連float是啥意識都不知道,要知道不少特性的原理是和其命名的單詞或者字母有密切關聯的,不是隨便命名的。從名字中能夠看到一些當初設計的初衷。瀏覽器

找出問題是關鍵

問本身三個問題:bash

第一 浮動會形成什麼影響?

第二,如何解決這些由於浮動而形成的影響?

第三,bfc原理?
複製代碼

其實我我的理解,浮動形成的最核心的問題就是破壞了文檔流,那麼問題來了,float破壞了文檔流,爲何還要設計這個api,我查了一些資料最後才知道,這是由於當初設計float的目的是爲了能實現文字可以環繞圖片的排版功能,也就是咱們有時會納悶的一點:設置浮動後,仍是會擠佔容器中的文本內容。佈局

好比看下面這段代碼:spa

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>float實現浮動</title>
</head>
<style> .z1{ height: 200px; width: 200px; float: left; text-align: center; line-height: 200px; background: skyblue; } .fu { width: 400px; } </style>
<body>
<div class="fu clearfix">
    <div class="z1">設置了float爲left的圖片</div>
    <div class="z2">你看,我沒有被浮動哥哥擋住哦,這是一段神奇旅行,一天我趕上了白雪公主</div>
</div>
</body>
</html>
複製代碼

效果圖以下:翻譯

image

看到這,是否是有些理解了。從上圖會發現,即便圖片浮動了,脫離了正常文檔流,也覆蓋在沒有浮動的元素上了,可是其並無將文本內容也覆蓋掉,這也證明了float這個api當初被設計出來的主要目的:實現文字環繞圖片排版功能。設計

當想到這時,我忽然意識到,其餘佈局模式是什麼樣子,而後進行了實驗。去掉容器z1float屬性,增長了position屬性,代碼以下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>absolute實現浮動</title>
</head>
<style> .z1{ height: 200px; width: 200px; box-sizing: border-box; position: absolute; text-align: center; background: skyblue; padding-top: 80px; opacity: 0.8; } .fu { width: 400px; } </style>
<body>
<div class="fu clearfix">
    <div class="z1">設置了positon爲absolute的圖片</div>
    <div class="z2">你看,我被absolute哥哥擋住哦,這是一段神奇旅行,一天我趕上了白雪公主</div>
</div>
</body>
</html>
複製代碼

效果圖以下:

image

咱們能夠看到,設置absolute的容器,纔是意義上的徹底脫離正常文檔流。覆蓋在當前位置上的全部容器和文本內容之上。對比思考一下,會發現這又證實了float被設計出來的主要目的。若是能理解成這樣,我以爲對於不一樣業務上該用什麼方式清除float,或者說該用什麼來代替float,將會有個很明確的方向。

其實你會發現,absolutefloat都不會去覆蓋掉在他們以前的正常文檔流,這應該和瀏覽器渲染機制有關係,會從上到下依次渲染內容,渲染成功後,就不會由於後續元素浮動而使其被覆蓋住(不考慮使用fix等強行覆蓋的狀況)。

簡易代碼以下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>清除float浮動</title>
</head>
<style> .z1{ height: 200px; width: 200px; box-sizing: border-box; float: left; text-align: center; background: skyblue; padding-top: 80px; opacity: 0.5; } .z2 { background: yellow } .z3 { background: red; } .z4 { background: green; } .z5 { background: pink; } </style>
<body>
<div class="fu">
    <div class="z2">沒有設置任何浮動的容器,背景爲黃色</div>
    <div class="z3">沒有設置任何浮動的容器,背景爲紅色</div>
    <div class="z1">設置了浮動的元素,opacity爲0.5</div>
    <div class="z4">沒有設置任何浮動的容器,背景爲綠色</div>
    <div class="z5">沒有設置任何浮動的容器,背景爲粉色</div>
</div>
</body>
</html>
複製代碼

效果圖以下:

image

從圖中的標註和說明咱們能夠清晰的知道,float不會影響前面已經渲染好的文檔,而會影響在其後面將要渲染的文檔。那麼問題來了,怎樣才能消除由於z1的浮動而對z4,z5形成的影響呢?

首先咱們要知道,z1這個浮動形成了哪些影響,影響以下:

第一個影響:影響了z4,z5的佈局。

第二個影響:影響了父容器的高度,正常父元素的高度是自適應的,高度爲其包含的內容總高度,而內部元素的浮動形成了父容器高度塌陷。

第三個影響:父容器高度塌陷了,將會影響和父元素同級的文檔佈局。

下面的代碼能夠完美的詮釋這些影響:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>清除float浮動</title>
</head>
<style> .z1{ height: 200px; width: 200px; box-sizing: border-box; float: left; text-align: center; background: skyblue; padding-top: 80px; opacity: 0.5; } .z2 { background: yellow } .z3 { background: red; } .z4 { background: green; } .z5 { background: pink; } .z6 { color: #fff; background: black; } .z7 { color: #fff; background: blue; } .fu { /* overflow: hidden; */ } </style>
<body>
<div class="fu">
    <div class="z2">沒有設置任何浮動的容器, 背景爲黃色</div>
    <div class="z3">沒有設置任何浮動的容器, 背景爲紅色</div>
    <div class="z1">設置了浮動的元素, opacity爲0.5</div>
    <div class="z4">沒有設置任何浮動的容器, 背景爲綠色</div>
    <div class="z5">沒有設置任何浮動的容器, 背景爲粉色</div>
</div>
<div class="z6">和父級元素同級的容器, 沒有設置任何浮動, 背景爲綠色</div>
<div class="z7">和父級元素同級的容器, 沒有設置任何浮動, 背景爲綠色</div>
</body>
</html>
複製代碼

效果圖以下:

image
經過圖中的標註咱們能夠很清晰看到上面提到的三個影響,那麼影響也清晰的看到了,下面該如何去解決這些影響呢?

解決思路很重要

要解決這三個影響,須要從兩個方向思考:

第一個方向:解決父元素給其同級的元素形成的影響,我比喻成解決外部矛盾

第二個方向:解決父級元素內部的浮動元素對其同級元素的影響,我比喻成解決內部矛盾

俗話說的好,家醜不可外揚,那麼來,如今就先解決外部矛盾,怎麼解決呢,解決的思想,無非就是讓父級元素的高度再也不塌陷,把浮動元素的高度算進去。記住一個關鍵點,這時候,內部矛盾仍是存在的。好比浮動元素和其後續的同級元素有高度重疊。

解決外部矛盾

觸發bfc

第一個是觸發bfc,爲何呢,由於觸發bfc後,高度會包括浮動元素的高度。怎麼觸發呢,能夠給父級元素設置overflow:auto;對於其餘的觸發bfc方式,我就不說了,我主要說一下原理。代碼以下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>清除float浮動</title>
</head>
<style> .z1{ height: 200px; width: 200px; box-sizing: border-box; float: left; text-align: center; background: skyblue; padding-top: 80px; opacity: 0.5; } .z2 { background: yellow } .z3 { background: red; } .z4 { background: green; } .z5 { background: pink; } .z6 { color: #fff; background: black; } .z7 { color: #fff; background: blue; } .fu { overflow: hidden; } </style>
<body>
<div class="fu">
    <div class="z2">沒有設置任何浮動的容器, 背景爲黃色</div>
    <div class="z3">沒有設置任何浮動的容器, 背景爲紅色</div>
    <div class="z1">設置了浮動的元素, opacity爲0.5</div>
    <div class="z4">沒有設置任何浮動的容器, 背景爲綠色</div>
    <div class="z5">沒有設置任何浮動的容器, 背景爲粉色</div>
</div>
<div class="z6">和父級元素同級的容器, 沒有設置任何浮動, 背景爲綠色</div>
<div class="z7">和父級元素同級的容器, 沒有設置任何浮動, 背景爲綠色</div>
</body>
</html>
複製代碼

效果圖以下:

image
圖中能夠很清晰的看出,觸發父元素的bfc後,外部矛盾解決了,可是內部的矛盾尚未解決。那麼如今就開始解決內部矛盾。怎麼解決內部矛盾呢,也就是父元素內部的浮動元素的高度和後面的同級元素的高度有重疊呢。這個時候,咱們先不着急解決內部矛盾,咱們來看一下,另外一種解決外部矛盾的方式。

clear原理

給父元素增長僞元素:代碼以下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>清除float浮動</title>
</head>
<style> .z1{ height: 200px; width: 200px; box-sizing: border-box; float: left; text-align: center; background: skyblue; padding-top: 80px; opacity: 0.5; } .z2 { background: yellow } .z3 { background: red; } .z4 { background: green; /* clear: left */ } .z5 { background: pink; } .z6 { color: #fff; background: black; } .z7 { color: #fff; background: blue; } .fu { } .clearfix:after { display: block; overflow: hidden; content: '僞元素的內容哦'; clear: both; height: 0; background: slateblue; } </style>
<body>
<div class="fu clearfix">
    <div class="z2">沒有設置任何浮動的容器, 背景爲黃色</div>
    <div class="z3">沒有設置任何浮動的容器, 背景爲紅色</div>
    <div class="z1">設置了浮動的元素, opacity爲0.5</div>
    <div class="z4">沒有設置任何浮動的容器, 背景爲綠色</div>
    <div class="z5">沒有設置任何浮動的容器, 背景爲粉色</div>
</div>
<div class="z6">和父級元素同級的容器, 沒有設置任何浮動, 背景爲綠色</div>
<div class="z7">和父級元素同級的容器, 沒有設置任何浮動, 背景爲綠色</div>
</body>
</html>
複製代碼

不少人不清楚用僞元素清除浮動的原理是什麼,爲何給父元素加這個僞元素,能夠清除父元素的浮動。這裏我故意在僞元素的content寫了一些文本內容,同時加了背景色,有點像基佬色。。。


OK,先看總體效果圖吧:

image
不出意外,從上圖能夠看到,外部矛盾被解決了。這只是開始,你們眼睛盯好,繼續看下面截圖:


image
從圖中標註能夠看出,爲何僞元素要設置 display:block,繼續看下一個截圖。


image
從上圖中能夠知道,爲何 height要設置成0了。若是 content不是空字符串,那麼就會在頁面中顯示內容。但其實清除浮動時, content都會寫成空的字符串,若是 content裏面只設置成 ''空的字符,那麼 height也能夠不寫,包括 overflow也能夠不寫,寫 heightoverflow都是爲了代碼的魯棒性。不過有個很重要, content這個屬性,必需要寫,不寫 content,是無法清除浮動的。


最重要的知識點要來了,請看兩個截圖:

image
我故意讓 content顯示出來,會發現 僞元素清除浮動的核心原理實際上是在給父元素增長塊級容器,同時對塊級容器設置clear屬性,使其可以清除自身的浮動,從而正常按照塊級容器排列方式那樣排列在浮動元素的下面。同時,父元素的同級元素也會正常排列在僞元素造成的塊級元素後面,而不受浮動影響。


下面是幹掉clear屬性後的截圖:

image
發現清除浮動失敗了,其實能夠看出,給父元素增長一個僞元素來清除浮動的本質,是經過

給父元素再加一個塊級子容器,固然這個也就是父元素的最後一個塊級子容器了。同時給這個塊級子容器設置clear屬性來清除其浮動,這樣這個子容器就能排列在浮動元素的後面,同時也把父元素的高度撐起來了。那麼父元素的同級元素也能正常排列了。因此這個子容器不能有高度和內容,否則會影響父元素的佈局。

寫到這,外部矛盾的解決方式和各自的原理已經說的很清楚了。那麼內部矛盾怎麼解決呢?

其實,解決內部矛盾的原理和解決外部矛盾的第二種方式的原理是同樣的,經過給被浮動影響的第一個元素進行清除浮動,就可使後面的元素也不會受到浮動影響了。代碼以下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>清除float浮動</title>
</head>
<style> .z1{ height: 200px; width: 200px; box-sizing: border-box; float: left; text-align: center; background: skyblue; padding-top: 80px; opacity: 0.5; } .z2 { background: yellow } .z3 { background: red; } .z4 { background: green; clear:both; } .z5 { background: pink; } .z6 { color: #fff; background: black; } .z7 { color: #fff; background: blue; } </style>
<body>
<div class="fu">
    <div class="z2">沒有設置任何浮動的容器, 背景爲黃色</div>
    <div class="z3">沒有設置任何浮動的容器, 背景爲紅色</div>
    <div class="z1">設置了浮動的元素, opacity爲0.5</div>
    <div class="z4">沒有設置任何浮動的容器, 背景爲綠色</div>
    <div class="z5">沒有設置任何浮動的容器, 背景爲粉色</div>
</div>
<div class="z6">和父級元素同級的容器, 沒有設置任何浮動, 背景爲綠色</div>
<div class="z7">和父級元素同級的容器, 沒有設置任何浮動, 背景爲綠色</div>
</body>
</html>
複製代碼

效果圖以下:

image

給內部元素設置clear:both;清除浮動後,會直接解決內部矛盾和外部矛盾。可能會有人想,若是z4容器後面又有一個浮動元素呢,這裏我不想再解釋了,由於可遞歸得出原理都是同樣的,可是吧,我仍是上個代碼分析一下吧:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>清除float浮動</title>
</head>
<style> .z1{ height: 200px; width: 200px; box-sizing: border-box; float: left; text-align: center; background: skyblue; padding-top: 80px; opacity: 0.5; } .z2 { background: yellow } .z3 { background: red; } .z4 { background: green; clear:both; } .z5 { background: pink; /* clear:both */ } .z6 { color: #fff; background: black; } .z7 { color: #fff; background: blue; } .fu { overflow: auto; } </style>
<body>
<div class="fu">
    <div class="z2">沒有設置任何浮動的容器, 背景爲黃色</div>
    <div class="z3">沒有設置任何浮動的容器, 背景爲紅色</div>
    <div class="z1">設置了浮動的元素, opacity爲0.5</div>
    <div class="z4">沒有設置任何浮動的容器, 背景爲綠色</div>
    <div class="z1">設置了浮動的元素, opacity爲0.5</div>
    <div class="z5">沒有設置任何浮動的容器, 背景爲粉色</div>
</div>
<div class="z6">和父級元素同級的容器, 沒有設置任何浮動, 背景爲綠色</div>
<div class="z7">和父級元素同級的容器, 沒有設置任何浮動, 背景爲綠色</div>
</body>
</html>
複製代碼

效果圖以下幾張截圖:

父元素沒有清除浮動,外部矛盾,內部矛盾都存在

image

父元素使用bfc清除浮動,外部矛盾解決,內部矛盾還存在

image

經過給父元素中的浮動元素後面的第一個同級塊級元素設置clear清除浮動,內部矛盾解決,外部矛盾也解決。

image

對於clear還有leftright,這個就不說了,api的事情,正常both就能夠了。寫到此,差很少要結束了。最後再總結一下吧:

不一樣業務中可能須要不一樣的清除浮動的方式,不論選擇哪種方式,都避不開外部矛盾和內部矛盾,你的業務須要保留內部矛盾,只解決外部矛盾,仍是外部矛盾和內部矛盾都解決。這些得須要根據業務的特色來決定。其次,是使用bfc仍是clear仍是僞元素,使用bfc的話使用哪一種方式去觸發。這也是根據業務的特色來決定。

文末的可愛聲明:若是轉發或者引用,請貼上原連接,尊重一下熬夜完成的勞動成果😂。文章可能有一些錯誤,歡迎評論指出,也歡迎一塊兒討論。文章可能寫的不夠好,還請多多包涵。爲了前端,我也是操碎了心,人生苦短,我學前端,多一點貢獻,多一分開心~

相關文章
相關標籤/搜索