组织你的 CSS
当你开始处理更大的样式表和大型项目时,你会发现维护一个庞大的 CSS 文件可能具有挑战性。在本文中,我们将简要介绍一些编写易于维护的 CSS 的最佳实践,以及你在他人使用中会发现的一些解决方案,以帮助提高可维护性。
保持 CSS 整洁的技巧
以下是一些关于如何保持样式表组织有序和整洁的一般性建议。
你的项目有编码风格指南吗?
如果你正在团队中处理一个现有项目,首先要检查的是项目是否有现有的 CSS 样式指南。团队样式指南应始终优先于你自己的个人偏好。通常没有绝对正确或错误的做法,但保持一致性很重要。
例如,请查看 MDN 代码示例的 CSS 指南。
保持一致
如果你为项目设定规则,或者独自工作,那么最重要的事情就是保持一致。一致性可以通过各种方式实现,例如对类使用相同的命名约定,选择一种描述颜色的方法,或者保持一致的格式。(例如,你将使用制表符还是空格来缩进代码?如果是空格,用多少个空格?)
拥有一套始终遵循的规则可以减少编写 CSS 时所需的脑力开销,因为有些决定已经做出。
格式化可读的 CSS
你会看到 CSS 有几种格式化方式。一些开发者将所有规则放在一行,如下所示:
.box {background-color: #567895; }
h2 {background-color: black; color: white; }
其他开发者则喜欢将所有内容分行
.box {
background-color: #567895;
}
h2 {
background-color: black;
color: white;
}
CSS 不介意你使用哪种方式。我们个人认为将每个属性和值对放在新行上更具可读性。
注释你的 CSS
为你的 CSS 添加注释将帮助任何未来的开发者使用你的 CSS 文件,但在你休息一段时间后回到项目时,也会对你有所帮助。
/* This is a CSS comment
It can be broken onto multiple lines. */
一个好建议是在样式表中的逻辑部分之间添加一块注释,以便在扫描时快速定位不同部分,甚至为你提供一些可以搜索的内容,以便直接跳转到 CSS 的该部分。如果你使用一个不会出现在代码中的字符串,你可以通过搜索它在各个部分之间跳转——下面我们使用了 ||
。
/* || General styles */
/* … */
/* || Typography */
/* … */
/* || Header and Main Navigation */
/* … */
你不需要注释 CSS 中的每一个细节,因为大部分内容都是不言自明的。你应该注释的是那些你出于某种原因做出特定决定的地方。
例如,你可能以特定方式使用了 CSS 属性来解决旧浏览器的兼容性问题
.box {
background-color: red; /* fallback for older browsers that don't support gradients */
background-image: linear-gradient(to right, red, #aa0000);
}
也许你为了实现某个功能而遵循了一个教程,而 CSS 本身并不是很直观或容易理解。在这种情况下,你可以将教程的 URL 添加到注释中。当你一年左右后回到这个项目时,你会感谢自己,那时你可能模糊地记得有一个关于那个东西的很棒的教程,但却想不起它是从哪里来的。
在你的样式表中创建逻辑分区
一个好主意是首先在样式表中放置所有通用样式。这意味着所有通常会应用的样式,除非你对该元素做了一些特殊处理。你通常会为以下内容设置规则:
body
p
h1
,h2
,h3
,h4
,h5
ul
和ol
table
属性- 链接
在样式表的这一部分,我们为网站上的字体提供默认样式,为数据表和列表等设置默认样式。
/* || GENERAL STYLES */
body {
/* … */
}
h1,
h2,
h3,
h4 {
/* … */
}
ul {
/* … */
}
blockquote {
/* … */
}
本节之后,我们可以定义一些实用类,例如,一个用于移除我们要以 flex 项或以其他方式显示的列表的默认列表样式的类。如果你有一些样式选择,你知道你想要应用于许多不同元素,它们可以放在此节中。
/* || UTILITIES */
.no-bullets {
list-style: none;
margin: 0;
padding: 0;
}
/* … */
然后我们可以添加网站范围内使用的所有内容。这可能包括基本的页面布局、页眉、导航样式等。
/* SITEWIDE */
.main-nav {
/* … */
}
.logo {
/* … */
}
最后,我们将包含特定内容的 CSS,按它们使用的上下文、页面甚至组件进行分类。
/* || STORE PAGES */
.product-listing {
/* … */
}
.product-box {
/* … */
}
通过这种方式组织,我们至少知道在样式表的哪个部分寻找我们想要更改的内容。
避免过度特定的选择器
如果你创建了非常具体的选择器,你通常会发现需要重复你的 CSS 片段,以便将相同的规则应用于另一个元素。例如,你可能有一个如下所示的选择器,它将规则应用于在具有 main
类的 <article>
中,具有 box
类的 <p>
。
article.main p.box {
border: 1px solid #cccccc;
}
如果你想将相同的规则应用于 main
之外的某个元素,或者除了 <p>
之外的某个元素,你将不得不为这些规则添加另一个选择器,或者创建一个全新的规则集。相反,你可以使用选择器 .box
将你的规则应用于任何具有 box
类的元素。
.box {
border: 1px solid #cccccc;
}
有时,使内容更具体是有意义的;然而,这通常是例外而不是常规做法。
将大型样式表拆分成多个较小的样式表
如果网站的不同部分有非常不同的样式,你可能希望有一个包含所有全局规则的样式表,以及一些包含这些部分所需特定规则的较小样式表。你可以从一个页面链接到多个样式表,并应用正常的层叠规则,其中链接在后的样式表中的规则会覆盖链接在前的样式表中的规则。
例如,我们可能有一个作为网站一部分的在线商店,其中大量 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
类几乎相同的规则,除了微小的差异。这两个组件之间的差异是 list-item
有一个下边框,而评论中的图像有边框,但 list-item
图像没有。
.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——一个基本类,用于大致呈媒体对象形状的事物。然后我们会添加一个额外的类来处理那些微小的差异,从而以特定的方式扩展该样式。
.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 中,评论需要同时应用 media
和 comment
类
<div class="media comment">
<img src="" alt="" />
<div class="content"></div>
</div>
列表项将应用 media
和 list-item
<ul>
<li class="media list-item">
<img src="" alt="" />
<div class="content"></div>
</li>
</ul>
Nicole Sullivan 在描述和推广这种方法方面所做的工作意味着,即使是那些今天不严格遵循 OOCSS 方法的人,通常也会以这种方式重用 CSS——它已经作为一种通用的良好方法进入我们的理解。
BEM
BEM 代表块(Block)、元素(Element)和修饰符(Modifier)。在 BEM 中,块是一个独立的实体,例如按钮、菜单或徽标。元素是类似于列表项或标题之类的东西,它与其所在的块相关联。修饰符是块或元素上的一个标志,用于改变样式或行为。由于 CSS 类中大量使用了破折号和下划线,你将能够识别使用 BEM 的代码。例如,请看来自关于 BEM 命名约定 页面的此 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,以及最初由 Yahoo! 创建的 Atomizer CSS (ACSS)。如果你遇到一个使用这些方法之一的项目,那么优点是你将能够搜索并找到许多文章和指南来帮助你理解如何以相同的风格编写代码。
使用这类系统的缺点是,它们可能看起来过于复杂,尤其是对于较小的项目。
CSS 的构建系统
另一种组织 CSS 的方法是利用前端开发者可用的一些工具,这些工具允许你采用稍微更具编程性的方法来编写 CSS。有许多工具,我们称之为预处理器和后处理器。预处理器处理你的原始文件并将它们转换为样式表,而后处理器则处理你完成的样式表并对其进行一些操作——也许是为了优化它以便更快地加载。
使用这些工具中的任何一个都需要你的开发环境能够运行进行预处理和后处理的脚本。许多代码编辑器可以为你完成这项工作,或者你可以安装命令行工具来帮助。
最受欢迎的预处理器是 Sass。这不是一个 Sass 教程,所以我将简要解释一些 Sass 可以做的事情,即使你不使用其他 Sass 功能,这些功能在组织方面也非常有帮助。如果你想了解更多关于 Sass 的知识,可以从 Sass 基础 文章开始,然后继续阅读他们的其他文档。
定义变量
CSS 现在有了原生的 自定义属性,这使得这个功能的重要性越来越低。然而,你可能使用 Sass 的一个原因是能够将项目中使用的所有颜色和字体定义为设置,然后将该变量用于整个项目。这意味着如果你发现使用了错误的蓝色阴影,你只需要在一个地方更改它。
如果像下面第一行那样创建了一个名为 $base-color
的变量,那么就可以在样式表中任何需要该颜色的地方使用它。
$base-color: #c6538c;
.alert {
border: 1px solid $base-color;
}
一旦编译成 CSS,你最终会在最终的样式表中得到以下 CSS。
.alert {
border: 1px solid #c6538c;
}
编译组件样式表
我上面提到过,组织 CSS 的一种方法是将样式表分解成更小的样式表。当使用 Sass 时,你可以将这一点提升到另一个层次,拥有许多非常小的样式表——甚至可以为每个组件都有一个单独的样式表。通过使用 Sass 中包含的功能(局部文件),它们都可以编译成一个或少量样式表,以实际链接到你的网站。
因此,例如,使用 partials,你可以在一个目录中拥有多个样式文件,例如 foundation/_code.scss
、foundation/_lists.scss
、foundation/_footer.scss
、foundation/_links.scss
等。然后你可以使用 Sass 的 @use
规则将它们加载到其他样式表中
// foundation/_index.scss
@use "code";
@use "lists";
@use "footer";
@use "links";
如果所有局部文件都加载到一个索引文件中,如上所示,那么你可以一次性将整个目录加载到另一个样式表中。
// style.scss
@use "foundation";
注意:尝试 Sass 的一个简单方法是使用 CodePen — 你可以在 Pen 的设置中为 CSS 启用 Sass,然后 CodePen 将为你运行 Sass 解析器,以便你看到应用了常规 CSS 的结果网页。有时你会发现在他们的 CodePen 演示中,CSS 教程使用了 Sass 而不是纯 CSS,所以了解一些 Sass 知识会很方便。
用于优化的后处理
如果你担心增加样式表的大小,例如,通过添加大量额外的注释和空白,那么后处理步骤可以是优化 CSS,方法是剥离生产版本中所有不必要的内容。一个实现此功能的后处理器解决方案的例子是 cssnano。