Hugo Giraudel在《Looking Into the Future of Sass》(译文Sass新特性)一文中向大家介绍了Sass的十大新特性。这些特性都将让你的工作变得更简单与方便。那么今天我主要想向大家介绍我自己对Sass3.3中几个新特性的理解与使用心得,希望对大家的学习有所帮助。
&
在Sass3.3中,连体符&
让你的选择器变得更简单,维护更方便。他可以轻松的让你选择父元素,可以配合伪类元素等(详细请参考《Sass中连体符(&)的运用》)。但在Sass中还有一个新的用法,如:
$selector: null;
.block{
$selector: &;
}
#{$selector}--map {
color: green;
}
编译出来的CSS:
.block--map {
color: green;
}
但此时Sass编译器将报出错误信息:
DEPRECATION WARNING on line 6 of test.scss:
Assigning to global variable "$selector" by default is deprecated.
In future versions of Sass, this will create a new local variable.
If you want to assign to the global variable, use "$selector: & !global" instead.
根据报警提示,我们将上面的代码进行修改,在代码中加入!global
:
.block{
$selector: & !global;
}
#{$selector}--map {
color: green;
}
编译出来的CSS:
.block--map {
color: green;
}
和第一种方法编译出来的CSS是一样的。此时试想,如果我们的代码中有不同的BEM命名方式,比如在CSS中有这样的一段代码:
.view-element {...}
.block-element {...}
根据前面的示例,大家可能第一时间想到是:
.view,
.block {
$selector: & !global;
}
#{$selector}--element{
color:green;
}
但这段SCSS代码编译出来的CSS并不是我们想要的代码:
.block,
.view--element {
color: green;
}
或许你会考虑这样来重构SCSS代码:
.block{
$selector: & !global;
}
.view {
$selector: & !global;
}
#{$selector}--element {
color: green;
}
但编译出来的CSS还不是你想要得到的:
.view--element {
color: green;
}
很明显.view
覆盖了.block
中的$selector: & !global
。但仍不死心,在nex3/sass上提了一个issues。@lolmaus提供了一种方法:
.block,
.view {
$selectors: & !global;
}
@each $selector in $selectors {
#{$selector}--element {
color: green;
}
}
编译出来CSS:
.block--element {
color: green;
}
.view--element {
color: green;
}
这似乎是我们想要的CSS代码,但换一个条件:
.block-element {color:green;}
.view-element {color: blue;}
那么目前为止,在Sass使用!global
中还无法实现。只能变换一种方式:
$selector: null;
.block {
$selector: &;
}
#{$selector}--element{
color: green;
}
.view {
$selector: &;
}
#{$selector}--element{
color:blue;
}
这样编译出来的CSS是我们所需要的:
.block--element {
color: green;
}
.view--element {
color: blue;
}
虽然实现我们需要的效果,但似乎这样的SCSS代码并没有给我们的工作带来方便。当然,在Sass中还有一种更容易实现的方法,这也是Sass3.3中的另一个新特性,稍后需要描述的。不过在这里,通过多种方式演示,唯一想说明的一点是在Sass3.3中新引入了一个!global
,它可以用来定义某个选择器为全局选择器变量或者定义全局变量。等同效果:
//方法一
$selector: '.selector';
#{$selector}--element {
background-color: #fcc;
}
//方法二
.selector {
$selector: & !global;
}
#{$selector}--element {
background-color: #fcc;
}
CSS:
.selector--element {
background-color: #fcc;
}
但有一点需要特别声明,!global
和!default
并不相同。
!default
VS !global
!default
在Sass中常称为变量默认值,而!global
在Sass中称为变量全局值。这好象又回到了全局变量和局部变量的争论中了。有关于这两个方面的争论,我们避而不谈,主要还是来看看他们功能上的区别。
首先我们简单的回忆一下这样的一个示例:
p {
$color: green;
color: $color;
a {
color: $color;
}
}
div {
color: $color;
}
在编译Sass时将会报错:
error test.scss (Line 16: Undefined variable: "$color".)
错误信息告诉我们,在div
中的$color
是没有定义的一个变量值。为了能让代码正常运行,必须先得在外面显式的声明$color
变量。
$color: blue;
p {
$color: green;
color: $color;
a {
color: $color;
}
}
div {
color: $color;
}
编译出的CSS:
p {
color: green;
}
p a {
color: green;
}
div {
color: green;
}
那么在Sass3.3中,我们可以借助于!global
在任何地方定义一个变量,而且任何一组代码中都可以调用这个变量:
p {
$color: green !global;
color: $color; //输出green
a {
color: $color; //输出green
}
}
div {
color: $color; //输出green
}
使用!global
之后,将不会报错,编译出来的CSS也无误。
另外在使用!global
依旧无法避免顺序造成的覆盖,我们来尝试一个新示例:
p {
$color: green !global;
color: $color; //输出green
a {
$color: red;
color: $color; //输出red
}
}
div {
color: $color; //输出red
}
回到!default
中,大家都知道同一变量后面出现的总是会覆盖前面出现的:
$color: blue;
$color: red ;
p {
color: $color; //输出red
a {
color: $color; //输出red
}
}
div {
color: $color; //输出red
}
一旦在第二个变量加上!default
之后,那么一切将有可能改变:
$color: blue;
$color: red !default;
p {
color: $color; //输出blue
a {
color: $color; //输出blue
}
}
div {
color: $color; //输出blue
}
但要是将后面出现的$color
变量后添加!global
,那依旧是后者覆盖前者:
$color: blue;
$color: red !global;
p {
color: $color; //输出red
a {
color: $color; //输出red
}
}
div {
color: $color; //输出red
}
而这种方式也将无任何意义。
通过这些对比,我们可以得出:!default
可以用来设置一个默认变量,其不会覆盖前面设置的相同变量;而!global
可以在任何代码块中声明一变量,提供给其他代码块调用此变量。
备注:有关于!default
的相关介绍,大家要是感兴趣的话可以猛击《Sass揭秘之变量》一文。
&
另一用法#{&}
在Sass中&
配上#{}
可以做为选择器插值。当然,这个在生成后代选择器的时候非常方便,简单的看个示例:
block {
#{&} .bar {
color: red;
}
}
编译出CSS:
.block .block .bar {
color: red;
}
似乎把我们的CSS变得更为复杂,但其还是具有一定的优势的,比如在BEM的应用中:
.block {
#{&}--element {
color: red;
}
}
编译出CSS:
.block .block--element {
color: red;
}
编译出来的样式代码,虽然离BEM的初衷甚远,但也免强可一用。不过在Sass3.3中有一个新的特性@at-root
可以更好的配合BEM一起使用。
在Sass中,如果你不想嵌套选择器,可以使用@at-root
特性。当像使用#{&}
可以明确的告诉Sass,他只是一个变量,而不会嵌套。来看一个示例:
.block {
@at-root #{&}__element {
color: red;
}
@at-root #{&}--modifier{
color:green;
}
}
编译出CSS:
.block__element {
color: red;
}
.block--modifier {
color: green;
}
生成的CSS代码正是我们想要的BEM模式。也就是说,有了@at-root
可以非常简单的实现BEM模式。在Sass中除了这种方式之外,还可以将@at-root
以块的方式展示:
.block {
@at-root {
#{&}__element {
color: red;
}
#{&}--modifier{
color:green;
}
}
}
同样可以编译出来上一段相同的CSS代码。当然@at-root
的实际应用不只这些,有关于更详细的使用,可以猛击《Sass @at-root》一文。
在《Sass中连体符(&)的运用》一文中介绍了Sass中&
的使用。其实&
是Sass3.3中十大特性之一。他可以让你的选择器嵌套更便捷,而且可以配合#{}
实现选择器的插值。另外通过与!global
的配合可以指引定选择器为变量。另外最大的优势是,配合@at-root
可以与BEM完美的结合,真正实现BEM的设计模式。
希望这些简单的示例,能帮助大家更好的理解&
和更好的使用&
符。如果您有更好的建议和使用经验,可以在下面的评论中与我们一起分享。
出处:http://www.w3cplus.com/preprocessor/sass-future-use-ampersand.html