前端重構正規化之 float layout

ScalaCool發表於2019-03-01

本文由 Rhyme、Captain 發表在 ScalaCool 團隊部落格。

如果讓我用一句話來總結浮動佈局,就是浮動佈局是一種排隊的藝術。你可以向左排隊、向右排隊,關鍵在於你如何去組織他們。如果你去看float的屬性值就會發現它最為重要的無非就是leftright,而他們顧名思義就是向左或向右進行浮動。在我們的網頁佈局中,凡是涉及到水平佈局的,大都會涉及到浮動,例如我們的導航欄,水平方向的網頁佈局,他們都或多或少的在水平方向進行向左或向右的排隊。因此,如果說網頁的佈局是擺放一個個盒子的藝術,那麼浮動佈局就是在水平方向擺放盒子的藝術。

那麼我們為什麼要在水平方向進行佈局呢?這就猶如多一個遊戲規則與少一個遊戲規則的區別。我們可以用我們小時候玩過的堆積木遊戲來做一個形象的比喻。普通的佈局就如同一個盒子疊著一個盒子的遊戲規則,我們在同一個水平方向只能放一個盒子,因此只能達到下圖中的效果

前端重構正規化之 float layout

浮動佈局允許你在同一個水平方向可以放置多個盒子,共同組成一個大盒子,也就是說原來的一個盒子不再是一個簡單的盒子,它的內部可以由各種複雜的佈局組成, 因此你就可以很輕易得實現下圖中的效果,雖然你乍一看下方的佈局好像有違遊戲規則,但是隻要你細心一點進行下圖中的劃分,就可以發現其實它的最終的規則沒有變,依舊是普通佈局中的一個盒子疊一個盒子的遊戲規則,只不過是它的盒子結構變得更豐富,功能更加強大了了而已。因此明白了這一點,你也就能明白了為什麼要有浮動佈局,因為,它可以實現更多樣的佈局來實現各種各樣的需求。

前端重構正規化之 float layout

好,現在你對這個積木遊戲有個一定的瞭解,也對浮動佈局有了一個總體的認識,但是我們知道一個厲害的遊戲玩家,並不是因為他比其他人要有天賦,大部分原因是因為他對遊戲規則更為了解。因此要想成為一個厲害的前端玩手,你就需要對前端的遊戲規則更為了解。所以,接下來就讓我們正式走近這個積木遊戲的大門,盡情得探索和玩耍吧!

1. 網頁中的地基-文件流

首先作為積木遊戲的入門,我們需要對最基礎的遊戲規則做個瞭解,而這個最基礎的遊戲規則在網頁設計中被稱作「文件流」。你可以把積木遊戲中的一個個盒子看做是我們頁面中的一個個標籤,例如<div></div>標籤就可以看做是一個盒子。但是有一點不同的是,在我們的網頁中,有兩種型別的盒子,一種是被稱為塊元素的盒子,類似div,另一種是被稱為內聯元素的盒子,例如span。這兩種型別的盒子在文件流中或脫離文件流的時候會表現出不同的性質,直接影響了我們的網頁佈局。所以接下來我們將介紹這兩種型別的盒子在文件流中具有什麼特點?至於脫離文件流之後的特點,會在後面「元素的變性」那一節中講述。

首先我們需要了解什麼是文件流?

如果說把一個複雜的網頁想象成一棟漂亮的樓房,那麼這棟樓的地基就是文件流。上面的樓房就是各種定位和浮動的綜合體。(定位顧名思義就是負責元素在網頁中的位置,具體會在後面的系列中做詳細地介紹)

我們所建立的元素預設都在文件流中。例如以下程式碼中的divh2標籤都處於文件流中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>float layout</title>
</head>
<body>
<div>
    <h2>我處在文件流中</h2>
</div>
</body>
</html>
複製程式碼

瞭解了文件流,接下來我們將介紹兩種型別的盒子(塊元素與內聯元素)在文件流中具有什麼特點

霸道的盒子-塊元素

div,p等標籤被稱為塊元素

  1. 塊元素在文件流中很是霸道,哪怕它的實際大小隻有100px,但是它還是獨佔一行,且自上而下排列

前端重構正規化之 float layout

示例程式碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>霸道的盒子-塊元素</title>
    <style>
        .box {
            width: 100px;
            height: 100px;
        }
        .box1 {
            background-color: aqua;
        }
        .box2 {
            background-color: aquamarine;
        }
        .box3 {
            background-color: bisque;
        }
    </style>
</head>
<body>
<div class="box box1"></div>
<div class="box box2"></div>
<div class="box box3"></div>
</body>
</html>
複製程式碼
  1. 霸道的塊元素在文件流中預設寬度是父元素的100%,它的width屬性值預設為auto,當元素的width屬性值為auto時,此時修改元素左右內邊距不會修改該元素本身的寬度大小,而是會自動修改該元素的寬度,來適應內邊距,下圖中綠色的塊元素就新增了一個左100px的內邊距,你會發現綠色的塊元素的寬度大小並沒有改變,而是自動調整了寬度來適應內邊距的改變

前端重構正規化之 float layout

示例程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>霸道的盒子-塊元素</title>
    <style>
        .box1 {
            height: 100px;
            background-color: aqua;
        }
        .box2 {
            /*新增左內邊距不會影響該元素的寬度大小*/
            padding-left: 100px;
            height: 100px;
            background-color: aquamarine;
        }
        .box2-child {
            width: 100px;
            height: 100px;
            background-color: bisque;
        }
    </style>
</head>
<body>
<div class="box1"></div>
<div class="box2">
    <div class="box2-child">

    </div>
</div>
</body>
</html>
複製程式碼
  1. 塊元素在文件流中的高度可以說是終於沒有那麼霸道了,它的高度預設是由它裡面的內容撐開的

前端重構正規化之 float layout

示例程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>霸道的盒子-塊元素</title>
    <style>
        .box1 {
            background-color: aqua;
        }
    </style>
</head>
<body>
<div class="box1">a</div>
</body>
</html>
複製程式碼

最後總結一下塊元素文件流中的特點:

  1. 塊元素很霸道,哪怕自身大小隻有100px,它也會獨佔一行
  2. 塊元素的寬度預設是父元素的100%,width屬性值為auto,會自動調整寬度
  3. 塊元素的高度是它唯一不那麼霸道的地方,預設被裡面的內容撐開

Tips: 一定要注意是在文件流中,這點對於之後理解浮動佈局特別重要。

最環保的盒子-內聯元素

spana等標籤屬於內聯元素

  1. 相比於塊元素的霸道,內聯元素則要節約環保很多,它在文件流中僅佔自身大小,也就是說寬高預設都被其中的內容撐開,且從左向右排列

前端重構正規化之 float layout

示例程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>最環保的盒子-內聯元素</title>
    <style>
        .box1 {
            background-color: aqua;
        }
        .box2 {
            background-color: aquamarine;
        }
        .box3 {
            background-color: yellow;
        }
    </style>
</head>
<body>
<span class="box1">a</span>
<span class="box2">a</span>
<span class="box3">a</span>
</body>
</html>
複製程式碼
  1. 內聯元素不能設定寬和高,也就是說給他們設定width或者height屬性是沒有用的,你看它們是有多節約,給它們它們都不要一點多的。注意觀察示例中的程式碼,設定了寬和高是失效的

前端重構正規化之 float layout

示例程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>最環保的盒子-內聯元素</title>
    <style>
        .box1 {
            /*不能給內聯元素設定寬和高*/
            width: 100px;
            height: 100px;
            background-color: aqua;
        }
    </style>
</head>
<body>
<span class="box1">a</span>
</body>
</html>
複製程式碼
  1. 一行中放不下時,內聯元素會自動在下一行從左向右排列

前端重構正規化之 float layout

最後我們一起來總結一下內聯元素文件流中的特點

  1. 內聯元素很環保,只佔用元素本省的大小,從左向右排列
  2. 給內聯元素設定寬高是無效的,它依舊只佔用元素本省的大小
  3. 一行中放不下時,內聯元素會自動在下一行從左向右排列

Tips: 這裡再強調一遍,以上都是在文件流中的特點,這點對於之後理解浮動佈局特別重要。因為,元素浮動之後會脫離文件流,以上這些約束也就不存在了

2.初見浮動

我們已經解讀了文件流的遊戲規則,因此我們可以很輕易得用三個塊元素實現以下的效果

前端重構正規化之 float layout

但是在我們網頁設計中經常會有這樣的需求,三個div在同一行的佈局效果。我們可以清晰得分析出以下圖片是三個div佈局的水平排列。因為在網頁設計的時候我們大都採用div來進行網頁的佈局。

前端重構正規化之 float layout

因此我們就要解決這個問題,如何讓3個div塊元素水平排列?

前端重構正規化之 float layout

這個時候我們就要思考既然塊狀元素在文件流中獨佔一行,達不到我想要的效果,那如果我讓塊狀元素脫離文件流,是不是就沒有這個限制了呢?答案確實如此,以上的效果,就是通過為div塊元素設定浮動屬性float:left來使得這些塊元素脫離文件流向左浮動

補充:脫離文件流可以理解為在原有的地基上新建一層樓進行設計,新建的樓層不完全遵守地基中的遊戲規則,可以使得塊狀元素不再獨佔一行,具體的會在之後進行介紹

以上例項的程式碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>測試浮動佈局</title>
    <style>
        .box{
            width: 100px;
            height: 100px;
        }
        .box1{
            background-color: aqua;
        }
        .box2{
            background-color: red;
        }
        .box3{
            background-color: black;
        }
    </style>
</head>
<body>
<div class="box box1" style="float: left"></div>
<div class="box box2" style="float: left"></div>
<div class="box box3" style="float: left"></div>
</body>
</html>
複製程式碼

3. 解讀浮動的遊戲規則

到這裡你已經瞭解了最基礎的遊戲規則-文件流,也對浮動佈局有了一個初步的認識,但是我們要想在地基之上搭建出漂亮的房子,還需要進一步的解讀浮動的遊戲規則

3.1 元素的層級

浮動使得元素脫離了文件流,可以理解元素是在文件流(地基)之上進行的活動。明白了這一點,你就可以明白接下來的這句話:浮動的元素對文件流(地基)中的元素是不可見的,因為它脫離了地基,位於地基之上。

浮動是在地基之上進行的活動,那麼它難免會帶來一個問題,就是如果浮動元素與地基上原有的元素或者別的脫離文件流的元素重疊了,這個時候應該怎麼辦呢?到底是誰說了算呢?別急,你想到的,他們也都想到了,並且定好了一系列的遊戲規則。而我們作為玩家,只要知道這些規則的存在,並且學以致用就可以了。我們這一節所講的「元素的層級」講的就是這些規則。

首先在網頁中元素的歸屬可以大致分為兩種,一種是在文件流中,另一種是不在文件流中,也就是脫離文件流。在文件流中的元素屬於低層級,脫離文件流的元素屬於高層級。那顧名思義,高層級的元素會蓋住低層級的元素,那展現在視覺效果上就是蓋住的那一部分我只能看見高層級元素,看不見低層級元素。而浮動佈局是一種脫離文件流的藝術,因此浮動元素屬於高層級。但是這也只解決了一個問題,就是文件流與非文件流的元素層級的問題,那非文件流的元素之間呢,如果它們覆蓋了,又是什麼樣的遊戲規則呢?

首先所有非文件流的元素也就是脫離文件流的元素在層級上的地位都是相同的。具體的覆蓋規則有兩條

  1. z-index屬性值大的覆蓋屬性值小的
  2. z-index屬性值一樣的情況下,後面的元素蓋住前面的元素

接下來是一些示例,可以加深你對以上這些結論的理解

結論1:浮動元素處於高層級,會覆蓋處於低層級的文件流元素

前端重構正規化之 float layout

示例程式碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>元素層級</title>
    <style>
        .box1{
            float: left; // 注意這裡設定了浮動屬性
            width: 100px;
            height: 100px;
            background-color: aqua;
        }
        .box2{
            width: 200px;
            height: 200px;
            background-color: red;
        }
    </style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
</body>
</html>
複製程式碼

結論2:脫離文件流的元素都處於高層級,它們地位是相等的,覆蓋規則為:後面的元素會覆蓋前面的元素

前端重構正規化之 float layout

示例程式碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>測試浮動佈局</title>
    <style>
        .box1 {
            float: left; // 開啟浮動定位,元素處於高層級2
            width: 100px;
            height: 100px;
            background-color: aqua;
        }

        .box2 {
            position: absolute; // 開啟絕對定位,元素處於高層級2
            top: 50px;
            left: 50px;
            width: 100px;
            height: 100px;
            background-color: red;
        }

        .box3 {
            position: relative; // 開啟相對定位,元素處於高層級2
            left: 100px;
            top: 100px;
            width: 100px;
            height: 100px;
            background-color: black;
        }
    </style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
</body>
</html>
複製程式碼

結論3:脫離文件流的元素可以設定z-index屬性來提升自己的層級,z-index屬性值越大的越優先顯示,預設為0

前端重構正規化之 float layout

示例程式碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>測試浮動佈局</title>
    <style>
        .box1 {
            float: left; // 開啟了浮動定位,元素處於層級2
            z-index: 1;  // 設定z-index 優先順序為1 
            width: 100px;
            height: 100px;
            background-color: aqua;
        }

        .box2 {
            position: absolute; // 開啟了絕對定位,元素處於層級2
            z-index: 2; // 設定z-index 優先順序為2
            top: 50px;
            left: 50px;
            width: 100px;
            height: 100px;
            background-color: red;
        }

        .box3 {
            position: relative; // 開啟了相對定位,元素處於層級2
            z-index: 1; // 設定z-index 優先順序為1
            left: 100px;
            top: 100px;
            width: 100px;
            height: 100px;
            background-color: black;
        }
    </style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
</body>
</html>
複製程式碼

補充:

  1. z-index屬性的設定只對開啟浮動或定位的元素有效
  2. 絕對定位:元素相對於最近的定位祖先元素進行定位
  3. 相對定位:元素相對於元素原先在文件流中的位置進行定位

最後,我們來總結一下元素的層級關係:

  1. 脫離文件流的元素處於高層級,文件流中的元素屬於低層級,高層級的元素會覆蓋低層級的元素
  2. 浮動會使得元素脫離文件流,因此浮動的元素會覆蓋文件流中的元素
  3. 脫離文件流的元素地位都是相等的,都屬於高層級,具體覆蓋規則為:
    1. z-index相同時,後面的元素覆蓋前面的元素
    2. z-index不同時,優先顯示z-index屬性值大的元素

3.2 浮動的邊界

浮動會使得元素脫離文件流,儘可能地向左上(float:left)或右上(float:right)浮動,然而你浮動歸浮動,那你什麼時候才會停止浮動呢?這個就是我們接下來要討論的話題

3.2.1 飛不出如來佛祖的掌心

浮動元素不會超過它的父元素的邊界,下圖中紅色的浮動元素不會超過body父元素的邊界,藍色的浮動元素不會超過黃色的父元素

前端重構正規化之 float layout

示例程式碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>浮動的邊界</title>
    <style>
        body {
            background-color: antiquewhite;
        }

        .father {
            width: 200px;
            height: 200px;
            background-color: yellow;
            margin: 0 auto;
        }

        .box1 {
            float: left;
            width: 100px;
            height: 100px;
            background-color: red;
        }

        .box2 {
            float: right;
            width: 100px;
            height: 100px;
            background-color: aqua;
        }
    </style>
</head>
<body>
<div class="box1">

</div>
<div class="father">
    <div class="box2">

    </div>
</div>
</body>
</html>
複製程式碼

3.2.2 不能超隊

浮動元素在浮動過程中遇到其他浮動元素就要停止浮動,這個時候的隊伍就像在排隊一樣

前端重構正規化之 float layout

示例程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>測試浮動佈局</title>
    <style>
        .box1 {
            float: left;
            width: 100px;
            height: 100px;
            background-color: aqua;
        }

        .box2 {
            float: left;
            width: 100px;
            height: 100px;
            background-color: red;
        }

        .box3 {
            float: left;
            width: 100px;
            height: 100px;
            background-color: black;
        }
    </style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
</body>
</html>
複製程式碼

以下是一行浮動元素的溢位情況,可以看到它們在一行裝不下的時候會進行換行浮動

前端重構正規化之 float layout

示例程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>不能超隊</title>
    <style>
        .box {
            float: left;
            width: 100px;
            height: 100px;
            background-color: aqua;
            border: 1px solid black;
        }
    </style>
</head>
<body>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</body>
</html>
複製程式碼

在以下示例中,三塊元素都是浮動元素,前兩塊向左浮動,黑色的向右浮動,你會發現即使第一行有足夠的空間,但是第三塊黑色的浮動元素就是上不去,原因還是那句話不能插隊,也就是不能超過兄弟元素

前端重構正規化之 float layout

示例程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>不能超隊</title>
    <style>
        .box1 {
            float: left;
            width: 600px;
            height: 100px;
            background-color: aqua;
        }

        .box2 {
            float: left;
            width: 600px;
            height: 100px;
            background-color: yellow;
        }

        .box3 {
            float: right;
            width: 100px;
            height: 100px;
            background-color: black;
        }
    </style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
</body>
</html>
複製程式碼

3.2.3 被牆了

浮動元素不能超過前面的文件流塊狀元素,我們檢視示例程式碼,可以發現浮動元素在原始碼中的結構位於文件流塊狀元素之後,解決辦法可以將它們在程式碼結構上交換位置即可

前端重構正規化之 float layout

示例程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>被牆了</title>
    <style>
        .box1 {
            height: 100px;
            background-color: yellow;
        }
        .box2 {
            float: left;
            width: 100px;
            height: 100px;
            background-color: aqua;
        }
    </style>
</head>
<body>
    <div class="box1"> // 文件流塊狀元素

    </div>
    <div class="box2"> // 浮動元素

    </div>
</body>
</html>
複製程式碼

交換位置之後的效果如下

前端重構正規化之 float layout

示例程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>交換位置</title>
    <style>
        .box1 {
            height: 100px;
            background-color: yellow;
        }
        .box2 {
            float: left;
            width: 100px;
            height: 100px;
            background-color: aqua;
        }
    </style>
</head>
<body>
    <div class="box2"> // 浮動元素

    </div>
    <div class="box1"> // 文件流塊狀元素

    </div>
</body>
</html>
複製程式碼

最後讓我們來總結一下浮動的邊界:

  1. 浮動的元素飛不出如來佛祖的掌心,這裡的如來佛祖指的是它的父元素
  2. 浮動元素之間得排好隊,不能隨便插隊
  3. 浮動元素不能前面的文件流塊狀元素

3.3 元素變性

在之前我們有詳細介紹過元素在文件流中的性質,然後,元素在脫離文件流之後性質會發生很大的改變,接下來就讓我們來看看元素都發生了哪些改變,我們將分別從塊元素和內聯元素說起

3.3.1 塊狀元素

塊狀元素在文件流中的特點:獨佔一行,寬度為父元素的100%,高度被內容撐開

塊狀元素浮動之後的特點:寬度和高度都被內容撐開,但是可以設定寬和高

前端重構正規化之 float layout

示例程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>元素變性</title>
    <style>
        .box1 {
            background-color: aqua;
        }

        .box2 {
            float: left;
            background-color: yellow;
        }

    </style>
</head>
<body>
<div class="box1">a</div>
<div class="box2">a</div>
</body>
</html>
複製程式碼

3.3.2 內聯元素

內聯元素在文件流中的特點:不能設定寬度和高度,寬度和高度都被內容撐開

內聯元素浮動之後的特點:可以設定寬度和高度,寬度和高度依舊是被內容撐開

前端重構正規化之 float layout

示例程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>元素變性</title>
    <style>
        .span1 {
            width: 100px;
            height: 100px;
            background-color: yellow;
        }
        .span2 {
            float: left;
            width: 100px;
            height: 100px;
            background-color: aqua;
        }
    </style>
</head>
<body>
<span class="span1">a</span>
<span class="span2">a</span>
</body>
</html>
複製程式碼

最後讓我們總結一下元素的變性:

浮動之後,會改變元素的在文件流中的性質,不管是塊狀元素還是內聯元素,最終都會變成一個塊狀元素和內聯元素的綜合體:不獨佔一行,可以設定寬和高,寬高預設被內容撐開

4. 副作用-清除浮動

任何東西都有好與壞,我們之前瞭解了那麼多浮動元素的特點,也瞭解了因為浮動帶來的種種變化,然而變化歸變化,它也會帶來一些問題,這些問題就是我們接下來要解決的所謂的副作用,在這裡我們只講一個最重要的副作用,解決了它在我們的日常開發中就不會有太大問題了,至於其他副作用,個人建議,你只要慢慢從實踐中體會積累就行了

4.1 高度塌陷

浮動具有副作用-高度塌陷,一般我們需要手動的消除浮動帶來的副作用

舉一個實際的例子,浮動經常用在導航欄的佈局中,例如以下的水滴微信平臺的導航欄,其中的導航選項很明顯都採用了浮動佈局。

前端重構正規化之 float layout

我們先使用瀏覽器的審查功能來看下清除浮動之後的,也就是正常的效果,我們可以看到此時的header佔據的大小為下圖中的陰影部分,將浮動元素(導航選項)包裹在裡面,也就是沒有因為浮動失調父元素的高度

前端重構正規化之 float layout

而在我們去掉浮動之後,我們可以發現header的高度變為了圖中的那麼一小塊陰影,沒有將浮動元素(導航選項)包裹在裡面,浮動元素的父元素header失去了原有的高度,這就是我們現在討論的高度塌陷問題

前端重構正規化之 float layout

高度塌陷會帶來很多問題,最明顯的就是會影響頁面的佈局,例如以上例子中,當我發生在導航欄發生高度塌陷之後,就會導致下方的頁面元素集體上移,甚至會覆蓋導航欄

以下是正常的佈局,可以發現下面陰影部分的佈局沒有影響導航欄

前端重構正規化之 float layout

以下是發生高度塌陷的佈局,可以發現導航欄被下面的佈局影響

前端重構正規化之 float layout

4.2 解決方案

我們管高度塌陷的解決方案稱作清除浮動,也就是清除浮動帶來的副作用

以下是未進行浮動之前,沒有發生高度塌陷

前端重構正規化之 float layout

示例程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>高度塌陷之前</title>
    <style>
        .box {
            border: 5px solid black;
        }
        .float-child {
            width: 100px;
            height: 100px;
            background-color: aqua;
        }
        .others {
            height: 100px;
            background-color: yellow;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="float-child">

        </div>
    </div>
    <div class="others">

    </div>
</body>
</html>
複製程式碼

這是我們進行浮動之後的情況,你可以看到在元素浮動之後對我們的佈局產生了副作用,浮動元素的父元素髮生了高度塌陷,只留下黑色的邊框,下方的佈局往上偏移

前端重構正規化之 float layout

示例程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>發生高度塌陷</title>
    <style>
        .box {
            border: 5px solid black;
        }
        .float-child {
            float: left; // 浮動
            width: 100px;
            height: 100px;
            background-color: aqua;
        }
        .others {
            height: 100px;
            background-color: yellow;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="float-child">

        </div>
    </div>
    <div class="others">

    </div>
</body>
</html>
複製程式碼

接下來是我們成功清除浮動帶來的副作用之後的例子,我們可以發現父元素的高度塌陷沒有了,彷彿父元素被裡面的浮動元素撐開一樣。

這個清除浮動方法的關鍵在於以下這個結論的應用:

一個元素的高度總是由最後一個非浮動子元素絕定的,至於其中原理,可以自己去實踐一下,很多時候關於前端並沒有那麼多為什麼,大部分時候我們只要記住怎樣做最好就可以了

為什麼說下面這個清除浮動的方法是最好的呢?首先我們評判一個解決方法的好壞的標準是:能解決原有的問題,不會帶來新的問題。以下這個方法既解決了高度塌陷的問題嗎,又通過:after偽類解決了語義化的問題,很好地符合以上的標準。並且在實際開發中,以下這種方法也是我們用的最多的一種。

/*清除浮動*/
.float-father:after {
    content: "";
    display: block;
    clear: both;
}
複製程式碼

前端重構正規化之 float layout

示例程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>解決高度塌陷</title>
    <style>
        .float-father {
            border: 5px solid black;
        }
        /*清除浮動*/
        .float-father:after {
            content: "";
            display: block;
            clear: both;
        }

        .float-child {
            float: left;
            width: 100px;
            height: 100px;
            background-color: aqua;
        }

        .others {
            height: 100px;
            background-color: yellow;
        }
    </style>
</head>
<body>
<div class="float-father">
    <div class="float-child">

    </div>
</div>
<div class="others">

</div>
</body>
</html>
複製程式碼

總結,在對元素實施浮動操作之後,一定要考慮清除浮動帶來的副作用-高度塌陷

5. 實戰-最佳實踐

行之踐,則無敵,接下來就讓我們動手實踐一個簡單的頁面佈局

前端重構正規化之 float layout

示例程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>最佳實踐</title>
    <style>
        ul {
            /*取出列表的預設樣式*/
            list-style: none;
        }

        li {
            /*為導航項設定向左浮動*/
            float: left;
            /*將行高設定成與父元素一樣高,可以實現垂直居中的效果*/
            line-height: 50px;
        }
        /*清除浮動*/
        .fn-clear:after {
            content: "";
            display: block;
            clear: both;
        }

        li span {
            /*設定選項元素的內邊距*/
            padding: 6px 13px;
        }

        #header {
            /*設定header的高度為50px*/
            height: 50px;
            /*設定header的背景顏色*/
            background-color: aqua;
        }

        #body-left {
            /*設定body-left向左浮動*/
            float: left;
            /*設定寬度為父元素寬度的20%*/
            width: 20%;
            /*設定高度*/
            height: 500px;
            /*設定背景顏色*/
            background-color: aquamarine;
        }

        #body-center {
            /*設定body-center向左浮動*/
            float: left;
            /*設定寬度為父元素寬度的20%*/
            width: 60%;
            /*設定高度*/
            height: 500px;
            /*設定背景顏色*/
            background-color: aliceblue;
        }

        #body-right {
            /*設定body-right向左浮動*/
            float: left;
            /*設定寬度為父元素寬度的20%*/
            width: 20%;
            /*設定高度*/
            height: 500px;
            /*設定背景顏色*/
            background-color: aquamarine;
        }

        #footer {
            /*設定footer的高度*/
            height: 80px;
            /*設定footer的背景顏色*/
            background-color: antiquewhite;
        }
    </style>
</head>
<body>
<div id="header" class="fn-clear">
    <ul>
        <li><span>導航</span></li>
        <li><span>導航</span></li>
        <li><span>導航</span></li>
        <li><span>導航</span></li>
        <li><span>導航</span></li>
        <li><span>導航</span></li>
    </ul>
</div>
<div id="body" class="fn-clear">
    <div id="body-left"></div>
    <div id="body-center"></div>
    <div id="body-right"></div>
</div>
<div id="footer">

</div>
</body>
</html>
複製程式碼

前端重構正規化之 float layout

相關文章