组织你的 CSS
当你开始处理更大的样式表和大型项目时,你会发现维护巨大的 CSS 文件可能具有挑战性。在本文中,我们将简要介绍一些编写 CSS 使其易于维护的最佳实践,以及你会发现其他人正在使用的一些解决方案,以帮助提高可维护性。
¥As you start to work on larger stylesheets and big projects you will discover that maintaining a huge CSS file can be challenging. In this article we will take a brief look at some best practices for writing your CSS to make it easily maintainable, and some of the solutions you will find in use by others to help improve maintainability.
保持 CSS 整洁的技巧
你的项目有编码风格指南吗?
¥Does your project have a coding style guide?
如果你正在与团队合作处理现有项目,首先要检查该项目是否有现有的 CSS 样式指南。团队风格指南应该始终胜过你自己的个人喜好。做事的方式通常没有正确或错误之分,但一致性很重要。
¥If you are working with a team on an existing project, the first thing to check is whether the project has an existing style guide for CSS. The team style guide should always win over your own personal preferences. There often isn't a right or wrong way to do things, but consistency is important.
例如,看一下 MDN 代码示例的 CSS 指南。
¥For example, have a look at the CSS guidelines for MDN code examples.
保持一致
¥Keep it consistent
如果你要为项目制定规则或者单独工作,那么最重要的事情就是保持事情的一致性。一致性可以通过各种方式应用,例如对类使用相同的命名约定、选择一种描述颜色的方法或保持一致的格式。(例如,你会使用制表符还是空格来缩进代码?如果有空格,多少个空格?)
¥If you get to set the rules for the project or are working alone, then the most important thing to do is to keep things consistent. Consistency can be applied in all sorts of ways, such as using the same naming conventions for classes, choosing one method of describing color, or maintaining consistent formatting. (For example, will you use tabs or spaces to indent your code? If spaces, how many spaces?)
拥有一组始终遵循的规则可以减少编写 CSS 时所需的脑力消耗,因为某些决定已经做出。
¥Having a set of rules you always follow reduces the amount of mental overhead needed when writing CSS, as some of the decisions are already made.
设置可读 CSS 格式
¥Formatting readable CSS
你可以通过多种方式查看 CSS 格式。一些开发者将所有规则放在一行中,如下所示:
¥There are a couple of ways you will see CSS formatted. Some developers put all of the rules onto a single line, like so:
.box {background-color: #567895; }
h2 {background-color: black; color: white; }
其他开发者更喜欢将所有内容分解为新行:
¥Other developers prefer to break everything onto a new line:
.box {
background-color: #567895;
}
h2 {
background-color: black;
color: white;
}
CSS 并不介意你使用哪一个。我们个人发现将每个属性和值对放在一个新行中更具可读性。
¥CSS doesn't mind which one you use. We personally find it is more readable to have each property and value pair on a new line.
评论你的 CSS
¥Comment your CSS
向 CSS 添加注释将有助于任何未来的开发者处理你的 CSS 文件,而且当你剩余后返回项目时也会为你提供帮助。
¥Adding comments to your CSS will help any future developer work with your CSS file, but will also help you when you come back to the project after a break.
/* This is a CSS comment
It can be broken onto multiple lines. */
一个好的技巧是在样式表中的逻辑部分之间添加注释块,以帮助在扫描时快速找到不同的部分,甚至为你提供搜索内容以直接跳转到 CSS 的该部分。如果你使用的字符串不会出现在代码中,你可以通过搜索它从一个部分跳转到另一个部分 - 下面我们使用了 ||
。
¥A good tip is to add a block of comments between logical sections in your stylesheet too, to help locate different sections quickly when scanning it, or even to give you something to search for to jump right into that part of the CSS. If you use a string that won't appear in the code, you can jump from section to section by searching for it — below we have used ||
.
/* || General styles */
/* … */
/* || Typography */
/* … */
/* || Header and Main Navigation */
/* … */
你不需要对 CSS 中的每一项内容进行注释,因为其中大部分都是不言自明的。你应该评论的是你出于某种原因做出特定决定的事情。
¥You don't need to comment every single thing in your CSS, as much of it will be self-explanatory. What you should comment are the things where you made a particular decision for a reason.
你可能以特定方式使用 CSS 属性来解决旧版浏览器的不兼容性问题,例如:
¥You may have used a CSS property in a specific way to get around older browser incompatibilities, for example:
.box {
background-color: red; /* fallback for older browsers that don't support gradients */
background-image: linear-gradient(to right, #ff0000, #aa0000);
}
也许你遵循教程来实现某些目标,但 CSS 并不是很容易解释或识别。在这种情况下,你可以将教程的 URL 添加到评论中。当你一年左右回到这个项目时,你会感谢自己,并且隐约记得有一个关于那个东西的很棒的教程,但不记得它来自哪里。
¥Perhaps you followed a tutorial to achieve something, and the CSS isn't very self-explanatory or recognizable. In that case, you could add the URL of the tutorial to the comments. You will thank yourself when you come back to this project in a year or so and can vaguely remember that there was a great tutorial about that thing, but can't recall where it's from.
在样式表中创建逻辑部分
¥Create logical sections in your stylesheet
将所有常见样式放在样式表中是一个好主意。这意味着通常适用的所有样式,除非你对该元素做了一些特殊的操作。你通常会为以下内容设置规则:
¥It is a good idea to have all of the common styling first in the stylesheet. This means all of the styles which will generally apply unless you do something special with that element. You will typically have rules set up for:
body
p
h1
、h2
、h3
、h4
、h5
ul
和ol
table
属性- 链接
在样式表的这一部分中,我们为站点上的类型提供默认样式,为数据表和列表等设置默认样式。
¥In this section of the stylesheet we are providing default styling for the type on the site, setting up a default style for data tables and lists and so on.
/* || GENERAL STYLES */
body {
/* … */
}
h1,
h2,
h3,
h4 {
/* … */
}
ul {
/* … */
}
blockquote {
/* … */
}
在本节之后,我们可以定义一些实用程序类,例如,一个删除我们将要显示为弹性项目或以其他方式显示的列表的默认列表样式的类。如果你有一些样式选择,并且知道你想要应用到许多不同的元素,则可以将它们放在本部分中。
¥After this section, we could define a few utility classes, for example, a class that removes the default list style for lists we're going to display as flex items or in some other way. If you have a few styling choices you know you will want to apply to lots of different elements, they can be put in this section.
/* || UTILITIES */
.nobullets {
list-style: none;
margin: 0;
padding: 0;
}
/* … */
然后我们可以添加站点范围内使用的所有内容。这可能是基本页面布局、标题、导航样式等。
¥Then we can add everything that is used sitewide. That might be things like the basic page layout, the header, navigation styling, and so on.
/* || SITEWIDE */
.main-nav {
/* … */
}
.logo {
/* … */
}
最后,我们将包含针对特定事物的 CSS,按使用它们的上下文、页面甚至组件进行细分。
¥Finally, we will include CSS for specific things, broken down by the context, page, or even component in which they are used.
/* || STORE PAGES */
.product-listing {
/* … */
}
.product-box {
/* … */
}
通过以这种方式排序,我们至少知道我们将在样式表的哪一部分中寻找我们想要更改的内容。
¥By ordering things in this way, we at least have an idea in which part of the stylesheet we will be looking for something that we want to change.
避免过于具体的选择器
¥Avoid overly-specific selectors
如果你创建非常具体的选择器,你通常会发现需要复制 CSS 块才能将相同的规则应用于另一个元素。例如,你可能有类似下面的选择器,它将规则应用于类为 main
的 <article>
内类为 box
的 <p>
。
¥If you create very specific selectors, you will often find that you need to duplicate chunks of your CSS to apply the same rules to another element. For example, you might have something like the selector below, which applies the rule to a <p>
with a class of box
inside an <article>
with a class of main
.
article.main p.box {
border: 1px solid #ccc;
}
如果你随后想要将相同的规则应用于 main
之外的内容或 <p>
以外的内容,则必须向这些规则添加另一个选择器或创建一个全新的规则集。相反,你可以使用选择器 .box
将规则应用到具有 box
类的任何元素:
¥If you then wanted to apply the same rules to something outside of main
, or to something other than a <p>
, you would have to add another selector to these rules or create a whole new ruleset. Instead, you could use the selector .box
to apply your rule to any element that has the class box
:
.box {
border: 1px solid #ccc;
}
有时,制定更具体的内容是有意义的。然而,这通常是一种例外,而不是通常的做法。
¥There will be times when making something more specific makes sense; however, this will generally be an exception rather than usual practice.
将大型样式表分解为多个较小的样式表
¥Break large stylesheets into multiple smaller ones
如果网站的不同部分有非常不同的样式,你可能需要一个包含所有全局规则的样式表,以及一些包含这些部分所需的特定规则的较小样式表。你可以从一页链接到多个样式表,并且应用级联的正常规则,稍后链接的样式表中的规则位于先链接的样式表中的规则之后。
¥In cases where you have very different styles for distinct parts of the site, you might want to have one stylesheet that includes all the global rules, as well as some smaller stylesheets that include the specific rules needed for those sections. You can link to multiple stylesheets from one page, and the normal rules of the cascade apply, with rules in stylesheets linked later coming after rules in stylesheets linked earlier.
例如,我们可能有一个在线商店作为网站的一部分,其中大量 CSS 仅用于设计商店所需的产品列表和表单。将这些内容放在不同的样式表中,仅链接到商店页面上是有意义的。
¥For example, we might have an online store as part of the site, with a lot of CSS used only for styling the product listings and forms needed for the store. It would make sense to have those things in a different stylesheet, only linked to on store pages.
这可以让你的 CSS 更容易组织起来,也意味着如果多个人正在处理 CSS,那么两个人需要同时处理同一个样式表的情况就会减少,从而导致源代码管理中的冲突。
¥This can make it easier to keep your CSS organized, and also means that if multiple people are working on the CSS, you will have fewer situations where two people need to work on the same stylesheet at once, leading to conflicts in source control.
其他有帮助的工具
¥Other tools that can help
CSS 本身并没有太多内置的组织方式;因此,CSS 的一致性程度很大程度上取决于你。Web 社区开发了各种工具和方法,可以帮助你管理更大的 CSS 项目。由于你在与其他人一起工作时可能会遇到这些辅助工具,而且它们通常很有帮助,因此我们提供了其中一些辅助工具的简短指南。
¥CSS itself doesn't have much in the way of in-built organization; therefore, the level of consistency in your CSS will largely depend on you. The web community has developed various tools and approaches that can help you to manage larger CSS projects. Since you are likely to come across these aids when working with other people, and since they are often of help generally, we've included a short guide to some of them.
CSS 方法论
¥CSS methodologies
你无需制定自己的 CSS 编写规则,而可以从采用社区已经设计并在许多项目中测试过的方法之一中受益。这些方法本质上是 CSS 编码指南,采用非常结构化的方法来编写和组织 CSS。通常,如果你根据该项目的一组自定义规则编写并优化每个选择器,它们往往会比你可能会更详细地呈现 CSS。
¥Instead of needing to come up with your own rules for writing CSS, you may benefit from adopting one of the approaches already designed by the community and tested across many projects. These methodologies are essentially CSS coding guides that take a very structured approach to writing and organizing CSS. Typically they tend to render CSS more verbosely than you might have if you wrote and optimized every selector to a custom set of rules for that project.
然而,通过采用一种结构,你确实获得了很多结构。由于其中许多系统被广泛使用,其他开发者更有可能理解你正在使用的方法,并能够以相同的方式编写自己的 CSS,而不必从头开始制定自己的个人方法。
¥However, you do gain a lot of structure by adopting one. Since many of these systems are widely used, other developers are more likely to understand the approach you are using and be able to write their own CSS in the same way, rather than having to work out your own personal methodology from scratch.
OOCSS
你将遇到的大多数方法都归功于面向对象 CSS (OOCSS) 的概念,这是一种由 妮可·沙利文的作品 流行起来的方法。OOCSS 的基本思想是将 CSS 分离为可重用的对象,这些对象可以在站点上任何需要的地方使用。OOCSS 的标准示例是描述为 媒体对象 的模式。这是一种一侧具有固定大小的图片、视频或其他元素,另一侧具有灵活内容的模式。这是我们在评论、列表等网站上随处可见的一种模式。
¥Most of the approaches you will encounter owe something to the concept of Object Oriented CSS (OOCSS), an approach made popular by the work of Nicole Sullivan. The basic idea of OOCSS is to separate your CSS into reusable objects, which can be used anywhere you need on your site. The standard example of OOCSS is the pattern described as The Media Object. This is a pattern with a fixed size image, video or other element on one side, and flexible content on the other. It's a pattern we see all over websites for comments, listings, and so on.
如果你不采用 OOCSS 方法,你可以为使用此模式的不同位置创建自定义 CSS,例如,通过创建两个类,一个称为 comment
,其中包含一系列用于组件部分的规则,另一个称为 list-item
,几乎包含 除了一些微小的差异外,与 comment
级的规则相同。这两个组件之间的区别是列表项有底部边框,注释中的图片有边框,而列表项图片没有。
¥If you are not taking an OOCSS approach you might create a custom CSS for the different places this pattern is used, for example, by creating two classes, one called comment
with a bunch of rules for the component parts, and another called list-item
with almost the same rules as the comment
class except for some tiny differences. The differences between these two components are the list-item has a bottom border, and images in comments have a border whereas list-item images do not.
.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 - 通常是媒体对象形状的事物的基类。然后我们添加一个额外的类来处理这些微小的差异,从而以特定的方式扩展该样式。
¥In OOCSS, you would create one pattern called media
that would have all of the common CSS for both patterns — a base class for things that are generally the shape of the media object. Then we'd add an additional class to deal with those tiny differences, thus extending that styling in specific ways.
.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
类:
¥In your HTML, the comment would need both the media
and comment
classes applied:
<div class="media comment">
<img src="" alt="" />
<div class="content"></div>
</div>
列表项将应用 media
和 list-item
:
¥The list-item would have media
and list-item
applied:
<ul>
<li class="media list-item">
<img src="" alt="" />
<div class="content"></div>
</li>
</ul>
Nicole Sullivan 在描述和推广这种方法方面所做的工作意味着,即使今天不严格遵循 OOCSS 方法的人通常也会以这种方式重用 CSS ——它已经进入我们的理解,作为处理一般事物的好方法。
¥The work that Nicole Sullivan did in describing this approach and promoting it means that even people who are not strictly following an OOCSS approach today will generally be reusing CSS in this way — it has entered our understanding as a good way to approach things in general.
BEM
BEM 代表块元素修改器。在 BEM 中,块是独立的实体,例如按钮、菜单或徽标。元素类似于列表项或与其所在块相关联的标题。修饰符是块或元素上的一个标志,用于更改样式或行为。由于 CSS 类中大量使用破折号和下划线,你将能够识别使用 BEM 的代码。例如,查看有关 BEM 命名约定 的页面中应用于此 HTML 的类:
¥BEM stands for Block Element Modifier. In BEM a block is a stand-alone entity such as a button, menu, or logo. An element is something like a list item or a title that is tied to the block it is in. A modifier is a flag on a block or element that changes the styling or behavior. You will be able to recognize code that uses BEM due to the extensive use of dashes and underscores in the CSS classes. For example, look at the classes applied to this HTML from the page about BEM Naming conventions:
<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 命名约定。
¥The additional classes are similar to those used in the OOCSS example; however, they use the strict naming conventions of BEM.
BEM 广泛应用于大型 Web 项目中,许多人都以这种方式编写 CSS。即使在教程中,你也可能会遇到使用 BEM 语法的示例,而不会提及 CSS 为何以这种方式构建。
¥BEM is widely used in larger web projects and many people write their CSS in this way. It is likely that you will come across examples, even in tutorials, that use BEM syntax, without mentioning why the CSS is structured in such a way.
在 CSS Tricks 上阅读有关此系统 BEM 101 的更多信息。
¥Read more about this system BEM 101 on CSS Tricks.
其他常用系统
¥Other common systems
有大量此类系统正在使用中。其他流行的方法包括 Jonathan Snook 创建的 CSS 可扩展和模块化架构 (SMACSS)、Harry Roberts 的 ITCSS 以及最初由 Yahoo! 创建的 原子 CSS (ACSS)。如果你遇到使用其中一种方法的项目,那么优点是你将能够搜索并找到许多文章和指南来帮助你了解如何以相同的风格进行编码。
¥There are a large number of these systems in use. Other popular approaches include Scalable and Modular Architecture for CSS (SMACSS), created by Jonathan Snook, ITCSS from Harry Roberts, and Atomic CSS (ACSS), originally created by Yahoo!. If you come across a project that uses one of these approaches, then the advantage is that you will be able to search and find many articles and guides to help you understand how to code in the same style.
使用这种系统的缺点是它们看起来过于复杂,尤其是对于较小的项目。
¥The disadvantage of using such a system is that they can seem overly complex, especially for smaller projects.
构建 CSS 系统
¥Build systems for CSS
组织 CSS 的另一种方法是利用前端开发者可用的一些工具,这使你可以采用稍微更编程化的方法来编写 CSS。有许多工具,我们将其称为预处理器和后处理器。预处理器运行原始文件并将它们转换为样式表,而后处理器则获取完成的样式表并对其执行某些操作 - 也许是为了优化它以使其加载速度更快。
¥Another way to organize CSS is to take advantage of some of the tooling that is available for front-end developers, which allows you to take a slightly more programmatic approach to writing CSS. There are a number of tools, which we refer to as pre-processors and post-processors. A pre-processor runs over your raw files and turns them into a stylesheet, whereas a post-processor takes your finished stylesheet and does something to it — perhaps to optimize it in order that it will load faster.
使用任何这些工具都要求你的开发环境能够运行执行预处理和后处理的脚本。许多代码编辑器可以为你执行此操作,或者你可以安装命令行工具来提供帮助。
¥Using any of these tools will require that your development environment be able to run the scripts that do the pre- and post-processing. Many code editors can do this for you, or you can install command line tools to help.
最流行的预处理器是 Sass。这不是 Sass 教程,因此我将简要解释 Sass 可以执行的一些操作,即使你不使用任何其他 Sass 功能,这些操作在组织方面也非常有帮助。如果你想了解有关 Sass 的更多信息,请从 Sass 基础知识 文章开始,然后继续阅读他们的其他文档。
¥The most popular pre-processor is Sass. This is not a Sass tutorial, so I will briefly explain a couple of the things that Sass can do, which are really helpful in terms of organization even if you don't use any of the other Sass features. If you want to learn a lot more about Sass, start with the Sass basics article, then move on to their other documentation.
定义变量
¥Defining variables
CSS 现在有了原生 自定义属性,使得这个功能变得越来越不重要。然而,你可能使用 Sass 的原因之一是能够将项目中使用的所有颜色和字体定义为设置,然后在项目中使用该变量。这意味着,如果你发现自己使用了错误的蓝色色调,则只需在一处进行更改即可。
¥CSS now has native custom properties, making this feature increasingly less important. However, one of the reasons you might use Sass is to be able to define all of the colors and fonts used in a project as settings, then to use that variable around the project. This means that if you realize you have used the wrong shade of blue, you only need change it in one place.
如果我们创建一个名为 $base-color
的变量(如下面第一行所示),那么我们可以通过样式表中任何需要该颜色的地方使用它。
¥If we created a variable called $base-color
, as in the first line below, we could then use it through the stylesheet anywhere that required that color.
$base-color: #c6538c;
.alert {
border: 1px solid $base-color;
}
编译为 CSS 后,你将在最终样式表中得到以下 CSS。
¥Once compiled to CSS, you would end up with the following CSS in the final stylesheet.
.alert {
border: 1px solid #c6538c;
}
编译组件样式表
¥Compiling component stylesheets
我上面提到组织 CSS 的一种方法是将样式表分解为更小的样式表。使用 Sass 时,你可以将其提升到另一个级别,并拥有许多非常小的样式表 - 甚至可以为每个组件提供单独的样式表。通过使用 Sass(部分)中包含的功能,这些都可以一起编译成一个或少量样式表,以实际链接到你的网站。
¥I mentioned above that one way to organize CSS is to break down stylesheets into smaller stylesheets. When using Sass you can take this to another level and have lots of very small stylesheets — even going as far as having a separate stylesheet for each component. By using the included functionality in Sass (partials), these can all be compiled together into one or a small number of stylesheets to actually link into your website.
因此,例如,对于 partials,你可以在一个目录中拥有多个样式文件,例如 foundation/_code.scss
、foundation/_lists.scss
、foundation/_footer.scss
、foundation/_links.scss
等。然后你可以使用 Sass @use
规则将它们加载到其他样式表中:
¥So, for example, with partials, you could have several style files inside a directory, say foundation/_code.scss
, foundation/_lists.scss
, foundation/_footer.scss
, foundation/_links.scss
, etc. You could then use the Sass @use
rule to load them into other stylesheets:
// foundation/_index.scss
@use "code";
@use "lists";
@use "footer";
@use "links";
如果部分内容全部加载到索引文件中,如上所述,你可以一次性将整个目录加载到另一个样式表中:
¥If the partials are all loaded into an index file, as implied above, you can then load that entire directory into another stylesheet in one go:
// style.scss
@use "foundation";
注意:尝试 Sass 的一个简单方法是使用 CodePen — 你可以在笔的设置中为 CSS 启用 Sass,然后 CodePen 将为你运行 Sass 解析器,以便你可以看到应用了常规 CSS 的结果网页。有时你会发现 CSS 教程在其 CodePen 演示中使用了 Sass 而不是纯 CSS,因此了解一点它会很方便。
¥Note: A simple way to try out Sass is to use CodePen — you can enable Sass for your CSS in the Settings for a Pen, and CodePen will then run the Sass parser for you in order that you can see the resulting webpage with regular CSS applied. Sometimes you will find that CSS tutorials have used Sass rather than plain CSS in their CodePen demos, so it is handy to know a little bit about it.
后处理以进行优化
¥Post-processing for optimization
如果你担心增加样式表的大小(例如,通过添加大量附加注释和空格),那么后处理步骤可能是通过删除生产版本中不需要的任何内容来优化 CSS。用于执行此操作的后处理器解决方案的一个示例是 cssnano。
¥If you are concerned about adding size to your stylesheets, for example, by adding a lot of additional comments and whitespace, then a post-processing step could be to optimize the CSS by stripping out anything unnecessary in the production version. An example of a post-processor solution for doing this would be cssnano.
概括
¥Summary
这是我们构建块模块的最后一部分,正如你所看到的,你可以通过多种方式继续探索 CSS - 但现在你可以继续使用我们的评估来测试自己:第一个链接如下。
¥This is the final part of our building blocks module, and as you can see there are many ways in which your exploration of CSS can continue from this point — but now you can go on to testing yourself with our assessments: the first one is linked below.
要了解有关 CSS 布局的更多信息,请参阅 CSS 布局 模块。
¥To learn more about layout in CSS, see the CSS Layout module.
你现在还应该具备探索 MDN CSS 材料其余部分的技能。你可以查找属性和值,探索我们的 CSS 秘诀 以获取要使用的模式,或继续阅读一些特定指南,例如我们的 CSS 网格布局指南。
¥You should also now have the skills to explore the rest of the MDN CSS material. You can look up properties and values, explore our CSS Cookbook for patterns to use, or continue reading in some of the specific guides, such as our Guide to CSS grid layout.