随着越来越多的人使用 Sass 编写代码,我们有必要考虑如何对其进行格式化。 CSS 样式指南 非常普遍,因此我们可以将其扩展到涵盖 Sass 独有的选择。
以下是我一直以来比较倾向的一些想法。 或许它们对您有所帮助,或者能帮助您形成自己的想法。 如果您想查看更多示例,Sass 指南 也是一个不错的选择。
使用您常规的 CSS 格式化规则/样式指南
这篇文章主要讨论 Sass 特定的内容,但作为基础,您应该遵循您已经在使用的任何良好的 CSS 格式化指南。 如果您还没有,这份 样式指南汇总 可能对您有所帮助。 这包括以下方面:
- 保持缩进一致
- 保持冒号/大括号前后空格的使用一致
- 每行一个选择器,每行一条规则
- 将相关的属性放在一起
- 制定类名命名方案
- 不要使用 ID #hotdrama
- 等等
首先列出 @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 预处理器
- (Sass 教程) 使用 Sass 3.3 中的 Source Map
部署时,编译压缩后的代码
线上网站应该始终只包含压缩后的 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 的情况下编写的一样。
在高等教育领域,有很多利益相关者,潜在的员工流动性很大,并且有很多继承的代码。因此,我们最近创建了一个 CSS/SASS 样式指南,以确保我们保持一致。仍然有很多从未有机会使用 SASS 的人,因此虽然这不是样式指南的一部分,但我们确实包含了一个 Sass 入门 Markdown 文件,我们如何编译[我们都在使用 Windows],Sublime Text 代码片段等等,以期有一天我们会继续前进,并且某些倒霉蛋将不得不处理我们所有的代码——如果新人不认识 .scss 会怎么样?
我们所做的另一件事是真正将我们的所有样式抽象化到极致,以便快速查看所有 _partials 就能清楚地了解全局样式表包含的内容。例如,你可能会查看仓库并看到,“哦,这里有关于警报、按钮、表单、面包屑的规则,但没有工具提示。”这样,实际上没有人需要打开样式表来确定是否有该样式。
我真的很喜欢 _shame.scss 文件的想法,我经常发现自己不得不在项目结束时仓促地插入一些难看的代码,并且我讨厌将它留在我的主要样式中。我也需要开始限制我的嵌套,它正在成为 Web 设计师的新“div-itis”。
总的来说,这些建议都很棒,我肯定以后会重新评估我编写 Sass 的方式!
我也喜欢 _shame.scss 的想法,尽管我发现 90% 的时间我的所有令人尴尬的东西都放在我的 _ie.scss 中 :P
哈哈,这太对了。IE 一直以来都是我 cbc 生涯的梦魇,而且还会继续下去。顺便说一句,我喜欢在代码中添加大量注释的想法。我曾经在一个 SEO 公司工作,他们声称这样做对爬虫不利。但作为一个程序员,它只是让我更容易添加一些注释,以便 6 个月后如果需要快速修改时,可以轻松查看。很棒的文章!
有趣的是,我的做法也正是如此。我想提到的另一个关于嵌套的要点是,尽量不要在任何地方使用标签选择器作为最深的层级,仅仅是为了性能考虑,即使在嵌套格式中它看起来很优雅。
精彩的文章,我想把你的结尾段落印成贴纸,贴在每个抱怨预处理器生成糟糕的生产代码的开发人员的键盘上。
我不太理解限制嵌套的意义。例如
它使 a 位于你下一级样式的最底层,变得非常具体,在你提到的导航示例中,这可能不是一个大问题,导航是唯一一个即使在原生 CSS 中,我们很多人也会编写
但是假设你的客户随后添加了一个下拉菜单,你将不得不将其嵌套,代码很快就会变得混乱。
编写一些示例代码,嵌套一些样式,然后尝试在样式表中进一步覆盖一些嵌套样式,你会发现嵌套样式变得过于具体,导致你必须在任何地方都编写很长的选择器,或者诉诸更糟糕的做法,例如 !important。
此外(虽然在我看来问题不大)
它还会稍微影响性能,因为浏览器从右到左读取样式,所以在这种情况下,它必须弄清楚
好的,这是一个锚点
并且它是列表项的子集
并且这是无序列表的子集
它是 nav 元素的子集
在它能够分配正确的样式之前。在大多数设备上,这影响不大,但如果相关的浏览器在旧款手机上,并且你的所有样式都嵌套了,它就会产生细微的差别。
通过使用类而不是嵌套,你可以让你的代码运行得更快一些,这肯定是一件好事。
尽管如此,基于列表的导航是唯一一个可以合理地使用嵌套的地方!你的代码,你的规则……
除了 Simon 所说的,持续嵌套会使选择器不必要地变得很具体。你应该只在绝对必要时才进行嵌套。
li
样式真的需要位于ul
内部吗?它们不适合放在ol
内部吗?a
标签的样式真的需要位于ul
内部的li
内部吗?如果它们位于div
内部,你不会希望使用相同的样式吗?如果你的标记类似于
那么你应该尝试像这样嵌套你的 SCSS
你的 SCSS 嵌套不需要完全匹配你的标记嵌套。它只需要足够具体以防止代码样式泄漏到意外的元素中,并且不应比这更具体。
答案在这里
避免嵌套选择器以获得更模块化的 CSS
文章中的建议很好,除了任意限制嵌套层级。
我非常倾向于将文档结构视为有向无环图,这为将其与面向对象编程中的有向无环对象图(一种非常常见的结构)进行类比提供了正式的基础。因此,将嵌套限制到任意级别,这与将对象图的深度限制到任意级别没有区别。两者都是无稽之谈。
Dale Sande 的评论 是嵌套限制的唯一理由:模块化 CSS。这篇文章中省略了这个解释,这很明显。但是,使用这种方法,嵌套限制将恰好为 0(无嵌套)。我个人不喜欢这种方法,因为它与我的 DAG 心智模型不符,而是迫使将 HTML 结构扁平化到全局的 CSS 选择器空间 中。
但是,他链接到的文章中的方法只是实现模块化 CSS 的众多方法之一,它也并非没有局限性。(我个人更喜欢一种利用 CSS 的优势(子组合器
>
)来提高性能和生产力的方法——我的博客上有详细介绍,如有兴趣)。这里的问题是,你创建了一个具有不必要高特异性的规则,因此很难随后覆盖这样定义的规则(除非你使用
!important
,但这并不是一个很好的实践)。还要考虑你正在编写的内容的性能:浏览器将从右到左解析该规则,因此为了应用该样式,它必须检查
a
元素是否嵌套在li
中,li
嵌套在ul
中,ul
最终嵌套在nav
中。也许你可以简单地编写
如果你可以在每个页面上拥有多个
nav
元素,你可能希望将该样式应用于特定的导航,因此你可以为其分配一个id
属性或role="navigation"
属性,你的代码块将变为嵌套过深的选取器也会降低网页/应用的性能。
很棒的列表。
关于:嵌套 - 我得出的结论是,“永远不要嵌套”是一个好的规则(与“永远不要使用 ID 进行样式”的原因相同,并且出于同样的原因)。
一旦你开始嵌套规则,就会为你的团队/未来的自己带来特异性方面的麻烦,并限制样式的可重用性。
我也开始尝试使用 BEM 类命名,尽管它一开始会让你感到困惑,但我相信它是未来,并且任何嵌套都会使 BEM 难以理解。
唯一的例外是媒体查询 - 将它们嵌套对我来说很有意义。
我也很喜欢 Sass 中的注释。我越来越倾向于为每个类编写注释
.classname { // 通常(如果适用),此样式强调文本等..
font-weight: bold;
}
尽管这看起来很麻烦,但它确实迫使你思考你正在编写的样式以及将来如何重用它们。
我还将大多数样式保留在主 .scss 文件中,并使用一些导入文件,这些文件对所有项目都有用
_compass.scss
_reset.scss(我自己的重置,尝试过并多次对 normalize 感到沮丧)
_components.scss(包含变量和 mixin 的文件)
_helpers.scss(来自 H5BP 的 .visuallyhidden、clearfix 等)
_grid.scss(我自己的基于 Twitter Bootstrap 的网格),如果我使用它的话
_placeholders(一个充满了不可见类的文件(%),仍然不确定处理此类问题的最佳方法)
_shame.scss(真是个绝妙的想法!)
然后将所有独特的样式放在一个文件中。我尝试将其拆分为排版、结构等,但发现这浪费了我的时间,因为我需要打开我需要的文件并在文件中搜索,所以又回到了一个主文件。如果在团队中工作,我相信将文件拆分为部分文件会很有意义。
尽管如此,我认为真正重要的是你的样式指南/编码约定对你和你的团队有意义。
使用双斜杠进行注释还可以确保你不会破坏 SASS 可以输出的错误消息。
如果块注释靠近你的错误,它会终止 SASS 用于在生成的 CSS 文件中输出回溯的块注释
很棒的文章。
我认为唯一剩下的问题是变量的放置位置。我将它们放在顶部,在 @extend 之前,如下所示
据我所知,变量在 Sass/Compass 中本身并没有作用域,但我同意它们应该像那样放在顶部。
变量本身可以具有作用域,但很容易被覆盖。确实,如果你只在选择器内部定义一个变量,那么它就被限制在该选择器范围内,不能在其他情况下使用。例如以下示例
但是,如果你在全局范围内引入一个新变量,那么 Sass 将允许级联在任何用例中覆盖该变量,即使它被限制在选择器范围内。
毫无疑问,Sass 的真正优势之一是使用全局变量在 CSS 规则中设置值。
在这个示例中,我设置了全局变量
$var: orange
,即使在第三个选择器中我没有在选择器中设置作用域变量,全局变量也会被选择器中作用域变量的最后一个实例覆盖。我们的输出 CSS 看起来像这样
唯一真正具有作用域的变量是在 Mixin 和 Function 内部。
你可以在 SassMeister.com 上尝试此示例。
这个谬论仍然存在,这太令人失望了,尤其是在一篇关于 Sass/Less 的文章中(其中应该鼓励样式分离!)。CSS 将始终依赖于 HTML,而 HTML 的职责不仅仅是为了方便 CSS 工作。
对你的样式进行抽象,并将这些抽象应用于正确选择器。
如果你喜欢,你可以称之为谬论,但我永远会将诸如
.main nav ul li a
之类的东西称为糟糕的选择器。这是过度嵌套的结果,它曾经多次让我头疼,我已经克服了它。说像
div.foo span a strong .bar
这样的选择器是一个糟糕的选择器,因为它过于具体,因为div.foo .bar
在匹配正确元素方面同样有效,这是一种说法。你应该编写尽可能短的选择器来精确匹配你需要的内容。你节省的所有这些字节都会累积起来。另一种说法是“不要这样做”,因为这是过早优化。为所有链接添加一个类,因为这比像
nav > ul > li > a
这样的选择器(用于匹配顶级列表中的链接)快 20 毫秒,这简直是愚蠢的。值得阅读:http://www.stevesouders.com/blog/2009/03/10/performance-impact-of-css-selectors/
这更多的是关于使用后代选择器而不是子选择器。
像
.main nav ul li a
这样的东西被认为是不好的(缓慢,可能存在问题),但是我并不是那些建议你为 HTML 中的每个元素添加一个类的人,我也认为这很糟糕。但是,如果你使用子选择器
.main>nav>ul>li>a
(我们现在终于可以使用它了,因为它现在可以安全地完全忽略 IE6 了)
…那么这样更好。它肯定快得多,也清晰得多,并且不会引入潜在的不清楚的影响。但是通常你不需要使用这么长的选择器。
我总是说,避免极端观点。例如,说“永远、永远不要在 CSS 中使用 ID 选择器”是愚蠢的。
另一个需要标准化的好玩的事情是文档中的注释样式。进入一个新的项目,之前的编码人员使用不同的注释样式来表示代码的不同部分,这可能会让人头疼。
这个样式指南与我自己的偏好非常匹配,但即使有人不一定喜欢它,我仍然建议坚持某种指南。一致性很重要。
一个小问题:
@include
在普通 css 规则之前更有意义。如果我包含一个按钮或网格 mixin 并想单独调整它的样式,我需要在后面添加规则。占位符 - mixin - 样式按从最不具体到该选择器到最具体的顺序排列代码级联。100% 同意,mixins 应该先出现,利用级联,我的朋友!
我不得不部分同意你的观点,Rob。在大多数情况下,我们应该利用级联。我的常规规则实际上是将 includes 视为常规选择器,并在一个块中逻辑地对我的选择器进行分组,除非 includes 调用我知道会生成很多规则的 mixin,例如你示例中的
button
mixin。这正是我来这里想说的。@extends、@includes,然后是你的常规 CSS,每个都按字母顺序排列。如果需要,可以在中间添加换行符,但我发现没有换行符也足够容易阅读。
我同意 Mandy 的观点。我发现按字母顺序添加 CSS 样式也有助于我进行组织。
是的。我先使用 mixins,这样如果我需要覆盖 mixin 中的任何内容,我就可以做到。我将 extends 放在最后,只是为了感觉自己像个叛逆者。
我的正常情况是样式优先于背景和渐变。Compass(据我所知)不会输出带有渐变的纯色回退,所以我这样做
@Chris - 如果你将其写为“background-color”,你可以将其放在任何位置。顺序无关紧要。
是的,这是一个很好的观点。我经常认为回退是首先列出的 - 如果第二个/更高级的规则不起作用,它将回退到先前的选择器。但在这种情况下,渐变实际上是 background-image(即使作为 background 简写的一部分),而纯色是 background-color。因此,如果 background-image 失败,它将返回到 background-color - 正如你所说,它可以设置在任何位置。如果 background-image 成功,它无论如何都会位于 background-color 之上。
好的观点,而且修复方法很巧妙。
顺便说一句,如果你使用 autoprefixer,你将永远不必再担心这个问题了 :) :) :)。
https://github.com/ai/autoprefixer
赞赏!我也这样操作。
@Niels 这是一个可能性陈述,而不是一个坚实的真实陈述,因此有“可能”前缀和免责声明。但是,层级超过三级的选择器应该很少见。导航示例
nav ul li a
可以简化为nav a
。你不需要指定锚点是列表项的后代,该列表项是无序列表的后代,该无序列表是<nav>
元素的后代。@Martin Bean
我不认为它们很少见,事实上,我相信它们非常普遍。一旦你开始使用 html 组件,事情往往会变得更加通用。
如果你进行公平的抽象或你的 css 样式(这是 css 预处理器的目的),这不成问题。它当然比在你的 html 中散布无用的类要好得多,这些类不会在项目之间传递,并且只匹配单个项目内的某些可视化效果。在我看来,这比 6 个元素的选择器更糟糕。
使用的注释是否有所不同,/* comment */ 与 // comment,这是否会影响它是否显示在编译后的 CSS 中?我以为是这样的,但可能是错的。
是的,
/* 这应该在编译时显示 */
// 这不会
但这取决于你选择输出类型。我建议压缩 CSS 输出,以便它在管道中变小 :)
典型的 /* comment */ 将显示在嵌套、展开和紧凑输出中,但不会显示在压缩输出中…除非你使用 !bang;例如
/! 注释将在压缩输出中编译;即添加版权声明/
sass-lang.com 上的注释信息
不错的文章。为什么有些开发人员总是喜欢类而不是 ID?我从未完全理解这一点,并且个人一直有意识地努力只在样式将在页面其他地方重复使用时使用类,如果它是一个突出的元素,例如侧边栏或页脚,或者我可能想要链接到或使用 jQuery 绑定元素的部分,我会使用 ID。
现在我正在使用 Sass 编写 CSS,并且可以使用 mixins、变量并轻松控制嵌套元素的样式。我想知道使用类而不是 ID 的优缺点是什么?
类是首选,因为 CSS 用于样式设计,如果你以模块化的方式编写样式,那么你就是在编写它们以便在页面上可能多次使用。因此,你将在类而不是 ID 上挂钩样式。
我知道一些开发人员发誓永远不要使用 ID(咳嗽 Harry Roberts 咳嗽),但我并不介意在孤立的情况下使用它们,例如
#content
作为我网站的主要内容包装器。此外,你也可以在类名称和 ID 上挂钩 JavaScript 功能;)
在 CSS 中使用 ID 的最大问题是,它们在特异性战争中过于强大。如果你曾经编写过使用 ID 的选择器,那么你几乎无法使用任何仅由类组成的选择器来覆盖它,除非你使用 256 个类。那样做简直是疯了。
你可能会认为这没问题,因为“我为什么要覆盖 ID 上的样式?页面上应该只有一个!”但是,在实践中,情况往往并非如此,尤其是在任何类型的复合选择器中。
感谢分享,Chris。我一直在尝试创建一个“样式指南”,我应该在我的 repo 中坚持使用它作为我的起点 - https://github.com/sturobson/a-slightly-bizarre-starting-point#sass
我还讨论了我的 Sass 的结构应该是什么 -
http://alwaystwisted.com/post.php?s=2013-01-07-structuring-my-sass-101-part-1
http://alwaystwisted.com/post.php?s=2013-01-07-structuring-my-sass-101-part-2
http://alwaystwisted.com/post.php?s=2013-01-08-structuring-my-sass-101-part-3
很高兴看到更多关于此的讨论和思考
感谢分享你的方法,Chris。这非常接近我组织 Sass 代码/文件的方式。
有一些
@include
语句我更喜欢放在声明块的顶部,比如来自 Compass 的@include pie-clearfix;
和@include inline-block;
。此外,我发现当嵌套选择器上面有空行时,它们更容易阅读/识别(即使有很好的语法高亮)。
所以这样
变成这样
我很想知道其他开发者是否也更喜欢在嵌套选择器上面加空行。
Chris,如果你不提交 CSS 文件,如何在开发服务器上编译?
你提交 .scss 或 .sass 文件
我同意,为什么要让你的生产服务器重新渲染 CSS 文件?我宁愿我的生产环境不包含任何可以修改的 sass/scss 文件。
@peter 提交并不一定意味着部署。理想情况下,你应该有一个“构建”流程,负责处理编译 Sass 或 CoffeeScript 等任务,以及连接、压缩、资产版本控制等操作。然后是一个“部署”流程,将所有文件放到正确的位置。
Jenkins (jenkins-ci.org) 和 CircleCI (circleci.com) 是用于此类流程自动化的流行持续集成工具。
另一种选择是使用诸如 deployhq.com 之类的工具。
我们这么做的主要原因是,当 Git 对比压缩的 CSS 文件(其中代码都在一行上)时,经常会卡住。因此,当我们两个人编辑同一个 SASS 文件,然后输出不同的 CSS,并且我们必须合并这些 CSS 文件时,Git 会完全崩溃。合并和维护主 SASS 文件更容易管理,并且冗余度也低得多。此外,当团队中的各个成员使用不同的库或不同的 SASS 版本等时,可能会出现问题。将 CSS 编译为 GIT 后挂钩可确保每个人都遵守标准。
始终以 @includes 开头……这在某种程度上似乎是合理的。在包含规则的 @includes 中,需要在覆盖其包含位置之间权衡一定程度的痛苦。有时最好将它们放在最后,以确保它们是最后调用的,并且不会被覆盖。虽然全局样式规则非常好,但我不知道是否应该逐个案例进行审查。
为什么所有人都讨厌嵌套超过 4 层?如果这是一个大问题,为什么 Sass 不能在 config.rb 中设置一个变量,将顶级限制在小于 4 层?
根据我的经验,在匆忙命名的 include 文件中搜索某个标签非常糟糕。
也许问题是人们写了太多的 CSS。
这是一篇很棒的文章,涉及 Sass 的一些强大功能。但是能力越大,责任越大(谁说的?)。无论如何,我强烈建议那些喜欢这篇文章的人阅读 清理你的 Sass 杂物抽屉。
“对于我们许多 Sass 初学者来说,或多或少都曾经创建过一个杂物抽屉式的文件。对大多数人来说,这是一个菜鸟错误,但对另一些人来说,这仍然是我们的架构和文件管理技术的持续问题。Sass 没有提供任何真正意义上的文件管理规则,因此开发人员基本上只能靠自己摸索。”
还有一个 幻灯片!
我已经养成了在主文件顶部(所有包含语句之后)保留所有 z-index 的习惯,因为它们通常是头痛的根源,并且很容易失控。
我不喜欢 Sass,我的 CSS 干净高效,为什么要重新发明轮子,真的……
好东西。我一直在 http://betterfrontend.com 上整理最佳实践列表——它是开源的,所以请随时添加你的反馈。
一个说明
你忘记了前面的 $
zOverlay: 5000;
zMessage: 5050;
一个建议
对颜色使用两级变量,一级声明,一级映射。
示例
/* 颜色声明 */
$red-1: #ff0000;
$red-2: #890000;
/* 颜色映射 */
$red-border: $red-1;
$alert: $red-2;
等等…
这样,你就可以更轻松地调整颜色,而不用担心它会如何影响不相关的样式。
希望这有帮助!
已修复 z-index 语法问题,谢谢。
我有点困惑,我之前是这样使用 SASS 的
也许是开发者设置 SASS 的方式……但我喜欢这样。非常干净。
这篇文章的标题有点误导——它写着 SASS,而应该写 SCSS。
SASS 的语法与 Haml 相同,但对于许多 CSS 用户来说,它显得比较陌生,因此在 3.0 版本中,他们引入了 SCSS(Sassy CSS),Chris 和大多数人都在使用它。
你可以将大多数(如果不是全部)概念应用到你的 SASS 工作流程中,而不会遇到太多麻烦。
哦哦哦哦哦哦哦哦。
标题以“Sass 样式指南”开头,然后代码是 SCSS
; /
不错的文章,Chris。
就我个人而言,我会对我的规则进行字母排序,因此我的 @extend 自然会排在第一位,@include 排在第二位,然后其余的样式在下面。我有点喜欢这样,而不是将 @include 放在底部,它将 SASS 方法与普通的纯 CSS 样式分隔开来。在“将所有常用数字和有意义的数字变量化”标题下的代码框中,第二个和第三个变量缺少美元符号。它们感觉被遗忘了。
只是一个小的拼写错误,在“将所有常用数字和有意义的数字变量化”标题下的代码框中,第二个和第三个变量缺少美元符号。它们感觉被遗忘了。
“最大嵌套:三层”。效仿 SMACSS,我实际上建议进一步收紧此限制:任何选择器在 DOM 中的跨度都不应超过三层。
http://smacss.com/book/applicability
>
全局和特定部分的 Sass 文件仅仅是目录
换句话说,其中没有直接的样式。 强制自己将所有样式组织成组件部分。
有人可以详细说明一下吗?
请参阅你引用的部分后面的示例。如果你遵循本指南,你的全局(或 main.scss 或 app.scss 或其他任何名称)应该仅仅是一个包含所有已创建的组件 scss 文件的导入列表
然后你的头部部分可能会有
如果你将样式很好地组织到组件中,那么全局和部分样式表的作用类似于教科书的目录,让新程序员能够很好地了解在哪里可以找到他们正在寻找的样式,而无需让他们翻阅所有 CSS。
Dan,谢谢。我现在明白了。
出于某种原因,我感觉这两部分相互矛盾,但在你分解之后,它就说得通了。
在 Sublime Text 2 中安装哪个包才能对 .scss 进行文本高亮?
谢谢……
顺便说一句,在 Windows 上……
如果你还没有安装 Package Control,我建议你安装它。然后,只需搜索“scss”,它会弹出一系列工具,第一个就是语法高亮。
即使你为黑色和白色设置了 #FFF 和 #000 的值,也请使用变量。你永远不知道你将来是否需要将其更改为米白色或较浅的黑色。
相关好文章:设计提示:永远不要使用黑色。
我昨天链接了这个,似乎没有被选中。我作为自己的“样板”的一部分,为自己编写了一个 SCSS“样式指南”。
基本上,它类似于 Chris 的这个,但有一些小的变体——
在考虑如何嵌套媒体查询后,我决定采用以下方法——
更多关于我如何操作的信息在这里——https://github.com/sturobson/a-slightly-bizarre-starting-point#sass
我曾在 1 月份写过一篇关于如何组织我的 SCSS 文件夹的文章。第一篇文章在这里 – http://alwaystwisted.com/post.php?s=2013-01-07-structuring-my-sass-101-part-1
我同意文章中的每个建议,除了一个:嵌套媒体查询。可能只是我个人看法,但我发现它是一种可怕的重复工作。通过将所有特定于断点的代码分离到一个专用的部分文件中,你只需要编写一次媒体查询,并且所有特定于该断点的样式都将位于一个文件中。我不明白为什么将所有这些内容在多个文件中碎片化和复制是一种最佳实践。
fchristant,这是一种你只需要决定哪种方法最适合你的情况。要么将特定元素的样式碎片化到多个媒体查询中,要么将媒体查询碎片化到多个元素中。你不能同时拥有两者。
我对媒体查询有一个问题。
如果你像文本中使用 mixin 的方式编写它,那么你的 CSS 中将会有很多媒体查询?当我检查我的样式时,这会在 CSS 中生成大约 40 个媒体查询 - 例如,用于设置菜单样式。这是否有点过载了?
我不建议在最后使用 @include。我会把它放在 @extends 的前面或后面。如果你把它放在最后,如果需要覆盖某些内容,就没有选择了。
冒泡媒体查询的使用一直存在争议。这是否会增加不必要的代码膨胀?是否存在性能问题?这些问题是否可以忽略不计,而我仅仅因为我的输出 CSS 看起来很丑而感到困扰?
我建议阅读Sass 和媒体查询,这是我去年 12 月写的一篇文章,其中对这个论点进行了探讨。
我还建议听一下与 Chris 的访谈,我们也在其中讨论了这个话题。简而言之,当你的 CSS 被压缩时,这无关紧要。
我们做的另一件事是在每个部分文件的顶部留下一条多行注释。这使得调试变得简单,而无需在出现问题时进入并打开行注释。然后,每个部分文件在以后调试时都易于识别。
很棒的良好实践清单!
伪选择器放在哪里?在其他嵌套选择器之前还是之后?
在嵌套媒体查询时,你是否也坚持嵌套 3 层的规则?
断点媒体查询算作另一层嵌套吗?
我通常对伪选择器以及任何使用“&”符号的选择器所做的是将它们写在后代选择器之后。所以,它看起来像这样
感谢您提供一篇精彩的文章!我很高兴我没有花更多时间编写自己的 SCSS 样式指南 - 它正在制作中,但这篇指南已经涵盖了一切!
不过,还有一个快速的问题:在一个典型的项目中,你使用多少个文件(模式和部分)?
我在阅读本文时想到的一件事是使用 mixin 和 z-index 变量创建“层”。我的 z-index 总是失控,如果我使用一个 _shame 文件,那么你就会在那里找到它们!
我认为伪选择器应该直接放在与父选择器相关的样式之后。它在概念上仍然是选择器本身的一部分,只是包装在一个伪元素中。
在我的 CSS-LESS 工作流程中(也可以应用于 SASS),我发现使用深度嵌套选择器来避免使用 !important 非常有用。
这是一个简单的例子
对我来说,嵌套是关于代码组织的。因此,我将嵌套结构与我的 HTML 保持一致,以及我可能需要的任何伪选择器。然后,我将所有可以从嵌套中分离出来而没有任何不良影响的选择器放在深度嵌套的下方。“分离出来”的部分是我进行主要编码的地方,同时保留嵌套作为参考(因为我不喜欢在窗口或编辑器的拆分视图中在 HTML 和 CSS 之间切换)。
好处是,在编译期间,任何未使用的深度嵌套选择器(即,它们为空)都不会被放入生成的 CSS 文件中(我使用 WP-LESS 与 wordpress 结合)。
深度嵌套的作用几乎与 !important 相同,因为它们是特定的。此外,由于我在代码中很少真正需要 !important(最多可能 10 次,遍布整个 wordpress 主题),因此任何性能问题都是微不足道的。
请记住,这仅在我构建不需要在页面其他地方重用的内容时适用。
这确实是一种平衡,人们需要找到它,不仅是为了浏览器性能和可重用性,也为了个人工作流程。
有谁知道为什么 Chrome 中的 SASS 调试停止工作了?
你是否确保在 chrome://flags 中仍然启用了“实验性开发者工具”,并且“支持 Sass”仍然处于选中状态?我知道我其中一个安装没有启用“实验性开发者工具”,而另一个(我之前启用了 Sass 调试)则取消了“支持 Sass”的选中状态。我不知道更新是否取消了它,但值得再次检查。
(更新,对于那些找到此页面并且尚未使 Chrome 的调试重新工作的人。)几周前我发现了原因。他们切换到实际的源映射,不再使用调试信息或行注释。从 3.3.0 版(目前处于 RC 状态)开始的 Sass 以及 Compass 的源映射分支包含一个输出源映射的标志。获取它们,你就可以恢复源映射。
Google 提供了一个方便的指南,用于启用源映射支持,但我发现它需要重新启动浏览器才能生效(我当时使用的指南没有提到这一点)。
这并不完全正确,具体取决于你如何拆分文件。
一个很好的例子是默认的 Octopress 主题采用的结构。它拆分文件的方式之一是通过排版、主题和布局。因此,选择器模式之间存在相当多的重叠。Sass 在编译时不会合并这些模式,因此最终的 CSS 可能包含相当多的选择器重复,这意味着渲染引擎必须多次查找相同的元素。这最终可能导致渲染速度变慢。
你的碎片化样式似乎不太容易出现这种情况,但我认为仍然值得记住这一点,以便你可以继续以避免重复选择器的方式拆分文件。
如何在本地以展开带行号的方式编译,并在生产环境中压缩编译?
我知道在
config.rb
中,你可以指定output_style
,但这仅适用于一个环境。如何同时适应这两个环境?config.rb
文件是一个 Ruby 文件,因此你可以访问整个 Ruby 工具包,包括变量和 if 语句。这是我在我的config.rb
文件中使用的代码然后,你需要做的就是设置“environment”变量。由于这几乎不会改变,所以快速简便的方法是在文件中声明它,并将 Git 设置为“assume-unchanged”以用于
config.rb
文件。更稳健的方法是在其他地方(例如,机器级配置)设置它,并访问它,或者如果环境在其他地方未设置,则假设它是生产环境并在本地设置它。将占位符与 @extend 结合使用可以实现非常强大的设计模式,这些模式实际上开始类似于真正的面向对象编程代码。
考虑以下 Sass 代码
这将生成以下输出
此类技术允许你结合最佳的 CSS 占用空间和最佳的 HTML 占用空间,同时易于维护和自定义。
我目前正在试验 [Cascade Framework](Cascade Framework “http://cascade-framework.com/”) 的代码库,以找到最适合该项目的模式。Cascade Framework 的下一个版本可能会包含基于该模式的 SASS 版本。
我是 SASS 新手,在一点上遇到了问题,需要一些帮助,以下是我的代码
在这里,我试图为菜单的每个项目赋予不同的背景颜色,但此代码不起作用。请帮忙,让我知道我哪里错了。
谢谢
@sanjan… 看起来我不确定这是否是 Sass 问题还是 HTML 问题。你是否计划创建 .l2、.l3 等,然后将它们映射到 HTML 中列表项中的相应类?
如果是这样,你可能需要探索 SASS 列表作为解决方案,Chris 在 css-tricks 上发布了一些关于此方法的精彩文章。
@Crispen: 谢谢你的回复。
实际上我正在创建菜单项,它们的类名分别为 l1、l2,并希望为每个项目提供不同的背景颜色。为了在 css 文件中获取每个项目的所需背景颜色,我必须这样编写代码
.menu ul li.l1
{
background: red;
}
.menu ul li.l2
{
background: green;
}
在 Sass 中,我尝试使用嵌套属性并这样编写代码
.menu
{
一些属性
ul li
{
一些属性
.l1
{
background: red;
}
}
}
在编写上述代码后,我得到以下 css 作为输出
.menu ul li .l1
{
background: red;
}
这并没有设置我想要的背景,我如何使用 sass 访问我的菜单项。
我完全不同意您关于 @include 和 @extend 的样式建议。
在 OOCSS 中,将标记与 CSS 耦合而不是将 CSS 与标记耦合很流行。这具有半模块化代码的优势。但是,将标记与 CSS 耦合需要向标记添加非语义类名。但是使用 SASS,可以获取这些 CSS 代码块并将其 @include 到元素上的语义类或 ID 名称中。我认为重要的是要了解 @include 和 @extend 在输出的 CSS 中的作用,并将这些行放在最合理的位置。
@Tom
“在最合理的地方”这个指南很模糊,意义不大。
对于 OOCSS、SMACSS 或 原子设计(它们基本上是具有细微差别的相同设计模式),IMO 最佳模式是
创建包含最小规则的占位符的初始 DRY CSS 层
在顶部添加第二层占位符以定义您的组件,这些组件扩展第一层。
添加第三层选择器以扩展第二层。这可以是语义或表现性选择器,具体取决于偏好。
这基本上是我上面描述的模式,尽管形式非常粗略……
@Johnslegers
所以我的想法基本上是获取这些第一、第二和第三级选择器,并尽可能将它们 @include 到语义类名称中。
这种模式当然会导致 CSS 文件略大,但 HTML 文件也会略小。至于“在最合理的地方”,我想这很模糊,作为指南意义不大,因为我认为它不应该成为样式指南的一部分。