在看眾多大神的css布局指南時,經常看到一個布局:聖杯布局(也有稱為雙飛翼布局的)。今天我們也來剖析一下。
其實,對於眾多css布局,我們只要明確理解了3種技術,那么基本上大多數布局都難不倒我們了:
浮動 float
絕對定位和相對定位 negative margin
負邊距 relative position
浮動
浮動的框可以向左或向右移動,直到它的外邊緣碰到包含框或另一個浮動框的邊框為止。
由於浮動框不在文檔的普通流中,所以文檔的普通流中的塊框表現得就像浮動框不存在一樣。(w3c)
上面是官方的界定。我們可以用"float:left"和"float:right"來使元素塊向左向右浮動。
當一個元素塊被浮動后,其在原文檔流中的空間被關閉,后面的內容會向前補充,這樣很容易造成后面的元素包圍了浮動的元素塊。
為了解決這個問題,我們可以用clear方法來阻止行框包圍元素塊。
絕對定位和相對定位
我們通過position屬性來聲明這個元素塊進行絕對定位或者相對定位。如果要進行定位的是行內元素,首先需要用display:block來將其聲明為一個塊級元素。
兩者的區別為:
相對定位是相對於自身在文檔流中的原有位置的起點為基准進行位移定位。其在文檔流中的位置不會被關閉。
絕對定位是相對於最接近的已定位父元素的起點為基准,如果沒有已定位的父元素,則為其最初的包含快,也就是body。絕對定位相對於相對定位的不同,是其在文檔流中的元素框被關閉,該位置被后面的元素填充。
負邊距
在css中,有兩種邊距,分別為內邊距padding和外邊距margin。
內邊距padding是元素內動與邊框之間的距離,外邊距margin為元素邊框到父元素框外邊距之間的距離。
內邊距padding只能設置為正值,而外邊距margin可以設置為正值也可以設置為負值。
我們還需要了解一點,元素的背景是可以占用內邊距padding距離的。
了解了以上三種方法,我們就可以通過這三種方法來實現我們的各種布局。
這包括了下面介紹的聖杯布局:
先寫一個基本布局:
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 2 <html> 3 <head> 4 <meta http-equiv="content-type" content="text/html; charset=utf-8" /> 5 <title>聖杯布局/雙飛翼布局</title> 6 <style type="text/css"> 7 * { 8 margin: 0; 9 padding: 0; 10 text-Align: center; 11 } 12 #parents { 13 width: 600px; 14 border: 2px solid; 15 margin: 0 auto; 16 } 17 #top { 18 background: #666; 19 } 20 #left { 21 background: #E79F6D; 22 } 23 #content { 24 background: #D6D6D6; 25 } 26 #right { 27 background: #77BBDD; 28 } 29 #foot { 30 background: #666; 31 } 32 </style> 33 </head> 34 <body> 35 <div id="parents"> 36 <div id="top">這是Top!</div> 37 <div id="main"> 38 <div id="left">這是Left!</div> 39 <div id="content">這是Content!</div> 40 <div id="right">這是Right!</div> 41 </div> 42 <div id="foot">這是Foot!</div> 43 </div> 44 </body> 45 </html>
效果:
我們將中間left、content和right向左浮動,並設置left和right的寬度分別設置為100px和150px,將三者的父元素的左右內邊距設置為100px和150px,與left和right的寬度相同。然后我們將foot清除浮動。
1 <style type="text/css"> 2 * { 3 margin: 0; 4 padding: 0; 5 text-Align: center; 6 } 7 #parents { 8 width: 600px; 9 border: 2px solid; 10 margin: 0 auto; 11 } 12 #top { 13 background: #666; 14 } 15 #main { 16 margin-left: 100px; 17 margin-right: 150px; 18 } 19 #left { 20 background: #E79F6D; 21 float: left; 22 width: 100px; 23 } 24 #content { 25 background: #D6D6D6; 26 float: left; 27 width: 100%; 28 } 29 #right { 30 background: #77BBDD; 31 float: left; 32 width: 150px; 33 } 34 #foot { 35 background: #666; 36 clear: both; 37 } 38 </style>
效果:
我們發現,由於content寬度設置了100%,故而其寬度不夠,所以content和right就掉下來了,對於這個我們可以為content和right設置一個margin-left屬性來解決這個問題。
1 #left { 2 background: #E79F6D; 3 float: left; 4 width: 100px; 5 } 6 #content { 7 background: #D6D6D6; 8 float: left; 9 width: 100%; 10 margin-left: -100px; 11 } 12 #right { 13 background: #77BBDD; 14 float: left; 15 width: 150px; 16 margin-left: -150px; 17 }
效果:
上圖中left被content擋住了。
隨后,我們用相對定位把left向左移,right向右移。並把top和foot設置高度為50px;
1 #top { 2 background: #666; 3 height: 50px; 4 } 5 #main { 6 padding-left: 100px; 7 padding-right: 150px; 8 } 9 #left { 10 background: #E79F6D; 11 float: left; 12 width: 100px; 13 position: relative; 14 left: -100px; 15 } 16 #content { 17 background: #D6D6D6; 18 float: left; 19 width: 100%; 20 margin-left: -100px; 21 } 22 #right { 23 background: #77BBDD; 24 float: left; 25 width: 150px; 26 margin-left: -150px; 27 position: relative; 28 left: 150px; 29 } 30 #foot { 31 background: #666; 32 clear: both; 33 height: 50px; 34 }
效果:
看起來差不多了,不過我們還需要處理一個問題,就是中間三列的等高問題,這個是在前面已經探討過的多列等高問題。
1 <style type="text/css"> 2 * { 3 margin: 0; 4 padding: 0; 5 text-Align: center; 6 } 7 #parents { 8 width: 600px; 9 border: 2px solid; 10 margin: 0 auto; 11 } 12 #top { 13 background: #666; 14 height: 50px; 15 } 16 #main { 17 padding-left: 100px; 18 padding-right: 150px; 19 overflow: hidden; 20 } 21 #left,#content,#right { 22 padding-bottom: 2000px; 23 margin-bottom: -2000px; 24 } 25 #left { 26 background: #E79F6D; 27 float: left; 28 width: 100px; 29 position: relative; 30 left: -100px; 31 } 32 #content { 33 background: #D6D6D6; 34 float: left; 35 width: 100%; 36 margin-left: -100px; 37 } 38 #right { 39 background: #77BBDD; 40 float: left; 41 width: 150px; 42 margin-left: -150px; 43 position: relative; 44 left: 150px; 45 } 46 #foot { 47 background: #666; 48 clear: both; 49 height: 50px; 50 } 51 </style>
效果:
這樣就沒問題了,當我們給三者無論哪個添加內容時,三列的高度總會以最高的那列為准維持等高。
在這個布局中,主要內容content的寬度是自適應的,而left和right的寬度是固定的,當我們增加parents的寬度時,content的寬度隨之增加,left和right保持不變。
這就是聖杯布局,也有叫做雙飛翼布局的。
而且我們通過相對定位,可以通過計算,隨意定制left、content和right三者的前后順序。
關於聖杯布局,引用一下CobbySung總結的優缺點:
優點:
- 實現了內容與布局的分離,即Eric提到的Any-Order Columns.
- content部分是自適應寬度的,很容易在定寬布局和流體布局中切換。
- 任何一欄都可以是最高欄,不會出問題。
- 需要的hack非常少(就一個針對ie6的清除浮動hack:_zoom: 1;)
- 在瀏覽器上的兼容性非常好,IE5.5以上都支持。
不足:
- content需要添加一個額外的包裹層。
- 等待你的發現與反饋。
最后附上完整代碼:
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 2 <html> 3 <head> 4 <meta http-equiv="content-type" content="text/html; charset=utf-8" /> 5 <title>聖杯布局/雙飛翼布局</title> 6 <style type="text/css"> 7 * { 8 margin: 0; 9 padding: 0; 10 text-Align: center; 11 } 12 #parents { 13 width: 1000px; 14 border: 2px solid; 15 margin: 0 auto; 16 } 17 #top { 18 background: #666; 19 height: 50px; 20 } 21 #main { 22 padding-left: 100px; 23 padding-right: 150px; 24 overflow: hidden; 25 } 26 #left,#content,#right { 27 padding-bottom: 2000px; 28 margin-bottom: -2000px; 29 } 30 #left { 31 background: #E79F6D; 32 float: left; 33 width: 100px; 34 position: relative; 35 right: 150px; 36 left: 100px; 37 38 } 39 #content { 40 background: #D6D6D6; 41 float: left; 42 width: 100%; 43 margin-left: -100px; 44 position: relative; 45 left: -100px; 46 } 47 #right { 48 background: #77BBDD; 49 float: left; 50 width: 150px; 51 margin-left: -150px; 52 position: relative; 53 left: 150px; 54 } 55 #foot { 56 background: #666; 57 clear: both; 58 height: 50px; 59 } 60 </style> 61 </head> 62 <body> 63 <div id="parents"> 64 <div id="top">這是Top!</div> 65 <div id="main"> 66 <div id="left">這是Left!</div> 67 <div id="content">這是Content!<br><br><br><br>這是多行高度!<br></div> 68 <div id="right">這是Right!</div> 69 </div> 70 <div id="foot">這是Foot!</div> 71 </div> 72 </body> 73 </html>