CSS 兩欄佈局和三欄佈局

Chaowei發表於2018-12-05

圖片.png

兩欄佈局

圖片.png
基礎部分的程式碼:

<div class="container">
    <div class="left">left</div>
    <div class="right">right</div>
</div>

.left {
    width: 100px;
    height: 150px;
    background-color: #FFB5BF;
}
.right {
    height: 150px;
    background-color: #94E8FF;
}
複製程式碼

此時的 .left 和 .right 獨佔一行,如何實現兩個 div 元素排在一行呢? 1.設定 display 為 inlin-block inline-block 兼具塊級元素可以設定寬高和行內元素不獨佔一行的特性,設定了 inline-block 的兩個 div 之間會有間距,記得消除。由於左邊是固定的,總的寬度是 100%,要計算右邊的寬度,可以使用 calc 來計算。

.container {
    font-size: 0;    /* 消除間距 */
}
.left, .right {
    display: inline-block;
}
.right {
    width: calc(100% - 100px);   /* 計算寬度,運算子號左右一定要有空格 */
}
複製程式碼

2.使用 float 處於文件流中的塊級元素無法感知到浮動元素的存在,如果設定 .left 為 左浮動,.right 會當 .left 不存在,由於塊級元素的預設寬度是父級元素的 100%,此時 .right 的寬度就已經是 100% 了,無需再計算。**別忘了設定 .right 的 margin 值來給 .left 預留空間,讓兩者看起來是和諧相處的。**這便是第一種方法,程式碼如下:

.left {
    float: left;
}
.right {
    margin-left: 100px;   /* 為 .left 留出空間 */
}
.container {
    overflow: hidden;    /* 別忘了清除浮動 */
}
複製程式碼

浮動元素會脫離文件流,直到它碰到父元素的邊框或另一浮動元素為止,因此,我們可以還設定 .left、.right 均左浮動,這時,它們便會緊貼著排列在一行。因為 .right 是浮動的,所以需要計算寬度。這是第二種方法:

.left {
    float: left;
}
.right {
    float: left;
    width: calc(100% - 100px);
}
.container {
    overflow: hidden;
}
複製程式碼

.left 浮動的時候,.right 會無視 .left,有沒有不無視,留出位置的可能?有的,讓 .right 形成 BFC,.right 就不會和 .left 重合了。BFC 不會忽視浮動元素,這也是它的特點之一。這是第三種方法:

.left {
    float: left;
}
.right {
    overflow: auto;    /* 形成 BFC */
}
.container {
    overflow: hidden;
}
複製程式碼

3.使用absolute 設定 .left 的 postion 為 absolute,.left 脫離了文件流,.right 會無視 .left 的存在。

.container {
    position: relative;
}
.left {
    postion: absolute;
}
.right {
    margin-left: 100px;
}
複製程式碼

三欄佈局

三欄佈局中耳熟能詳的便是聖盃佈局和雙飛翼佈局了。聖盃佈局來源於2006年的一篇文章:In Search of the Holy Grail。雙飛翼佈局始於淘寶 UED。兩者都是在解決兩邊固定寬度,中間自適應的三欄佈局,並且主要內容要優先渲染,按照 DOM 從上至下的載入原則,中間的自適應部分要放在前面。

聖盃佈局

我們首先將佈局的基礎框架搭出來,在下面程式碼中,父 div 包含了三個子 div,我們將 .center 寫在最前面,方便最先渲染。為了保證視窗縮小時仍然能展示,我們給 body 設定了最小寬度。

<div class="container">
    <div class="center"></div>
    <div class="left"></div>
    <div class="right"></div>
</div>
body {
    min-width: 630px;
}
.center {
    width: 100%;
    height: 150px;
    background-color: #94E8FF;
}
.left {
    width: 100px;
    height: 150px;
    background-color: #FFB5BF;
}
.right {
    width: 200px;
    height: 150px;
    background-color: #8990D5;
}

複製程式碼

圖片.png
三個子 div 各佔一行顯示了,此時我們給三者都加上左浮動看看效果。

.container {
    overflow: hidden;   /* 清除浮動 */
}
.center, .left, .right {
    float: left;
}
複製程式碼

圖片.png

由於 .center 設定了 100% 的寬度,所以 .left 和 .right 都被擠到下面去了,此時我們要解決的問題就是,如何讓它兩上去,這就要用到 margin 的負值了。我們知道 margin-left: 10px; 是設定 10px 的左外邊距,左邊要多空出一點,視覺效果上就是向右移動了 10px,那如果 margin-left: -10px; 呢?左外間距要減少 10px,自然是向左移動 10px 了。

我們回到要解決的問題中,因為 .center 的寬度是 100%,所以 .left 和 .right 排在了第二行,可以理解為排在了 .center 的後面。這個時候,.left 要回到 .center 的最左邊,便是要向左移動 .center 的寬度,即 100%,.left 移動了知之後,.right 會自動補上 .left 的空位,此時,.right 想要達到 .center 的最右邊,只需要向左移動它自己本身的寬度就可以了,即 200px。

.left {
    margin-left: -100%;
}
.right {
    margin-left: -200px;
}
複製程式碼

圖片.png

仔細一看發現,.center 的文字被遮擋了,此時 .left、.right 都覆蓋在 .center 的上面,我們要給兩者留出位置。

聖盃佈局的做法是先設定父元素 .container 的 padding 屬性,給 .left、.right 留出空間,兩者需要的空間大小便是兩者的寬度,然後利用定位屬性使其歸位。我們先設定 padding 看看效果。

.container {
    padding-left: 100px;
    padding-right: 200px;
}
複製程式碼

圖片.png

由於父元素設定了 padding,所有子元素都往中間擠了,此時只需將 .left、.right 分別向左向右拉到準備的空位就好了。首先將定位屬性設定為 relative,即相對自己定位,.left 要向左移動 100px,.right 要向右移動 200px,所以 .left 只要設定 left: -100px; 、.right 設定 right: -200px; 便能達到效果。

.left {
    position: relative;
    left: -100px;
}
.right {
    position: relative;
    right: -200px;
}
複製程式碼

圖片.png
到這裡,聖盃佈局便完成了,它的核心思想是使用浮動佈局,用 padding 為左右元素留空間,靈活使用 margin 的負值和相對定位讓元素移動到相應的位置。完整的程式碼如下:

<div class="container">
     <div class="center">center</div>
     <div class="left">left</div>
     <div class="right">right</div>
</div>

body {
    min-width: 630px;
}
.container {
    overflow: hidden;
    padding-left: 100px;
    padding-right: 200px;
}
.center {
    width: 100%;
    height: 150px;
    background-color: #94E8FF;
    float: left;
}
.left {
    width: 100px;
    height: 150px;
    background-color: #FFB5BF;
    float: left;
    margin-left: -100%;
    position: relative;
    left: -100px;
}
.right {
    width: 200px;
    height: 150px;
    background-color: #8990D5;
    float: left;
    margin-left: -200px;
    position: relative;
    right: -200px;
}
複製程式碼

雙飛翼佈局

雙飛翼佈局與聖盃佈局的前部分一樣,在給左右兩邊元素留出位置的思路有區別。聖盃佈局是設定了父元素的 padding 留出空間,之後利用 relative 來歸位。雙飛翼則是多加了一個 div,將中間自適應部分包裹起來,利用子 div 的 margin 來給左右元素留空間。

<div class="container">
    <div class="center-container">
        <div class="center"></div>
    </div>
    <div class="left">left</div>
    <div class="right">left</div>
<div>

body {
    min-width: 630px;
}
.container {
    overflow: hidden;
}
.center-container {
    width: 100%;
    float: left;
}
.center-container .center {
    height: 150px;
    background-color: #94E8FF;

    margin-left: 100px;        /* 新新增的屬性 */
    margin-right: 200px;       /* 新新增的屬性 */
}
.left {
    width: 100px;
    height: 150px;
    background-color: #FFB5BF;
    float: left;
    margin-left: -100%;
}
.right {
    width: 200px;
    height: 150px;
    background-color: #8990D5;
    float: left;
    margin-left: -200px;
}
複製程式碼

圖片.png

同樣的問題,雙飛翼佈局通過多加一個 div 並使用了 margin 來實現,聖盃佈局則是使用 padding、相對定位(relative)、設定偏移量(left、right)來實現,相對來說,雙飛翼佈局更容易理解。在聖盃佈局中,無限縮小螢幕(假設沒有設定 body 的最小寬度),當 .main 的寬度小於 .left 時,會出現佈局錯亂。

簡單的flex佈局實現三欄

基礎程式碼:

<div class="container">
    <div class="center">center</div>
    <div class="left">left</div>
    <div class="right">right</div>
</div>

.center {
    height: 150px;
    background-color: #94E8FF;
}

.left {
    width: 100px;
    height: 150px;
    background-color: #FFB5BF;
}
.right {
    width: 200px;
    height: 150px;
    background-color: #8990D5;
}
複製程式碼

我們首先將容器設定為 Flex 佈局:

.container {
    display: flex;
}
複製程式碼

接下來要解決的問題有,如何將 .left 排列在最左邊,和如何將 .center 佔滿剩餘空間。在專案屬性的學習中,order 屬性可以改變專案的排列順序,flex-grow 可以定義專案的放大比例。沒錯,利用這兩個屬性便能解決我們的問題。

.left {
    order: -1;
}

.center {
    flex-grow: 1;   /* flex: 1; 也行 */
}
複製程式碼

Flex 佈局相對於傳統佈局更靈活好用,上面只是給出了一個方法,更多的方法期待大家去探索。

感謝閱讀本文。 本文整理自CCS佈局實踐的部分內容。

相關文章