在 CSS 中实现“包装器”的最佳方法

Avatar of Kaloyan Kosev
Kaloyan Kosev

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费积分!

有时,我们在新文档中编写的第一个 HTML 片段是一个元素,它包装页面上的所有其他内容。术语包装器通常用于此。我们赋予它一个类,该类负责封装页面上的所有视觉元素。

我一直难以找到实现它的最佳方法。我发现 StackOverflow 上的相关帖子 有超过 250,000 次浏览量,因此显然我不唯一一个想知道的人!我将在本文中总结我最新的想法。

在深入探讨之前,让我们首先检查一下“包装器”和“容器”之间的区别。

“包装器”与“容器”

我相信包装器容器元素之间存在差异。

在编程语言中,单词容器通常用于可以包含多个元素的结构。另一方面,包装器是围绕单个对象包装以向其提供更多功能和接口的内容。

因此,在我看来,使用两个不同的名称是有意义的,因为它们意在不同的功能。

说到包装器,通常会想到一个包含文档其余所有 HTML 的<div>。我相信我们许多人都经历过将宽度设置为 960px 并将所有主要内容居中对齐的时代。包装器还用于诸如应用 一个 粘性页脚之类的事情。

另一方面,容器通常意在另一种类型的包含。有时需要实现多个组件的行为或样式。它用于在语义上和视觉上对元素进行分组。例如,Bootstrap 有容器类”用于容纳其网格系统或包含各种其他组件。

根据开发人员及其意图,术语包装器和容器也可以表示相同的意思。也可能存在其他约定,因此最好的建议通常是实现对你最有意义的约定。但请记住,命名是开发人员活动中最基本和最重要的部分之一。命名约定使我们的代码更易读和可预测。谨慎选择!

这是一个通用页面包装器的示例

/**
 * 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将阻止它扩展到其容器的边缘(对于可读的行长等很有用)。因此,包装器元素将占用指定的宽度。当浏览器窗口比包装器的特定宽度窄时,就会出现问题。这将触发水平滚动条,这几乎总是不可取的。

在这种情况下,使用max-width会更好,因为它适用于较窄的浏览器窗口。这在使网站在小型设备上可用时非常重要。这是一个展示问题的很好的例子。

查看 CodePen 上 Kaloyan Kosev (@superKalo) 编写的 Pen CSS-Tricks:在 CSS 中实现包装器的最佳方法

在响应式方面,max-width是更好的选择!

其他填充

我见过很多开发人员忘记了一个特定的极端情况。假设我们有一个包装器,其max-width设置为 980px。当用户设备屏幕宽度恰好为 980px 时,就会出现这种情况。然后内容将完全粘贴到屏幕边缘,没有留下任何呼吸空间。

“没有留下任何呼吸空间”的问题。

我们通常希望在边缘有一些填充。因此,如果我需要实现一个总宽度为 980px 的包装器,我会这样做

.wrapper {
  max-width: 960px; /* 20px smaller, to fit the paddings on the sides */

  padding-right: 10px;
  padding-left: 10px;

  /* ...  */
}

因此,这就是为什么向包装器添加padding-leftpadding-right可能是一个好主意,尤其是在移动设备上。

或者,考虑使用 box-sizing,这样填充就不会改变整体宽度。

选择哪个 HTML 元素

包装器没有语义含义。它只是包含页面上的所有视觉元素和内容。它只是一个通用容器。在语义方面,<div>是最佳选择。<div>也没有语义含义,它只是一个通用容器。

有人可能会想知道<section>元素是否可以满足此目的。但是,以下是W3C 规范所说的

<section>元素不是一个通用容器元素。当仅出于样式目的或作为脚本的便利而需要元素时,鼓励作者使用div元素。一般规则是,只有当元素的内容在文档的大纲中明确列出时,section元素才合适。

<section>元素带有其自身的语义。它表示内容的主题分组。每个部分的主题应被识别,通常是通过包含标题(h1-h6 元素)作为 section 元素的子元素来识别。

部分的示例包括章节、选项卡对话框中的各个选项卡页面或论文的编号部分。网站的首页可以分为介绍、新闻资讯和联系信息等部分。

乍一看可能不太明显,但是是的!普通的<div>最适合包装器!

使用 <body> 标签与使用额外的 <div>

值得一提的是,在某些情况下可以使用<body>元素作为包装器。以下实现将完美运行

body {
  margin-right: auto;
  margin-left:  auto;
  max-width: 960px;
  padding-right: 10px;
  padding-left:  10px;
}

它将使标记中的元素减少一个,因为你可以这样删除不必要的包装器<div>

但是,我不建议这样做,因为这样会降低灵活性并难以应对变化。想象一下,在项目的后期阶段出现以下任何一种情况

  • 你需要强制页脚“粘贴”到文档的末尾(当文档较短时,粘贴到视口的底部)。即使你可以使用最现代的方法来做到这一点——使用 flexbox,你也需要一个额外的包装器<div>
  • 你需要设置整个页面的background-color。通常,你在<body>上设置的任何背景都会表现得好像它是在<html>元素上设置的一样,前提是它还没有背景。CSS 中的一个奇怪之处。但是,如果你的<html>元素确实已经有一个背景,并且你将 body 设置为其他内容,并且 body 具有任何类型的间距约束,那么背景会变得很奇怪。这是一个棘手的事情

我得出的结论是,为了实现 CSS 包装器,最好还是使用额外的<div>。这样,如果以后规范要求发生变化,你就不必以后再添加包装器并处理样式移动。毕竟,我们只谈论一个额外的 DOM 元素。