仅仅在 Sass 3.3 发布几个月后,官方就放出了 3.4 版本 —— “Selective Steve”。虽然名字有点怪异,但却很准确,因为新版本的诸多特性就是关于选择器的。
父类选择器 &
“SassScript?” 你或许对此会有所疑问。那么你可以将 SassScript视为 Sass 的编程语言。在使用 SassScript 创造了 Sass 之后,Sass 成了一个预处理器,也成了一套开发系统,换一种角度说,Sass 总是隐藏在后台之中。或许就像是 Natalie Weizenbaum 的观点:
SassScript,就是 Sass 用来创造变量、属性值等等的轻量级语言。虽然其中使用了许多 CSS 的值,但它还提供了自定义函数、算法等功能。
在 Sass 3.4 之前,除了下面的几个用法,开发者基本没法使用父级选择器做太多的事情(我并不喜欢父级选择器这个名字,实际上该选择器只是对上级的引用,而非真正地使用了父级选择器):
.selector {
.no-svg & {
// Stuff
}
&:hover {
// (H)o(v|th)er stuff (see what I did there?)
}
}
现在,我们可以做的更多了。首先需要说明的是,该特性本打算在 Sass 3.3 中实现,但由于技术原因推迟了。
大体上说,你可以像使用其他变量一样来使用 &
。 &
中通常保存了一系列的列表——这些列表可能就是你所期望的。
举例来说,如果有一个选择器 .foo .bar, .baz
,那么 &
列表就会包含两个元素:.foo .bar
和 .baz
——而且这两个都是列表。详细来说,第一个列表也包含了两个元素(.foo
和 .bar
),而第二个列表则只包含了一个(.baz
)。
要当心了,即使是单一选择器构成的列表,也会包含一个两级列表。举例来说,.item
就会包含 ((item,),)
。所以,如果想从 &
中选择 .item
,那么就需要使用 nth(nth(&, 1), 1)
。
以上说法可能还无法说明白为什么需要这样的功能。当然,不可否认的是,一直以来没有这样的我们也可以顺利的工作。但是在这之前,有一个会频繁使用到的功能,却没法实现:
// This doesn't work in 3.3.
// This doesn't work in 3.4.
.selector {
color: blue;
a& {
color: red;
}
}
期待输出的结果:
.selector {
color: blue;
}
a.selector {
color: red;
}
典型问题是:我想快速引用一个选择器。在这个示例中,我们希望给类名为 .selector
的链接(a
)添加自定义样式。
虽然看起来并不简洁,但是我们至少可以实现功能了:
// This doesn't work in 3.3.
// This does work in 3.4.
.selector {
color: blue;
@at-root #{a + &} {
color: red;
}
}
首先,我们需要在顶层输出,因此可以使用 @at-root
,这样我们就不致于生成 .selector a.selector
。然后,只需要插入样式即可。
现在,我们可以通过创建函数将该功能模块化。就像下面这样:
// This doesn't work in 3.3.
// This does work in 3.4.
@mixin qualify($selector) {
@at-root #{$selector + &} {
@content;
}
}
然后:
.selector {
color: blue;
@include qualify(a) {
color: red;
}
}
很酷对不对?据我所知,这只是 SassScript 中 &
用法的冰山一角。虽然可能有更多其他的场景,但它们通常包含更复杂的上下文环境(Sass 框架,等等)。
选择器函数
接下来,你会兴奋地看到 Sass 3.4 带来了一些处理选择器的函数。
- selector-append
- selector-nest
- selector-extend
- selector-replace
- selector-unify
- selector-parse
- is-superselector
- simple-selectors
关于这些函数我并不会讲太多,因为这对大多数开发者来说是没有意义(包括我)。事实上,这些特性主要服务于框架开发者(这是 Natalie 在 Twitter 上跟我确认的,不过我已经找不到这条信息了,要怪就怪 twitter 的搜索太差劲了)。
基本上,你可以做任何想做的事情:无论是在选择器后继续添加选择器,还是嵌套、替换选择器,或者是合并选择器……
不过,这里我只介绍两个函数:selector-extend
和 selector-replace
。
首先,非常有必要指出 selector-extend
的解析机制和 @extend
指令完全相同。实际上,我怀疑使用的就是该指令。
其次,selector-replace
可能会比我们的想的更有效。注意!这不是一个字符串替换函数。实际上它正是利用了 @extend
指令的能力,在不违反逻辑思维的前提下替换选择器的。
这里我要借用一下 Natalie 的例子——selector-replace(".foo.bar.baz", ".foo.baz", ".qux")
(在 .foo.bar.baz
中 .qux
用 .foo.baz
替换)返回 .bar.qux
。普通的字符处替换函数不会返回值,因为 .foo.bar
在 .foor.bar.baz
中根本不存在。这就是 Sass 选择器函数的创新之处。
如果你问我这些是否有用,我会回答大多数没用。不过有些人也找到了用处,比如 Marc Mintel和 Micah Godbolt,但是就我而言,这解决不了多大的问题,因为当他们这么做的同时,也会增加代码的复杂程度。简单至上!。
使用 @error
进行错误处理
好了,关于选择器就讲这么多吧!如果说 Sass 3.4 中我所期待的特性,那么就要说 @error
指令了。实际上,作为一个框架开发者,我已经期待它两年多了。
再也不用使用 @warn "..."; @return null;
了,朋友们!@error
万岁!直到现在,Sass 都还没一个简洁的方式来处理错误。如果你长期关注我的文章,那么你会发现对下面的代码模式很熟悉:
@function rainbow($unicorn) {
@if type-of($unicorn) != "unicorn" {
@warn "What?! `#{$unicorn}` is not a unicorn? Are you serious?!";
@return null;
}
// Proceed with the code.
}
基本上我们需要检查所有需要检查的地方,通过 @warn
提醒使用者,该指令返回 null
(或者 false
等其他消息),并会继续处理所有的逻辑操作。
下面让我们见识一下 Sass 3.4 的魔力:
@function rainbow($unicorn) {
@if type-of($unicorn) != "unicorn" {
@error "What?! `#{$unicorn}` is not a unicorn? Are you serious?!";
}
// Proceed with the code.
}
Boom! 如果解析器执行到 @error
指令,它就会中断,并在控制台输出错误信息——类似语法错误之类的提示。代码执行就是简单的中断了,这是非常棒的做法!
颜色方面的改进
首先,rebeccapurple
(#663399
)被添加进了 Sass,其处理方式和其他颜色相同。这是为了纪念 Eric A. Meyer(CSS 传奇人物) 的女儿,她最喜欢的颜色就是紫色,不幸的是她在六岁就去世了。
此外,在 Sass 处理颜色的操作细节上,做了很棒的优化。举例来说,如有可能,Sass 将会保留颜色的原始值,除非在压缩模式下。压缩模式下,Sass 会尝试寻找最简洁的方式表示颜色。
同样的,rgb()
, rgba()
, hsl()
,和 hsla()
函数也会尝试压缩为最小/最大的可用值,而不是直接抛出错误。这个改动更多的是为了在 CSS Colors Level 4上和 CSS 规范保持一致。
最后,很多开发者都抱怨在占位符中使用颜色的做法,现在 Sass 将对这种编程方式提出警告。基本上,一些开发者所抱怨的就是下面代码生成的结果:
@each $color in darkolivegreen, firebrick, blanchedalmond {
.item-#{$color} {
color: $color;
}
}
虽然这段代码可以在任何模式下正常渲染(除了压缩模式),但编译之后的代码却成了这样:
.selector-#556b2f{color:#556b2f}.selector-#b22222{color:#b22222}.selector-#ffebcd{color:#ffebcd}
正如所看到的,因为十六进制值更短小,所以为了节省空间,使用十六进制值所替代了颜色名。解决方案是引用列表("darkolivegreen", "firebrick", "blanchedalmond"
)中的颜色,但为了防止更多的混淆,Sass 将会在控制台中直接提出警告。
有没有感到很激动?!
如果这些都没有打动你,朋友们,那么不用担心,因为 Sass 3.4 还有很多新特性值得深挖。
让我给你介绍一些额外的功能吧——我认为很有趣:
- 现在使用
map-remove
函数可以一次性删除多个键。该函数与map-merge
一致,也可以接受数对参数。 - 现在
@extend
指令可以正确处理伪类了——Sass 3.4 之前还存在问题。 - Sourcemaps 大幅优化。
更多信息请参阅官方更新动态。
本文根据@Hugo Giraudel的《Sass 3.4 is Out!》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://www.sitepoint.com/sass-3-4-is-out/。
如需转载,烦请注明出处:http://www.w3cplus.com/preprocessor/sass-3-4-is-out.html