Sass 样式指南

Avatar of Chris Coyier
Chris Coyier 发布

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

随着越来越多的人使用 Sass 编写代码,我们有必要考虑如何对其进行格式化。 CSS 样式指南 非常普遍,因此我们可以将其扩展到涵盖 Sass 独有的选择。

以下是我一直以来比较倾向的一些想法。 或许它们对您有所帮助,或者能帮助您形成自己的想法。 如果您想查看更多示例,Sass 指南 也是一个不错的选择。

使用您常规的 CSS 格式化规则/样式指南

这篇文章主要讨论 Sass 特定的内容,但作为基础,您应该遵循您已经在使用的任何良好的 CSS 格式化指南。 如果您还没有,这份 样式指南汇总 可能对您有所帮助。 这包括以下方面:

  1. 保持缩进一致
  2. 保持冒号/大括号前后空格的使用一致
  3. 每行一个选择器,每行一条规则
  4. 将相关的属性放在一起
  5. 制定类名命名方案
  6. 不要使用 ID #hotdrama
  7. 等等

首先列出 @extend

.weather {
  @extend %module; 
  ...
}

立即知道这个类继承了来自其他地方的另一整套规则是很好的。 另一个好处是,覆盖该继承规则集的样式变得更容易。

何时使用 @extend 与 @include 可能有点棘手。 Harry 对 区分两者做了很好的工作,并提供了关于如何使用它们的思考。

接下来列出 @include

.weather {
  @extend %module; 
  @include transition(all 0.3s ease-out);
  ...
}

接下来是用于混合和其它函数的 @includes。 同样,将其放在顶部附近以供参考也很不错,但也允许覆盖。 您可能还想决定是否要将用户编写的 @includes 和供应商提供的 @includes 分开。

接下来列出“常规”样式

.weather {
  @extend %module;
  @include transition(all 0.3s ease-out);
  background: LightCyan;
  ...
}

在 @extends 和 @includes 之后添加常规样式,以便在需要时正确覆盖这些属性。

接下来嵌套伪类和伪元素

.weather {
  @extend %module;
  @include transition(all 0.3s ease-out);
  background: LightCyan;
  &:hover {
    background: DarkCyan;
  }
  &::before {
    content: "";
    display: block;
  }
  ...
}

伪元素和伪类与元素本身直接相关,因此,我们首先嵌套它们,然后再嵌套其它选择器。 将伪元素放在类之前似乎更容易阅读,但是哪一个放在前面完全是个人喜好。 无论哪种方式,最好将元素与其它元素放在一起,将类与其它类放在一起。

最后嵌套选择器

.weather {
  @extend %module; 
  @include transition(all 0.3s ease);
  background: LightCyan;
  &:hover {
    background: DarkCyan;
  }
  &::before {
    content: "";
    display: block;
  }
  > h3 {
    @include transform(rotate(90deg));
    border-bottom: 1px solid white;
  }
}

嵌套内容之后没有任何内容。 并且嵌套选择器内部应遵循与上述相同的顺序。

不要编写供应商前缀

供应商前缀是时间敏感的事情。 随着浏览器随着时间的推移而更新,对它们的需要将逐渐消失。 如果您使用 Autoprefixer 在编译 Sass 时,则永远不必编写它们。

或者,您可以使用 Compass 和 Bourbon 等库提供的 @mixins。 或者自己编写。 尽管使用 @mixins 来实现供应商前缀仍然不如 Autoprefixer 方便,并且仍然需要一些维护,但它仍然比手动编写要好。

最大嵌套深度:三层

.weather {
  .cities {
    li {
      // no more!
    }
  }
}

如果嵌套深度超过三层,那么很有可能您编写了一个糟糕的选择器。 糟糕之处在于它过于依赖 HTML 结构(脆弱)、过于具体(过于强大)并且不太可重用(没有用处)。 它也处于难以理解的边缘。

如果您真的想使用标签选择器,因为类的事情变得对您来说太多了,您可能希望对其进行非常具体的说明以避免不必要的级联。 并可能甚至利用 @extend,以便它在 CSS 方面具有可重用性的好处。

.weather
  > h3 {
    @extend %line-under;
  }
}

最大嵌套行数:50 行

如果 Sass 的嵌套块超过 50 行,则很有可能它不适合在一个代码编辑器屏幕上显示,并且开始变得难以理解。 嵌套的重点是方便和帮助进行心理分组。 如果它损害了这一点,请不要使用它。

全局和特定部分的 Sass 文件只是目录

换句话说,其中没有直接的样式。 强制自己将所有样式组织成组件部分。

首先列出供应商/全局依赖项,然后是作者依赖项,然后是模式,最后是部件

最终它成为一个易于理解的目录

/* Vendor Dependencies */
@import "compass";

/* Authored Dependencies */
@import "global/colors";
@import "global/mixins";

/* Patterns */
@import "global/tabs";
@import "global/modals";

/* Sections */
@import "global/header";
@import "global/footer";

像 Compass、颜色和混合这样的依赖项根本不会生成任何编译后的 CSS,它们纯粹是代码依赖项。 接下来列出模式意味着更具体的“部件”(随后出现)具有覆盖模式的能力,而无需进行特异性冲突。

分成尽可能多的较小的文件

将文件拆分成多个较小的文件没有任何损失。 尽可能多地拆分,直到感觉对项目有好处为止。 我知道我发现跳转到较小的特定文件并浏览它们比跳转到较少/较大的文件更容易。

...

@import "global/header/header/";
@import "global/header/logo/";
@import "global/header/dropdowns/";
@import "global/header/nav/";
@import "global/header/really-specific-thingy/";

我可能会直接在 global.scss 中执行此操作,而不是让 global @import 一个包含其自身子导入的 _header.scss 文件。 所有这些子导入可能会变得难以控制。

通配符匹配 如果导入文件过多,可能会有所帮助。

部分文件命名为 _partial.scss

这是一个常见的命名约定,表示此文件不应单独编译。它可能存在依赖关系,导致无法单独编译。就我个人而言,我喜欢在“实际”文件名中使用连字符,例如 _dropdown-menu.scss。

本地编译并使用 Source Map

在开发过程中,本地编译 Sass 使用哪种格式(例如 expanded、compressed 等)可能并不重要,只要你生成了 Source Map 即可。

这是你在编译 Sass 时的一个标志。

$ sass sass/screen.scss:stylesheets/screen.css --sourcemap

尽管你可能不会通常这样编译 Sass,但总会有某种方式可以配置你用来编译 Sass 的工具,使其生成 Source Map。当你拥有它们时,这意味着 DevTools 会显示 Sass 代码的位置,这非常(非常)有用。

这里有一些相关的链接:

部署时,编译压缩后的代码

线上网站应该始终只包含压缩后的 CSS 文件。并且应该使用远期过期头信息进行 gzip 压缩。

不要提交 .css 文件

这可能需要一些 DevOps 工作,但如果 .css 文件甚至不在你的仓库中,那就非常棒了。编译过程发生在部署期间。因此,你在仓库中看到的只有你精心格式化的 Sass 文件。这使得 diff 也变得有用。diff 是版本控制提供商提供的关于代码更改的比较视图。压缩后的 CSS 文件的 diff 毫无用处。

多加注释

在代码中留下注释很少会让人后悔。它要么有用,要么很容易忽略。注释在编译成压缩代码时会被去除,因此没有任何成本。

.overlay {
  // modals are 6000, saving messages are 5500, header is 2000
  z-index: 5000; 
}

说到注释,你可能希望对其进行标准化。Sass 中的 // 语法非常不错,尤其是在块注释中,因此更容易注释/取消注释单个行。

将所有常用数字和有意义的数字转换为变量

如果你发现自己反复使用除 0 或 100% 之外的数字,它可能应该成为一个变量。因为它可能具有意义并控制一致性,因此能够批量调整它可能很有用。

如果一个数字显然具有强烈的意义,这也是将其转换为变量的用例。

$zHeader: 2000;
$zOverlay: 5000;
$zMessage: 5050;

.header {
  z-index: $zHeader;
}
.overlay {
  z-index: $zOverlay;
}
.message {
  z-index: $zMessage;
}

理想情况下,这些数字可能应该保存在一个单独的文件中,并通过 @import 作为依赖项引入。这样,你就可以在一个地方跟踪整个 z-index 栈。但是,如果变量的作用域限定在类中,那么确保它们在任何其他规则之前出现是有意义的。

.accordion {
  $accordion-header-color: $primary-color;
  $accordion-padding: 1em;
  
  @extend %module;
  @include transition(all 0.3s ease-out);
  background: $accordion-header-color;
  padding: $accordion-padding;
}

将所有颜色转换为变量

除了白色和黑色。颜色很可能不是一次性的,即使你认为它是,一旦它成为一个变量,你可能会发现它在其他地方也有用途。这些颜色的变体通常可以通过 Sass 的 颜色函数(如 lighten() 和 darken())来处理,这使得更新颜色变得更容易(在一个地方更改,整个配色方案都会更新)。

嵌套并命名你的媒体查询

在 Sass 中嵌套媒体查询的能力意味着 1) 你不必在其他地方重写选择器,这可能会导致错误 2) 你正在覆盖的规则非常清晰和明显,而当它们位于 CSS 底部或在不同的文件中时,通常并非如此。

.sidebar {
  float: right;
  width: 33.33%;
  @include bp(mama-bear) {
    width: 25%;
  }
}

更多信息以及如何正确命名它们的重要性。

最后处理不优雅的代码

在你的全局样式表中,最后 @import 一个 _shame.scss 文件。

@import "compass"

...

@import "shame"

如果你需要进行快速修复,你可以在此处进行。稍后当你拥有充足的时间时,可以将修复移动到正确的结构/组织中。 了解更多。

最终输出由你决定

Sass 不会做任何你没有告诉它的事情,所以声称 Sass 输出臃肿,就等于声称你编写了臃肿的代码。编写 Sass 代码,使其最终的 CSS 输出与你在没有 Sass 的情况下编写的一样。