通常,在一个新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元素。