添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

SassConf 大会上,给我们传递了Sass3.3的新特性。这些新特性有很多意义,特别是 @at-root 指令,这让你的代码会得更佳清洁。今天我们主要一起来了解Sass中的 @at-root 特性的使用规范。

在具体了解 @at-root 规范之间,我们先来回忆Sass的嵌套功能。简单的来看一个示例。在我们的CSS中常见有这样的一段代码:

.foo { color:green; .foo .bar { color:gray;

回到Sass中,实现上面的样式,我们可以使用Sass的嵌套来完成:

.foo { color: green; .bar { color: gray;

除了上面的方法之外,还可以通过连体符 & 来实现:

.foo { color: green; & .bar { color: gray;

如若简单实现:

.foo .bar { color: gray;

还可以使用另外一种特殊方式来实现:

.bar { .foo & { color: gray;

在我们CSS中有一种命名方式是 BEM ,如:

.block {} .block__element{} .block--modifier{}

试想我们在Sass中是否可以通过下面的方式来实现上面样式代码:

#{&}_element{}

不仿我们来验证一下:

.block { color: red; #{&}__element { color:blue; #{&}--modifier { color: orange;

悲催的是,编译出来的CSS并不是我们想要的代码:

.block { color: red; } .block .block__element { color: blue; } .block .block--modifier { color: orange; }

但在LESS和Stylus中,能很好的实现BEM类名的形式。此时在想,在Sass中有没有这样的功能呢?值得幸运的是,在Sass3.3中新增加了 @at-root 特性,能实现上面BEM的特性:

.block { color: red; @at-root #{&}__element { color: blue; @at-root #{&}--modifier { color:orange; @at-root 特性

前而的例子告诉我们 @at-root 是什么。通过他可以告诉Sass,你不想嵌套选择器。当使用 & 选择器时,就算你不想嵌套选择器,Sass也会自动嵌套。但往往很多时候,我们是不想要嵌套选择器,例如BEM。使用 @at-root #{&} 可以引用父(在Sass中总是引用父选择器)和插值,可以嵌套,做一些其他的事情。接下来,我们通过一些实例来说明 @at-root 的特性。

@at-root 运行环境

@at-root 是Sass的新特性。要想能正常的运行 @at-root ,首先需要先安装Sass的全新版本:只要确保你的电脑上已经安装了Ruby,你可以直接打开终端命令运行下面的命令安装Sass:

$ gem install sass --pre

如果你无法确认,你以前安装的Sass是不是最新版本,你可以通过:

$ sass -v

显示的版本信息:

Sass 3.3.0.rc.2 (Maptastic Maple)

如果不是,你可以使用下面的命令更新Sass:

$ gem update sass

注意,如果你的系统是刚升级到OS X 10.9 Mavericks,你得重新更新Command Line Tools:

$ xcode-select --install

重启您的终端命令,重新执行上面的命令就可以获取最新版本的Sass。请注意,这是一个未发表的版本,因为它还在开发中,但现在玩一点都不受影响,还可以体验Sass中新增加的一些 特性

Ben Frain The things I want from Sass aren’t the things I thought I wanted 一文中也详细的描述了Sass中新增的特性,如: Source Maps

@at-root 规范

@at-root 使用规范是如何工作,这里我们通过一些测试用例来做说明:

内联选择器模式 .foo { @at-root .bar { color:gray; .bar { color: gray;

测试用例可以说明, @at-root 的内联选择器模式,将不会让你的选择器发生任何的嵌套,直接移除了父选择。在来看一个嵌套深一点的用例:

.foo { @at-root .bar { color: gray; @at-root button{ color:red; @at-root span { color: orange; .bar { color: gray; button { color: red; span { color: orange;

在SCSS中嵌套,使用 @at-root 内联选择器模式,编译出来的CSS无任何嵌套,让代码更加的简单。回到SCSS中的嵌套中,如果不使用 @at-root 内联选择器模式,将会按代码的层级关系一层一层往下嵌套。如上例,将用例中的 @at-root 去掉之后,将会编译出像下面的CSS代码(了解过Sass)的同学,一点都不会觉得奇怪。

.foo .bar { color: gray; .foo .bar button { color: red; .foo .bar button span { color: orange; @at-root & 的结合

& 在Sass中所起的作用,文章开头就简单的进行演示了。在 @at-root 中也同样可以配合 & 一起使用,下面我们同样来看几个用例:

.foo { @at-root .bar & { color:gray; .bar .foo { color: gray;

大家很容易发现,这个示例和不加 @at-root 的SCSS代码一样,可以编译出完全相同的代码:

.foo { .bar & { color:gray;

同样的, & 符和 @at-root 按下面的方式一起工作:

.foo { @at-root & .bar { color:gray; .foo { @at-root &.bar { color:gray; .foo .bar { color: gray; .foo.bar { color: gray;

同样如此,这种方式与不加 @at-root 方式,运行的效果是一样的:

.foo { & .bar { color:gray; .foo { &.bar { color:gray;

如此说明,在Sass中同时使用 @at-root & 起到的作用是一样的,换句话说,这样并没有带来新的特性,而且在整个开发中还带来了额外的工作量。

@at-root #{&} 结合

Sass有脚本模式 #{} ,他和 & 不同之处是, & 只用作选择器,它只能出现在一个复合的开始选择器,类似于一个类型选择器,如 a 或者 h1 。但 #{} 他表示的是一个插值,它可以用在任何地方。同样的,当 @at-root #{&} 一起使用时,可以给我们的开发带来极大的方便与优势。例如:

.foo { @at-root .bar #{&} { color: gray; .foo { @at-root #{&} .bar { color:gray; .foo { @at-root #{&}.bar { color:gray; .bar .foo { color: gray; .foo .bar { color: gray; .foo.bar { color: gray;

可能会让你感到意外与失望,因为你从上面的代码之中并没有看到他有特别之处。或者说能帮你减少什么?也不能帮你优化什么?不过不用太心急,接着往下看。

先快速回忆一下 BEM ,如:

.block {} //Block .block__element{} //Element .block--modifier{} //Modifier

此时使用 @at-root 就能尽显其英雄本色:

.block { color:red; @at-root #{&}__element{ color:green; @at-root #{&}--modifier { color:blue; .block { color: red; .block__element { color: green; .block--modifier { color: blue;

到了这里,你是否体会到 @at-root 在BEM中是具有多大的优势了吧。不急,后面将来个实例,让你一览其整个过程。

@at-root 区块处理方式

@at-root 还具有区块处理的方式,可以将其内容以下面的方式进行嵌套:

.block { @at-root { #{&}__element{...} #{&}--modifier{...}

但在具体的使用过程中,有一些细节需要处理。先来看一个简单的示例:

.foo { @at-root{ .bar #{&} { color:gray; .bar .foo { color: gray;

从运行效果上可以看出,和不按区块显示效果是一致的。

@at-root 的块嵌套中,只会影响最近的子选择器,如:

.foo { @at-root { .bar { .baz { color: gray; } //.bar .baz {color:gray;} @at-root { .baz { .bac { color: green; }// .baz .bac {color:green;} @at-root { .baz { .bac { color: red; }//.baz .bac {color:red;} .foo { @at-root { .bar #{&}{ .baz { color: gray; } //.bar .foo .baz {color:gray;} @at-root { .baz #{&}{ .bac { color: green; }//.bar .bar .foo .bac {color:green;} @at-root { .baz #{&}{ .bac { color: red; }//.baz .foo .bac{color:red;} .bar .baz { color: gray; .baz .bac { color: green; .baz .bac { color: red; .bar .foo .baz { color: gray; .baz .bar .foo .bac { color: green; .baz .foo .bac { color: red;

这里有一个细节要特别注意,在使用 @at-root 块时,引用 #{&} 会略有不同。

@at-root with without

@at-root 中无法自动移除默认的指令,如 @media 或者 @supports ,先来看一个示例:

@media print { @supports (transorm-origin: 5% 5%) { .foo { @at-root { .bar #{&} { color: gray; @media print { @supports (transorm-origin: 5% 5%) { .bar .foo { color: gray;

默认情况之下, @at-root 只是通过 #{&} 来排除选择器。然而,它也可以使用 @at-root whit 或者 without 变得更加的灵活。比如,您可以使用 @at-root without 在媒体查询的时候实现另一种样式。例如:

@media print { .page { width: 8in; @at-root (without: media) { width: 960px; @media print { .page { width: 8in; .page { width: 960px;

你可以使用 @at-root (without: ...) 移除外面的任何指令。还可以通过 空格 用于移除多个指令,例如 @at-root (without: media supports ) 同时移除了 @media @supports 外部指令。

@media print { @supports ( transform-origin: 5% 5% ) { .foo { color: green; @at-root (without: media supports){ color: gray; @media print { @supports (transform-origin: 5% 5%) { .foo { color: green; .foo { color: gray;

特别声明: 到写本文的时候,运行 @at-root (with:...) 未成功过。如果有使用成功的同学,希望能分享使用案例。

案例: @at-rooot 在BEM中的应用

什么是BEM就不在多说了,来看一个简单的应用示例,假如你的应用中有一段这样的代码:

.speech-bubble{} .speech-bubble__header{} .speech-bubble__text{} .speech-bubble__text--link{}

前面介绍过, @at-root 特性允许在Sass中嵌套,编译出来的代码不会发生嵌套。这可以很好的组织你的代码。为了更好的说明,我们先回到Sass中的嵌套:

.speech-bubble { color: purple; .speech-bubble__header { color: orange; .speech-bubble__text { color: black; .speech-bubble__text--link { color:green; .speech-bubble { color: purple; .speech-bubble .speech-bubble__header { color: orange; .speech-bubble .speech-bubble__text { color: black; .speech-bubble .speech-bubble__text .speech-bubble__text--link { color: green;

这样编译出来的CSS离开了使用BEM的宗旨,也就失去了存在的意义。这个时候或许想到了Sass的 #{&} ,想通过他来解决:

.speech-bubble { color: purple; #{&}__header { color: orange; #{&}__text { color: black; #{&}--link { color:green; .speech-bubble { color: purple; .speech-bubble .speech-bubble__header { color: orange; .speech-bubble .speech-bubble__text { color: black; .speech-bubble .speech-bubble__text .speech-bubble .speech-bubble__text--link { color: green;

编译出来的CSS说明一切,特别是用在 .speech-bubble__text--link 元素上的样式:

.speech-bubble .speech-bubble__text .speech-bubble .speech-bubble__text--link { color: green;

可谓是差之毫厘失之千里。既然如此,我们一起来看 @at-root 能帮我们做什么:

.speech-bubble { color: purple; @at-root #{&}__header { color: orange; @at-root #{&}__text { color: black; @at-root #{&}--link { color:green; .speech-bubble { color: purple; .speech-bubble__header { color: orange; .speech-bubble__text { color: black; .speech-bubble__text--link { color: green;

好极了!完美实现BEM与Sass的结合。

不过大家先别急着高兴, Scott Kellum 在评论中提出了一个 要点 。他通过Sass的Mixin给 @at-root 与BEM的结合创建了一个更完美的语法:

Scott的Mixins: //elements get appended with "__" and the $name @mixin e($name) { @at-root #{&}__#{$name} { @content; //modifiers get appended with "--" and the $name @mixin m($name) { @at-root #{&}--#{$name} { @content; .speech-bubble { color: purple; @include e(header) { color:orange; @include e(text) { color:black; @include m(link){ color:green; .speech-bubble { color: purple; .speech-bubble__header { color: orange; .speech-bubble__text { color: black; .speech-bubble__text--link { color: green;

是不是很完美,而且通过Mixin是不是更方便。如果你还在想他是否具有通用性。我们不仿在使用大家最常见的“媒体对象”来验证一回。

在媒体对象中存在两种情形,一种图片居左显示,另一种图片居右显示,同时我们给他的主体创建一个BFC。常见的结构如下:

<div class="media"> <img src="https://www.w3cplus.com/preprocessor/logo.png" alt="Foo Corp logo" class="media__img--rev"> <div class="media__body"> <h3 class="alpha">Welcome to Foo Corp</h3> <p class="lede">Foo Corp is the best, seriously!</p> .media { @extend %clearfix; background-color: #f5f5f5; @include e(img) { float: left; display: inline; margin-right: 10px; @include m(rev){ float: right; display: inline; margin-left: 10px; @include e(body){ overflow: hidden;

注: 代码中引用了一个 %clearfix 用来实现清除浮动,具体制作方法,请点击 W3cplusSass核心库中的mixins

.media { *zoom: 1; .media:before, .media:after { content: ""; display: table; .media:after { clear: both; overflow: hidden; .media { background-color: #f5f5f5; .media__img { float: left; display: inline; margin-right: 10px; .media__img--rev { float: right; display: inline; margin-left: 10px; .media__body { overflow: hidden;

完美终结!

Sass 3.3 @at-root & BEM! Writing modular CSS (BEM/OOCSS) selectors with Sass 3.3 Sass Changelog Spec for the @at-root directive Interpolation with parent reference (#{&}) inside multiple selector generates incorrect selector The things I want from Sass aren’t the things I thought I wanted

@at-root 是Sass3.3版本中新增的特性,他可以让你在Sass中嵌套选择器,或者做别的事情,但编译出来的CSS却不会发生嵌套。让你的文件更简洁,更干净,更易于维护。特别是 @at-root 特性与CSS的BEM结合在一起,让你在编写样式时不用在恐惧BEM的长选择器的方式,同时让你的BEM更显风采。

当然 @at-root 是一个新特性,他有很多功能也还在完善当中,比如说 @at-rooot (with:) @at-root (without: rule) @at-root (without: all) 等。如果您对 @at-root 特性有更好的体验与理解,欢迎能在下面的评论中留下您的经验。

出处: https://www.w3cplus.com/preprocessor/Sass-3-3-new-feature-at-root-bem.html