前提
本文討論的是兩列自適應佈局:左列定寬/不定寬,右列自適應。
雖然分這兩種情況,但實際上不定寬的方案同樣適用於定寬的場景,因此不定寬的方案泛用度更高。
左列定寬,右列自適應
margin + float
<div class="parent">
<div class="left"><p>left</p></div>
<div class="right-fix">
<div class="right">
<p>right</p><p>right</p>
</div>
</div>
</div>
複製程式碼
.left{
float: left; //向左浮動
width: 100px; //固定寬度
position: relative;//由於.left與.right-fix重合,且.right-fix在DOM樹上的位置比.left要後,因此.right-fix會遮擋住.left,設定.left為relative可以讓其冒出來。
}
.right-fix{
float: right; //向右浮動
width: 100%; //為了自適應設為100%
margin-left: -100px;//由於寬度設為100%,.right-fix遭到瀏覽器換行處理;因此通過設定負的margin值,在左側製造出100px的空白,使.right-fix與.left重合(即處於同一行)
}
.right{
margin-left: 120px; //由於.left和.right-fix重合了,因此給.right設定一個margin-left,避免內容區(.right)與.left重合。另外,120px - 100px = 多出來的20px實際上就相當於.left和.right之間的間隔了。
}
複製程式碼
這個方法其實已經是兼顧到低版本IE的完善版本了,缺點是程式碼冗長,而且有兩個關鍵知識點比較難理解:
- 給.left加上position:relative;怎麼就能讓.left冒出來而不受.right-fix的遮擋了呢?
- .right-fix設定負的margin-left,怎麼就能使.left與.right-fix重合了呢?
再者,這個方案由於.right-fix的margin-left和.left的width高度耦合,因此無法實現自適應,只能應用在左列(當然右列也成)固定寬度的場景。
absolute
<div class="parent">
<div class="left">
<p>left</p>
</div>
<div class="right">
<p>right</p>
<p>right</p>
</div>
</div>
複製程式碼
.parent{
position: relative;
}
.left{
position: absolute;
left: 0;
width: 100px;
}
.right{
position: absolute;
left: 120px; //比.left的left多出20px,相當於間隔
right: 0;
}
複製程式碼
這種方法是通過absolute配合left/right進行佈局:
- 設定
display: absolute
後,通過top/right/bottom/left
可以實現對元素的位置進行畫素級的任意控制。因此,使用left
屬性即可控制各元素的起始位置,避免重疊。 - 自適應的關鍵在於
left
和right
屬性,在對元素同時設定這兩個屬性後,元素的寬度便會遭到拉伸,實現自適應。 - 需要注意的是父級元素需要設定
display: relative
。
這種方案很容易理解,但缺點就是不能做到**“不定寬”**,因為.left和.right的left
屬性的值高度相關。
左列不定寬,右列自適應
float + BFC
<div class="parent">
<div class="left">
<p>left</p>
</div>
<div class="right">
<p>right</p>
<p>right</p>
</div>
</div>
複製程式碼
.left{
float: left;
width: 100px;
margin-right: 20px; //形成20px的間隔
}
.right{
overflow: hidden; //通過設定overflow: hidden來觸發BFC特性
}
複製程式碼
這個方法主要是應用到BFC的一個特性:
- 浮動元素的塊狀兄弟元素會無視浮動元素的位置,儘量佔滿一整行,這樣該兄弟元素就會被浮動元素覆蓋。
- 若浮動元素的塊狀兄弟元素為BFC,則不會佔滿一整行,而是根據浮動元素的寬度,佔據該行剩下的寬度,避免與浮動元素重疊。
- 浮動元素與其塊狀BFC兄弟元素之間的margin可以生效,這將繼續減少兄弟元素的寬度。
並不是一定要在.right上用overflow: hidden;
,只要能觸發BFC就好了,另外在IE6上也可以觸發haslayout
特性(推薦用*zoom: 1;
)。
由於.right的寬度是自動計算的,不需要設定任何與.left寬度相關的css,因此.left的寬度可以不固定(由內容盒子決定)。
table佈局
<div class="parent">
<div class="left">
<p>left</p>
</div>
<div class="right">
<p>right</p>
<p>right</p>
</div>
</div>
複製程式碼
.parent{
display: table; width: 100%;
table-layout: fixed;
}
.left,.right{
display: table-cell;
}
.left{
width: 100px;
padding-right: 20px;
}
複製程式碼
這個方法是表格佈局的典型運用。說真的,我也很迷惘要不要使用表格佈局,畢竟已經是上個時代的產物了,雖然已經不再用<table>
的HTML結構了,但用上相應的CSS其實思路跟以前是變化不大的。
這個方法主要是利用了表格(table)的寬度必然等於其所有單元格(table-cell)加起來的總寬度,那麼只要表格的寬度一定,其中一個(或幾個)單元格的寬度也一定,那麼另外一個未設定寬度的單元格則會預設佔滿剩下的寬度,即實現自適應。
flex
<div class="parent">
<div class="left">
<p>left</p>
</div>
<div class="right">
<p>right</p>
<p>right</p>
</div>
</div>
複製程式碼
.parent{
display: flex;
}
.left{
margin-right: 20px;
}
.right{
flex: 1;
}
.left p{width: 200px;}
複製程式碼
flex佈局的自適應我就不多說了,本來就是設計來自適應的,只需要用上flex: 1;
,就能讓.right分到.parent的寬度減去.left的寬度。
推薦使用
我個人是比較推薦用float + BFC
方案,瀏覽器相容性很好,程式碼量也少,另外也很好理解;移動端上也可以考慮用上flex方案,不過還是那一句,注意用舊版的flex,相容性會好一點。
擴充套件
說是說**“兩列自適應佈局”**,實際上,只要滿足“只有一列是自適應”這一條件,多少列布局都行。