.布局前的認知
1.1 三種基本方案
多欄布局有三種基本的實現方案:固定寬度、流動、彈性。
固定寬度。布局的大小不會隨用戶調整浏覽器窗口大小而變化,一般是 900 到 1100 像素寬(最常見的是 960 像素)。
流動。布局的大小會隨用戶調整浏覽器窗口大小而變化。(結合 CSS 媒體查詢,能夠適應最大和最小的屏幕,業界稱之為 響應式設計。)
彈性。在浏覽器窗口變寬時,不僅布局變寬,而且所有內容元素的大小也會變化。(實現太過復雜,不多介紹。)
1.2 布局高度
多數情況下,布局中結構化元素(乃至任何元素)的高度是 不必或者不應該設定的。因為保持元素 height 屬性的默認值 auto 不變,才能使元素根據自己包含內容的增加而在垂直方向上擴展。這樣擴展的元素會把下方的元素向下推,而布局也能隨內容數量的增減而垂直伸縮。
1.3 布局寬度
為了使浏覽器窗口寬度合理變化,布局能作出適當的調整,我們 需要精細地控制 布局寬度。
2.三欄-固定寬度布局
結構如下:
上代碼:
結果如圖:
說明幾點:
通過給整個外包裝(#wrapper)設定寬度值(960px),並將其水平外邊距設定為 auto,就能實現居中。隨著向裡面添加內容,相關的欄的高度會增加。
設置寬度並浮動中間三欄(nav、article 和 aside),讓它們並排顯示。使用屬性:width 和 float。
三欄的總寬度加起來要等於外包裝的寬度(150 + 600 + 210 = 960)。同樣使用該方法就可以加任意多欄,只要它們的總寬度等於外包裝的寬度即可。
頁腳(footer)位於浮動元素後面,所以就會盡量往上移動。解決這個問題的方法就是使用 清除浮動(clear:both;或者使用clear:left;也可以,因為這裡只有左浮動元素)。
3.為欄設定內邊距和邊框
在上面的布局中,只要一調整各欄中的內容,布局就可能超過容器寬度,而右邊的欄就可能滑到左邊的欄下方。例如為了讓內容與欄邊界空開距離,為欄添加水平外邊距和內邊距,或者為了增加愛欄間距,為欄添加外邊距,導致布局寬度增大,進而浮動欄下滑;又或者在欄中添加大圖片,或者沒有空格的長字符串(如長URL),也會導致欄寬大超過布局寬度。
示例:
CSS Code復制內容到剪貼板結果就會變成這樣:
我們把這種現象稱為 浮動滑移,可以使用三種方法來預防發生:
從設定的元素寬度中減去添加的水平外邊距、邊框和內邊距的寬度和。
在容器內部的元素上添加內邊距或外邊距。
使用 CSS3 的 box-sizing 屬性切換盒子縮放方式。應該該屬性後,給元素添加邊框和內邊距都不會增大盒子,相反會導致內容變窄。
下面來討論這三種方法:
3.1 重設寬度以抵消內邊距和邊框
由於上面給 article 欄添加了左右 20px 的水平邊距,故將該欄寬度從 600px 減至 560px,故修改後的 article 欄 CSS 樣式規則如下:
CSS Code復制內容到剪貼板效果如下:
雖然能實現,但每次只要調整內、外邊距就要重設布局寬度,非常煩人,而且還可能導致頁面錯亂。
3.2 給容器內部的元素應用內邊距和邊框
把外邊距和內邊距應用到內容元素上確實有效,前提是這些元素沒有明確地設定寬度,這樣它們的內容才會隨著內、外邊距的增加而縮小。
根據盒模型定義,沒有寬度的元素在水平方向上會適應其父元素,其內容會隨著外邊距、邊框和內邊距的增加而減少。
考慮到將來修改的時候,一欄中可能包含大量不同內容的元素,如果想重新調整內容與容器邊界的距離,就必須每個元素都要進行調整,這樣不僅麻煩,而且容易出錯。況且,給欄添加邊框同樣會增大欄寬,不可能通過為其包含的內容元素逐個添加應用樣式來做到。
所以說,與其為容器中的元素添加外邊距,不如 在欄中再添加一個沒有寬度的 div,讓它包含所有內容元素,然後再給這個 div 應用邊框和內邊距。如此一來,只要為內部 div 設定一次樣式,就可以把讓所有內容元素與欄邊界保持一致的距離。而且,將來再需要調整時也會很方便。任何新增內容元素的寬度都由這個內部 div 決定。
還是拿 article 欄來開刀:
XML/Html Code復制內容到剪貼板增改樣式如下:
CSS Code復制內容到剪貼板效果如下:
從結果可以看出,中間欄的寬度並未因此有多少變化,因為內容區減少的寬度抵消了應用到內部 div 上的外邊距、邊框和內邊距的總寬度。於是,我們可以這樣結論:如果布局中的欄是浮動的,而且都設定了寬度,你就不要去動它!要動,就把內容放在內部 div 裡,動這個 div。
3.3 使用 box-sizing:border-box
這是最簡單的一個方法。只要在三個浮動的欄的 CSS 規則中分別 加上 box-sizing:border-box 聲明,再給欄添加內邊距(和邊框)就不會導致盒子的寬度變化。此時,既不用調整欄寬去抵消增加的內邊距,也不用使用內部 div。添加內邊距的結果就是內容收縮。
示例:
以下是簡介清晰的沒有內部 div 的標記:
XML/Html Code復制內容到剪貼板相應的,CSS 規則如下:
結果如下:
box-sizing:border-box 確實起作用了。
多麼好用的一個屬性啊!當然也就少不了 但是 —— IE6 和 IE7 不支持該屬性。
廢話少說,解決方案 如下:
使用一個專門解決這個問題的膩子腳本(polyfill),名叫 borderBoxModel.JS.
可以使用 條件注釋 把它添加到 Html 標記之後、結束的 </body> 標簽之前,以保證在加載 DOM 之後再執行該腳本: