组织你的 CSS

当你开始处理更大的样式表和大型项目时,你会发现维护一个巨大的 CSS 文件可能具有挑战性。在本文中,我们将简要介绍一些编写 CSS 的最佳实践,以使其易于维护,以及一些你将发现其他人正在使用的解决方案,以帮助提高可维护性。

先决条件 已安装基本软件处理文件的基本知识,HTML 基础(学习HTML 简介),以及 CSS 工作原理的概念(学习CSS 初步)。
目标 学习一些组织样式表的技巧和最佳实践,并了解一些常用的命名约定和工具,以帮助组织 CSS 和团队协作。

保持 CSS 整洁的技巧

以下是一些关于如何保持样式表井井有条的通用建议。

你的项目是否有编码风格指南?

如果你与团队合作处理现有项目,首先要检查项目是否已存在 CSS 风格指南。团队风格指南应始终优先于你自己的个人偏好。通常没有正确或错误的方法,但一致性很重要。

例如,查看MDN 代码示例的 CSS 指南

保持一致

如果你可以为项目设置规则或独自工作,那么最重要的事情是保持一致性。一致性可以通过各种方式应用,例如对类使用相同的命名约定,选择一种描述颜色的方法,或保持一致的格式。(例如,你将使用制表符还是空格缩进你的代码?如果是空格,则使用多少个空格?)

有一套你始终遵循的规则减少了编写 CSS 时所需的认知负担,因为某些决策已经做出。

格式化可读的 CSS

你会看到几种 CSS 格式化方式。一些开发者将所有规则放在一行上,如下所示

css
.box {background-color: #567895; }
h2 {background-color: black; color: white; }

其他开发者更喜欢将所有内容都换行

css
.box {
  background-color: #567895;
}

h2 {
  background-color: black;
  color: white;
}

CSS 不在乎你使用哪一种。我们个人认为,将每个属性和值对都换行更具可读性。

注释你的 CSS

向你的 CSS 添加注释将有助于任何未来的开发者使用你的 CSS 文件,但当你休息后返回项目时,它也会对你有所帮助。

css
/* This is a CSS comment
It can be broken onto multiple lines. */

一个好的技巧是在样式表中逻辑部分之间添加注释块,以帮助在扫描时快速找到不同的部分,甚至为你提供一些内容以搜索并直接跳转到 CSS 的该部分。如果你使用一个不会出现在代码中的字符串,你可以通过搜索它来在各个部分之间跳转——下面我们使用了||

css
/* || General styles */

/* … */

/* || Typography */

/* … */

/* || Header and Main Navigation */

/* … */

你不需要注释 CSS 中的每一件事,因为其中很多都是不言而喻的。你应该注释的是你在某个地方出于某种原因做出的决策。

例如,你可能以某种特定方式使用了 CSS 属性来解决旧版浏览器的兼容性问题。

css
.box {
  background-color: red; /* fallback for older browsers that don't support gradients */
  background-image: linear-gradient(to right, #ff0000, #aa0000);
}

也许你按照某个教程完成了某件事,并且 CSS 并不十分直观或易于识别。在这种情况下,你可以将教程的 URL 添加到注释中。当你在一年后回到这个项目并隐约记得有一个关于那个东西的精彩教程,但记不起它来自哪里时,你会感谢自己。

在样式表中创建逻辑部分

最好在样式表中首先包含所有常用样式。这意味着所有通常适用的样式,除非你对该元素执行了特殊操作。你通常会为以下内容设置规则:

  • body
  • p
  • h1h2h3h4h5
  • ulol
  • table 属性
  • 链接

在本节样式表中,我们为网站上的文本提供了默认样式,设置了数据表和列表的默认样式等等。

css
/* || GENERAL STYLES */

body {
  /* … */
}

h1,
h2,
h3,
h4 {
  /* … */
}

ul {
  /* … */
}

blockquote {
  /* … */
}

在本节之后,我们可以定义一些实用程序类,例如,一个用于移除我们打算作为弹性项目或以其他方式显示的列表的默认列表样式的类。如果您有一些您知道需要应用于许多不同元素的样式选择,可以将它们放在此节中。

css
/* || UTILITIES */

.nobullets {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* … */

然后,我们可以添加网站范围内使用的所有内容。这可能包括基本页面布局、页眉、导航样式等。

css
/* || SITEWIDE */

.main-nav {
  /* … */
}

.logo {
  /* … */
}

最后,我们将包含特定内容的 CSS,并根据其使用上下文、页面甚至组件进行细分。

css
/* || STORE PAGES */

.product-listing {
  /* … */
}

.product-box {
  /* … */
}

通过以这种方式排序,我们至少可以了解将在样式表的那一部分中查找我们要更改的内容。

避免过度具体的选取器

如果您创建非常具体的选取器,您会经常发现需要复制 CSS 的一部分才能将相同的规则应用于另一个元素。例如,您可能会有如下所示的选取器,它将规则应用于类名为 box<p> 元素,该元素位于类名为 main<article> 元素内。

css
article.main p.box {
  border: 1px solid #ccc;
}

如果您随后想将相同的规则应用于 main 之外的元素或 <p> 以外的元素,则必须为这些规则添加另一个选取器或创建一个全新的规则集。相反,您可以使用选取器 .box 将您的规则应用于任何具有类 box 的元素。

css
.box {
  border: 1px solid #ccc;
}

有时使某些内容更具体是有意义的;但是,这通常是例外情况,而不是惯例。

将大型样式表分解成多个较小的样式表

在网站的不同部分具有非常不同的样式的情况下,您可能希望有一个样式表包含所有全局规则,以及一些包含这些部分所需特定规则的较小样式表。您可以从一个页面链接到多个样式表,并且级联的正常规则适用,后面链接的样式表中的规则位于前面链接的样式表中的规则之后。

例如,我们可能在网站中有一个在线商店,其中许多 CSS 仅用于为产品列表和商店所需的表单设置样式。将这些内容放在一个单独的样式表中,仅在商店页面上链接,是有意义的。

这可以使您的 CSS 更易于组织,并且还意味着如果多人正在处理 CSS,您将遇到更少的两种人需要同时处理同一个样式表的情况,从而导致源代码控制冲突。

其他可帮助你的工具

CSS 本身在内置组织方面并没有太多内容;因此,CSS 中的一致性水平很大程度上取决于您。Web 社区开发了各种工具和方法来帮助您管理大型 CSS 项目。由于在与其他人合作时可能会遇到这些辅助工具,并且由于它们通常有帮助,因此我们提供了一些简要指南。

CSS 方法

无需自己制定编写 CSS 的规则,您可以从社区已经设计并在许多项目中测试过的方法中获益。这些方法本质上是 CSS 编码指南,采用非常结构化的方式来编写和组织 CSS。通常,与您为该项目编写和优化每个选取器以获得自定义规则集相比,它们往往会使 CSS 变得更冗长。

但是,通过采用其中一种方法,您确实获得了许多结构。由于许多这些系统被广泛使用,因此其他开发人员更有可能理解您使用的方法并能够以相同的方式编写自己的 CSS,而不是必须从头开始研究您自己的个人方法。

OOCSS

您将遇到的许多方法都或多或少地归功于面向对象 CSS (OOCSS) 的概念,这是一种由 Nicole Sullivan 的工作 推广的方法。OOCSS 的基本思想是将您的 CSS 分离成可重用的对象,这些对象可以在您网站的任何需要的地方使用。OOCSS 的标准示例是称为 媒体对象 的模式。这是一种模式,一侧是固定大小的图像、视频或其他元素,另一侧是灵活的内容。这是我们在整个网站上看到的用于评论、列表等的模式。

如果您没有采用 OOCSS 方法,则可能会为使用此模式的不同位置创建自定义 CSS,例如,通过创建两个类,一个名为 comment,其中包含组件部分的一系列规则,另一个名为 list-item,其规则与 comment 类几乎相同,除了某些细微差别。这两个组件之间的区别在于列表项底部有边框,评论中的图像有边框,而列表项图像没有。

css
.comment {
  display: grid;
  grid-template-columns: 1fr 3fr;
}

.comment img {
  border: 1px solid grey;
}

.comment .content {
  font-size: 0.8rem;
}

.list-item {
  display: grid;
  grid-template-columns: 1fr 3fr;
  border-bottom: 1px solid grey;
}

.list-item .content {
  font-size: 0.8rem;
}

在 OOCSS 中,您将创建一个名为 media 的模式,其中包含两种模式的所有通用 CSS——用于通常具有媒体对象形状的事物的基本类。然后,我们将添加一个额外的类来处理这些细微差别,从而以特定的方式扩展该样式。

css
.media {
  display: grid;
  grid-template-columns: 1fr 3fr;
}

.media .content {
  font-size: 0.8rem;
}

.comment img {
  border: 1px solid grey;
}

.list-item {
  border-bottom: 1px solid grey;
}

在您的 HTML 中,评论需要同时应用 mediacomment 类。

html
<div class="media comment">
  <img src="" alt="" />
  <div class="content"></div>
</div>

列表项将应用 medialist-item

html
<ul>
  <li class="media list-item">
    <img src="" alt="" />
    <div class="content"></div>
  </li>
</ul>

Nicole Sullivan 在描述和推广这种方法方面所做的工作意味着,即使是今天没有严格遵循 OOCSS 方法的人通常也会以这种方式重用 CSS——它已经成为我们普遍理解的一种好的方法。

BEM

BEM 代表块元素修改器。在 BEM 中,块是一个独立的实体,例如按钮、菜单或徽标。元素是诸如列表项或标题之类的与它所在的块相关联的内容。修饰符是块或元素上的标志,用于更改样式或行为。您将能够识别使用 BEM 的代码,因为 CSS 类中广泛使用了破折号和下划线。例如,查看从关于 BEM 命名约定 的页面应用于此 HTML 的类。

html
<form class="form form--theme-xmas form--simple">
  <label class="label form__label" for="inputId"></label>
  <input class="form__input" type="text" id="inputId" />

  <input
    class="form__submit form__submit--disabled"
    type="submit"
    value="Submit" />
</form>

其他类类似于 OOCSS 示例中使用的类;但是,它们使用 BEM 的严格命名约定。

BEM 在较大的 Web 项目中被广泛使用,许多人以这种方式编写 CSS。即使在教程中,您也可能会遇到使用 BEM 语法的示例,而没有说明为什么 CSS 以这种方式构建。

在 CSS Tricks 上阅读有关此系统的更多信息 BEM 101

其他常见系统

有大量此类系统正在使用。其他流行的方法包括由 Jonathan Snook 创建的 CSS 的可扩展和模块化架构 (SMACSS)、Harry Roberts 的 ITCSS 和最初由雅虎创建的 原子 CSS (ACSS)。如果您遇到使用其中一种方法的项目,那么优势在于您可以搜索并找到许多文章和指南来帮助您了解如何以相同的风格进行编码。

使用此类系统的缺点是它们可能看起来过于复杂,尤其是在较小的项目中。

CSS 构建系统

组织 CSS 的另一种方法是利用前端开发人员可用的某些工具,这些工具允许您采用稍微更具程序化的方法来编写 CSS。有一些工具,我们称之为预处理器后处理器。预处理器会遍历您的原始文件并将其转换为样式表,而后处理器会获取您的完成样式表并对其进行处理——也许是为了优化它以便更快加载。

使用任何这些工具都需要您的开发环境能够运行执行预处理和后处理的脚本。许多代码编辑器可以为您做到这一点,或者您可以安装命令行工具来提供帮助。

最流行的预处理器是 Sass。这不是 Sass 教程,因此我将简要解释 Sass 可以执行的几件事,这些事情在组织方面非常有用,即使您不使用任何其他 Sass 功能也是如此。如果您想了解有关 Sass 的更多信息,请从 Sass 基础 文章开始,然后继续学习他们的其他文档。

定义变量

CSS 现在具有本机 自定义属性,使此功能越来越不重要。但是,您可能使用 Sass 的原因之一是能够将项目中使用的所有颜色和字体定义为设置,然后在整个项目中使用该变量。这意味着,如果您意识到使用了错误的蓝色阴影,则只需在一个地方更改它即可。

如果我们创建一个名为 $base-color 的变量,如下面的第一行所示,那么我们可以在需要该颜色的样式表中的任何位置使用它。

scss
$base-color: #c6538c;

.alert {
  border: 1px solid $base-color;
}

编译成 CSS 后,您将在最终样式表中获得以下 CSS。

css
.alert {
  border: 1px solid #c6538c;
}

编译组件样式表

我在上面提到过,组织 CSS 的一种方法是将样式表分解成较小的样式表。使用 Sass 时,您可以将其提升到另一个层次,并拥有许多非常小的样式表——甚至可以为每个组件创建一个单独的样式表。通过使用 Sass 中包含的功能(部分),所有这些都可以编译成一个或少量样式表,以实际链接到您的网站。

因此,例如,使用 部分,您可以在目录中拥有多个样式文件,例如 foundation/_code.scssfoundation/_lists.scssfoundation/_footer.scssfoundation/_links.scss 等。然后,您可以使用 Sass 的 @use 规则将它们加载到其他样式表中。

scss
// foundation/_index.scss
@use "code";
@use "lists";
@use "footer";
@use "links";

如果所有部分都加载到索引文件中(如上所述),则可以立即将整个目录加载到另一个样式表中。

scss
// style.scss
@use "foundation";

注意:尝试使用 Sass 的一种简单方法是使用 CodePen——您可以在 Pen 的设置中为您的 CSS 启用 Sass,然后 CodePen 将为您运行 Sass 解析器,以便您可以看到应用了常规 CSS 的结果网页。有时您会发现 CSS 教程在其 CodePen 演示中使用了 Sass 而不是纯 CSS,因此了解一些关于 Sass 的知识非常方便。

优化后处理

如果您担心向样式表添加大小,例如,通过添加大量其他注释和空格,那么后处理步骤可能是通过删除生产版本中任何不必要的内容来优化 CSS。执行此操作的后处理解决方案的一个示例是 cssnano

总结

这是我们的构建块模块的最后一部分,如您所见,从这一点开始,您可以继续探索 CSS 的许多方法——但现在您可以通过我们的评估来测试自己:第一个链接如下。

要了解有关 CSS 中布局的更多信息,请参阅 CSS 布局 模块。

您现在还应该具备探索其余 MDN CSS 材料的技能。您可以查找属性和值,探索我们的 CSS 食谱 以获取要使用的模式,或者继续阅读一些特定指南,例如我们的 CSS 网格布局指南