前言
所謂三欄佈局,即使指兩邊定寬,中間寬度自使用的佈局方式,在過去,一直是一個麻煩的問題,
為了解決這個問題,有各種奇技淫巧,最出名的非聖盃佈局和雙飛翼佈局莫屬了,但是自CSS3發展以來,
特別是flexbox佈局的支援度越來越好,這個問題也越來越淡化了
正文
-
浮動佈局
HTML如下:
<div class="left">Left</div> <div class="right">Right</div> <div class="main">Main</div>
CSS如下:
body, html { height: 100%; padding: 0; margin: 0; } .left{ background: red; width:100px; float: left; height:100%; } .main{ background:blue; height:100%; margin-left:100px; margin-right:200px; } .right{ background:red; width:200px; float: right; height:100%; }
浮動佈局程式碼比較簡潔,同時也易於理解,但是浮動往往會帶來塌陷等問題,而且浮動渲染計算量
較大,在移動端效能表現較差。另一個需要注意的是,main即中間部分需要放在最後,如果是left-main-right的方式
納悶main部分將會佔滿剩餘空間,right也就被擠到下一行了,相反,如果我們設定了right和left,在設定main
main部分將會流入left和right的下面,從而達到我們的目的
-
絕對定位
HTML如下:
<div class="left">left</div> <div class="main">main</div> <div class="right">right</div>
CSS如下:
body, html { height: 100%; padding: 0; margin: 0; } .left, .right { position: absolute; top: 0; background: red; height: 100%; } .left { left: 0; width: 100px; } .right { right: 0; width: 200px; } .main { margin-left: 100px; margin-right: 200px; height: 100%; background: blue; }
該方法有個明顯的缺點,就是如果中間欄含有最小寬度限制,或是含有寬度的內部元素,當瀏覽器寬度小到一定程度,會發生層重疊的情況
-
聖盃佈局
聖盃佈局巧妙的利用負margin來使元素上移,再結合相對定位,移到外層容器的padding位置,從而達到目標 HTML如下:
<div class="main">main</div> <div class="left">left</div> <div class="right">right</div>
CSS如下:
body, html { height: 100%; padding: 0; margin: 0; } body{ padding-left:100px; padding-right:200px; } .left{ background: red; width:100px; float: left; margin-left:-100%;/*-100%:1、導致left超出body內容(此時body內容寬度只有100%-200-100)移到上層2:margin是根據父元素的寬度的,所以-100%就到上層body內容的最前*/ position: relative; left:-100px;/*-100px為了超出body內容左邊,到達視窗最左*/ height:100%; } .main{ background: blue; width:100%; height:100%; float: left; } .right{ background:red; width:200px; height:100%; float: left; margin-left:-200px;/*-200px為了超出body內容到達上一層body內容最後*/ position: relative; right:-200px;/*-200px是為了向右偏移回到視窗最右*/ } .container{ width:500px; height:200px; }
問題:如果外層內容盒寬度過小,不足以容納.left的寬度,那麼.left依然會被保留在下層
-
雙飛翼佈局
雙飛翼佈局與聖盃佈局原理類似,只不過是取消了外層的padding,從而使內容盒等於padding-box從而避免了.left上移後需要設定left值移動到padding HTML如下:
<div class="main"> <div class="inner"> main </div> </div> <div class="left"> left </div> <div class="right"> right </div>
CSS如下:
body, html { height: 100%; padding: 0; margin: 0; } body{ /*padding-left:100px;*/ /*padding-right:200px;*/ } .left{ background: red; width:100px; float: left; margin-left:-100%;/*-100% 1:是為了超出body內容(此時body內容為100%)最左 2:到達body上層內容最左也就是視窗最左 /*position: relative;*/ /*left:-100px;*/ height:100%; } .main{ background: blue; width:100%; height:100%; float: left; } .right{ background:red; width:200px; height:100%; float: left; margin-left:-200px;/*-200px 1:是為了超出body內容(此時body內容為100%)最左 2:到達body上層內容最右也就是視窗最右 /*position: relative;*/ /*right:-200px;*/ } .inner{ margin-left:100px; margin-right:200px; }
與聖盃佈局不同的地方已用註釋指出,而雙飛翼問題與聖盃一樣
-
flexbox佈局
flexbox佈局可謂是最為理想的解決方案了,一方面,程式碼簡潔易懂,另一方面,當寬度太小時,也可以通過伸縮,避免重疊 HTML如下:
<div class="main">main</div> <div class="left">left</div> <div class="right">right</div>
CSS如下:
body,html{
height:100%;
padding: 0;
margin:0;
}
body{
display: flex;
flex-flow:row nowrap;
}
.left{
background: red;
width:100px;
height:100%;
order:0;
}
.main{
background-color: blue;
flex:1;
height:100%;
order:1;
}
.right{
background: red;
width:200px;
height:100%;
order:2;
}