通常,在一個新HTML文檔中,我們首先要寫一個元素,用來包容頁面中的所有其他內容。術語“wrapper”常用在此處。我們給這個元素增加一個類,用來封裝頁面中的其他可視元素。
我一直在努力尋找最好的實現方法。我曾在StackOverflow上發現一個相關的帖子,有超過250,000位觀看者。很明顯,我并不是唯一對此好奇的人。在本文中,我將對我最近的思考做個總結。
在深入探討之前,我們首先說說"wrapper"和"container"之間的不同。
"Wrapper" vs "Container"
我相信wrapper元素和container元素之間存在不同。
在編程語言中,container一詞通常用來表示包含多個元素的結構,wrapper則表示對某單個對象進行包裝,該對象可以提供多個功能,也會向它提供接口。
因為他們代表不同的功能,所以也就擁有了兩個不同的名字。
談到wrapper,通常會想到一個<div>
標簽,它包含HTML文檔的其他所有內容。我相信我們中的很多人都有過將它的寬設置為960px,并將所有主要內容居中顯示的經歷。 wrapper也會用在其他地方,如設計一個sticky footer。
接下來是container,它通常代表另一種類型的包含。有時實現一種行為,有時代表多個組件的樣式。它將具有相同視覺和邏輯的元素進行分組。例如, Bootstrap有不同的container,用來包含它的網格系統或其他各式的組件。
術語wrapper和container也可以按照開發者的想法代表同樣的東西。可能也有其他的約定俗成,通常最好的建議是(讓它們)代表對你來說最合理的東西。但要記住,命名是最基礎也是最重要的開發者行為之一。命名規范可以讓代碼更易讀、更具有可預測性。請認真選擇!
下面是一個有關普通頁面wrapper的例子。
/**
* 1\. Centers the content. Yes, it's a bit opinionated.
* 2\. See the "width vs max-width" section
* 3\. See the "Additional Padding" section
*/
.wrapper {
margin-right: auto; /* 1 */
margin-left: auto; /* 1 */
max-width: 960px; /* 2 */
padding-right: 10px; /* 3 */
padding-left: 10px; /* 3 */
}
width vs max-width
為塊元素設定width
,可以防止它延伸到容器邊緣以外(在很多情況下都有好處,如可讀行的寬度)。所以,wrapper元素會擁有指定的寬。但當瀏覽器窗口比wrapper給的寬度窄時,問題就出現了。它將觸發水平滾動條,這是很不受歡迎。
在這種情況下,可以使用 max-width
代替,更適用于變窄的瀏覽器窗口。當想讓一個網站可以在小設備上運行時,這個屬性就非常重要。這里有個很好的例子來展示這個問題。
代碼演示請見原文。
根據響應式設計原則,max-width
是一個更好的選擇。
額外的Padding
我曾看見很多開發者忘記一種特殊的極端情況。我們將wrapper的max-width
設為980px。這極端情況就是,用戶設備的屏幕正好是980px。那時,內容將緊貼屏幕的邊緣,而沒有留白空間。
無留白空間的問題
我們通常需要離邊界有一定的留白。如果需要實現總寬度為980px的wrapper,我會這樣做:
.wrapper {
max-width: 960px; /* 20px smaller, to fit the paddings on the sides */
padding-right: 10px;
padding-left: 10px;
/* ... */
}
為wrapper增加padding-left
和padding-right
是個好辦法,尤其在移動端。
也可以考慮使用box-sizing。使用它,padding不會改變整體的寬度。
選擇哪個HTML元素
wrapper并沒有任何語義。它只是簡單地包含了所有可視元素和頁面上的內容。它只是一個普通的容器。從語義學角度來說,<div>
是最好的選擇,<div>
也沒有任何語義,也僅僅是一個普通的容器。
有人可能想知道<section>
是否適合。那讓我們來看看 W3C文檔對它的解釋:
The `` element is not a generic container element. When an element is needed only for styling purposes or as a convenience for scripting, authors are encouraged to use the div element instead. A general rule is that the section element is appropriate only if the element's contents would be listed explicitly in the document's outline.
<section>
有它自己的語義。它代表著同主題組。每個section的主題都應該是易區分的。包含一個標題元素(h1-h6),作為section子類,是很典型的做法。
Examples of sections would be chapters, the various tabbed pages in a tabbed dialog box, or the numbered sections of a thesis. A Web site's home page could be split into sections for an introduction, news items, and contact information.
第一眼看上去似乎并不是很出奇,但,是的!普通的div
最適合wrapper。
用<body>
標簽還是使用額外的<div>
值得一提的是,有一些例子使用<body>
標簽作為wrapper。下面的例子可以很好的執行:
body {
margin-right: auto;
margin-left: auto;
max-width: 960px;
padding-right: 10px;
padding-left: 10px;
}
你放棄使用非必須的<div>
作為wrapper,這樣就可以在標記語言中少寫一個元素。
鑒于靈活性和適應性,我不想對此做出評論。想象接下來的項目中,遇到下面這些場景:
你需要將footer固定在文檔的最底部(當文檔很短時,出現在視窗的底部)。即便你使用最現代的方法完成它,如使用flexbox,你還是需要一個額外的
<div>
作為wrapper。你需要為整個頁面設置背景顏色。因為body標簽有
max-width
屬性,很難使用它來實現。那我們可以為<html>
標簽設置背景顏色,以此來代替<body>
。好吧,對此我不太了解。我曾經讀過一篇文章 HTML vs Body in CSS,對我來說它只是聽起來有點陌生。但我也從沒聽到過因為為<html>
標簽設置背景顏色而出現問題、產生困難。不過,這聽起來確實有點怪異,不是嗎?
我的結論是,為實現CSS wrapper增加額外的<div>
是最佳實踐。使用這種方法,即使以后文檔規范發生了變化,你也不必添加wrapper,將樣式進行遷移。畢竟,我們只是討論一個額外的DOM元素。