多欄佈局有三種基本的實現方案:固定寬度、流動、彈性。css
固定寬度。佈局的大小不會隨用戶調整瀏覽器窗口大小而變化,通常是 900 到 1100 像素寬(最多見的是 960 像素)。html
流動。佈局的大小會隨用戶調整瀏覽器窗口大小而變化。(結合 CSS 媒體查詢,可以適應最大和最小的屏幕,業界稱之爲 響應式設計。)瀏覽器
彈性。在瀏覽器窗口變寬時,不只佈局變寬,並且全部內容元素的大小也會變化。(實現太過複雜,很少介紹。)app
多數狀況下,佈局中結構化元素(乃至任何元素)的高度是 沒必要或者不該該設定的。由於保持元素 height
屬性的默認值 auto
不變,才能使元素根據本身包含內容的增長而在垂直方向上擴展。這樣擴展的元素會把下方的元素向下推,而佈局也能隨內容數量的增減而垂直伸縮。ide
爲了使瀏覽器窗口寬度合理變化,佈局能做出適當的調整,咱們 須要精細地控制 佈局寬度。佈局
結構以下:spa
上代碼:設計
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>三欄-固定寬度佈局</title> <style> * { margin: 0; padding: 0; } #wrapper{ width: 960px; margin: 0 auto; border:1px solid; } header{ background: #f00; } nav{ background: #dcd9c0; width: 150px; float:left; } article{ background: #ffed53; width: 600px; float: left; } aside{ background: #6a6b6c; width: 210px; float: left; } footer{ clear:both; background: #6a6b6c; } </style> </head> <body> <div id="wrapper"> <header> This is header. </header> <nav> This is nav<br> This is nav<br> This is nav<br> </nav> <article> This is article.<br> This is article.<br> This is article.<br> This is article.<br> This is article.<br> This is article.<br> This is article.<br> This is article.<br> This is article.<br> </article> <aside> This is aside. </aside> <footer> This is footer. </footer> </div> </body> </html>
結果如圖:code
說明幾點:htm
經過給整個外包裝(#wrapper
)設定寬度值(960px
),並將其水平外邊距設定爲 auto
,就能實現居中。隨着向裏面添加內容,相關的欄的高度會增長。
設置寬度並浮動中間三欄(nav、article
和 aside
),讓它們並排顯示。使用屬性:width
和 float
。
三欄的總寬度加起來要等於外包裝的寬度(150 + 600 + 210 = 960
)。一樣使用該方法就能夠加任意多欄,只要它們的總寬度等於外包裝的寬度便可。
頁腳(footer
)位於浮動元素後面,因此就會盡可能往上移動。解決這個問題的方法就是使用 清除浮動(clear:both;
或者使用clear:left;
也能夠,由於這裏只有左浮動元素)。
在上面的佈局中,只要一調整各欄中的內容,佈局就可能超過容器寬度,而右邊的欄就可能滑到左邊的欄下方。例如爲了讓內容與欄邊界空開距離,爲欄添加水平外邊距和內邊距,或者爲了增長愛欄間距,爲欄添加外邊距,致使佈局寬度增大,進而浮動欄下滑;又或者在欄中添加大圖片,或者沒有空格的長字符串(如長URL),也會致使欄寬大超過佈局寬度。
示例:
article{ background: #ffed53; width: 600px; float: left; padding: 10px 20px; /* 添加這一行CSS規則 */ }
結果就會變成這樣:
咱們把這種現象稱爲 浮動滑移,可使用三種方法來預防發生:
box-sizing
屬性切換盒子縮放方式。應該該屬性後,給元素添加邊框和內邊距都不會增大盒子,相反會致使內容變窄。下面來討論這三種方法:
因爲上面給 article
欄添加了左右 20px
的水平邊距,故將該欄寬度從 600px
減至 560px
,故修改後的 article
欄 css 樣式規則以下:
article{ background: #ffed53; width: 560px; /* 這裏 */ float: left; padding: 10px 20px; /* 別忘了這裏 */ }
效果以下:
雖然能實現,但每次只要調整內、外邊距就要重設佈局寬度,很是煩人,並且還可能致使頁面錯亂。
把外邊距和內邊距應用到內容元素上確實有效,前提是這些元素沒有明確地設定寬度,這樣它們的內容纔會隨着內、外邊距的增長而縮小。
根據盒模型定義,沒有寬度的元素在水平方向上會適應其父元素,其內容會隨着外邊距、邊框和內邊距的增長而減小。
考慮到未來修改的時候,一欄中可能包含大量不一樣內容的元素,若是想從新調整內容與容器邊界的距離,就必須每一個元素都要進行調整,這樣不只麻煩,並且容易出錯。何況,給欄添加邊框一樣會增大欄寬,不可能經過爲其包含的內容元素逐個添加應用樣式來作到。
因此說,與其爲容器中的元素添加外邊距,不如 在欄中再添加一個沒有寬度的 div,讓它包含全部內容元素,而後再給這個 div 應用邊框和內邊距。如此一來,只要爲內部 div 設定一次樣式,就能夠把讓全部內容元素與欄邊界保持一致的距離。並且,未來再須要調整時也會很方便。任何新增內容元素的寬度都由這個內部 div 決定。
仍是拿 article
欄來開刀:
<article> <div class="inner"> <!-- 添加一個div --> This is article.<br> This is article.<br> This is article.<br> This is article.<br> This is article.<br> This is article.<br> This is article.<br> This is article.<br> This is article.<br> </div> </article>
增改樣式以下:
article{ background: #ffed53; width: 600px; float: left; } article .inner{ margin: 10px; border:2px solid red; padding: 20px; }
效果以下:
從結果能夠看出,中間欄的寬度並未所以有多少變化,由於內容區減小的寬度抵消了應用到內部 div 上的外邊距、邊框和內邊距的總寬度。因而,咱們能夠這樣結論:若是佈局中的欄是浮動的,並且都設定了寬度,你就不要去動它!要動,就把內容放在內部 div 裏,動這個 div。
box-sizing:border-box
這是最簡單的一個方法。只要在三個浮動的欄的 CSS 規則中分別 加上 box-sizing:border-box
聲明,再給欄添加內邊距(和邊框)就不會致使盒子的寬度變化。此時,既不用調整欄寬去抵消增長的內邊距,也不用使用內部 div。添加內邊距的結果就是內容收縮。
示例:
如下是簡介清晰的沒有內部 div 的標記:
<div id="wrapper"> <header> <!-- 標題 --> </header> <nav> <ul> <!-- 連接 --> </ul> </nav> <article> <!-- 文本 --> </article> <aside> <!-- 文本 --> </aside> <footer> <!-- 文本 --> </footer> </div>
相應的,CSS 規則以下:
* { margin: 0; padding: 0; } #wrapper{ width: 960px; margin: 0 auto; border:1px solid; } header{ background: #f00; } nav{ box-sizing:border-box; /* 這裏! */ background: #dcd9c0; width: 150px; float:left; padding: 10px 20px; /* 添加內邊距 */ } article{ box-sizing:border-box; /* 這裏! */ background: #ffed53; width: 600px; float: left; padding: 10px 20px; /* 添加內邊距 */ } aside{ box-sizing:border-box; /* 還有這裏!! */ background: #6a6b6c; width: 210px; float: left; padding: 10px 20px; /* 添加內邊距 */ } footer{ clear:both; /* 清除浮動,防止頁腳往上移動 */ background: #6a6b6c; }
結果以下:
box-sizing:border-box
確實起做用了。
當咱們取消勾選該屬性時,footer
欄就會因爲 article
欄的推擠產生了浮動滑移,移位到 nav
欄下方。
多麼好用的一個屬性啊!固然也就少不了 可是 —— IE6 和 IE7 不支持該屬性。
廢話少說,解決方案 以下:
使用一個專門解決這個問題的膩子腳本(polyfill),名叫 borderBoxModel.js
.
可使用 條件註釋 把它添加到 HTML 標記以後、結束的 </body> 標籤以前,以保證在加載 DOM 以後再執行該腳本:
<body> <!-- HTML 標記 --> <!-- 只讓 IE8 以前的 IE 加載它 --> <!-- [if It IE 8] --> <script src="helpers/borderBoxModel.js"></script> <![endif]--> </body>
備忘:【關於表現性標記的思考】、【子-星選擇符】、【預防過大的元素】。
參考資料