&
是 Sass(以及 Less)中一个非常有用的功能。它用于嵌套。当您知道如何使用它时,它可以是一个很好的节省时间的工具,但当您正在努力学习时,它也可能是一个浪费时间的工具,因为您本可以使用普通的 CSS 写出相同的代码。
让我们看看是否真的能理解它。
基本嵌套
.parent {
.child {}
}
这将编译为
.parent .child {}
您可以根据需要进行更深层的嵌套,但最好只嵌套一到两层,以防止过于具体的选择器(这将减少实用性,并使覆盖变得更加困难)。
添加另一个类
当您进行嵌套并希望创建更具体的选择器(例如同时具有两个类的元素)时,&
会非常有用,例如
.some-class.another-class { }
您可以在嵌套时使用 &
来实现这一点。
.some-class {
&.another-class {}
}
&
始终引用嵌套时的父选择器。将 &
视为被移除并替换为父选择器。例如:

顿悟时刻!
以下 Sass 代码
.parent {
.child {}
}
实际上可以看作是使用 &
进行嵌套的简写方式
.parent {
& .child {}
}
因此,这两个示例都将编译为相同的结果
.parent .child {}
使用 &
的示例与不使用 &
的示例没有什么不同。不使用 &
进行嵌套是使用 &
进行嵌套的简写形式。我们可以将 &
视为一种机制,它允许我们在子选择器中放置父选择器,无论我们将其放置在何处。它允许我们在嵌套时进行修改。让我们看一些更多的例子。
&
与伪类
使用 您可以使用 &
以更简洁的方式在类上编写伪类
.button {
&:visited { }
&:hover { }
&:active { }
}
这将编译为
.button:visited { }
.button:hover { }
.button:active { }
在这种情况下,&
允许我们在编写代码时将 .button
直接放置在伪类旁边,而无需重复。如果我们从该示例中省略 &
,基本嵌套将在它们之间添加空格,如下所示...
.button :hover
...这并不相同。
&
与 >、+ 和 ~
使用 使用 &
与 子 组合器 >
、相邻兄弟 组合器 +
和 一般兄弟 组合器 ~
非常容易。最初我以为您必须使用 &
,但
// You don't actually have to do this.
// Here, the ampersand is implied.
.button {
& > span { }
& + span { }
& ~ span { }
}
省略选择器中的 &
也可以在这里使用
// This compiles the same as above
.button {
> span { }
+ span { }
~ span { }
}
这两个示例都将编译为以下 CSS
.button > span { }
.button + span { }
.button ~ span { }
基于上下文进行限定
嵌套选择器并不一定需要以 &
开始。您可以通过将 &
放在右侧来限定选择器。
.button {
body.page-about & { }
}
我们正在将父选择器重新定位到我们需要的位置。这对基于不同父级进行选择器限定非常有用。这将编译为
body.page-about .button {}
意思是,仅当 button
类是具有 page-about
类的 body
的子元素时,才选择它。
&
的定义
调整 将 &
视为不仅会被父选择器替换,还会被*编译后的*父选择器替换。
当嵌套深度超过两层时,这一点很重要,因为多个层级中都包含 &
。以下两个古怪的例子说明了这一点。
古怪但有效的示例 #1
不要编写看起来像这样的选择器
.parent {
.child {
& div & & > a {}
}
}
对于每个 &
,它都将被编译后的父选择器替换。因此,每次出现 &
时,我们都会插入 .parent .child
。以下是编译后的 CSS
.parent .child div .parent .child .parent .child > a {}
古怪但有效的示例 #2
.parent {
.child {
.grand-child & {
&.sibling { }
}
}
}
要从心理上编译此 CSS 代码,请从最顶层开始,逐层向下剥离,将 &
替换为新的编译后的父选择器。
以下是编译后的结果
.grand-child .parent .child.sibling {}
&
不是什么
我发现自己经常将 &
用于它本来不适用的地方。&
无法让您选择性地向上遍历嵌套的选择器树,到达特定位置,然后仅使用您希望使用的编译后的父选择器的一部分。我之前希望能够执行类似的操作
.grand-parent {
.parent {
&(1) .child {} // Trying to get `.parent`, not `.grand-parent .parent`
}
}
我的本意是让 &
仅被 .parent
替换,以期编译为以下结果
.parent .child {}
但这行不通。
&
始终是完全编译后的父选择器。
@at-root 来帮忙
值得一提的是,@at-root
允许您完全跳出嵌套结构,到达嵌套树的“根”。
.grand-parent {
.parent {
@at-root .child {}
}
}
我们已经从嵌套树中传送到了以下编译后的 CSS
.child {}
这很好。从组织的角度来看,所有代码仍然分组在一起,这可以被视为嵌套的一个不为人知的优势。@at-root
可以帮助保持较低的特异性级别,因为您不再拥有编译后的父选择器来提高特异性。同时,仍然保持代码在概念上的组织,并使用嵌套
.grand-parent {
.parent {
@at-root body.page-about .child {}
}
}
编译后的 CSS
body.page-about .child {}
&
还有其他一些有趣的用例。
提高特异性
有时你需要降低第三方 CSS 库的特异性以获取样式的控制权。
.parent.parent {}
这比使用 ID、内联样式或 !important
要温和得多,而且它可能比使用任意父元素限定选择器更有利。特异性级别不会根据选择器的上下文提升,而是只根据它本身提升。使用 &
你可以像这样做到这一点。
.parent {
&#{&} { }
}
#{ }
中的 插值括号 是必需的,因为两个相邻的 & 符号在 Sass 中是无效的。
修改 & 符号
即使你不能在没有插值括号的情况下让两个 & 符号相邻(正如我们之前在伪类示例中演示的那样),你仍然可以让另一个选择器与 & 符号相邻。与 & 符号相邻对于修改器类非常有用。
.btn {
&-primary {}
&-secondary {}
}
编译后的 CSS
.btn-primary {}
.btn-secondary {}
如果使用命名方法(例如 BEM),它使用连字符和下划线组合的类而不是组合选择器,这将非常有用。
结论
与嵌套结合使用的 & 符号是一个很棒的功能。一旦你了解了它的作用,编写 Sass 就会变得更容易、更快、更不容易出错。
以下是一些关于 & 符号的专门文章,供你参考。
- 使用 & 符号引用父选择器 by
Adam Stacoviak - Sass 片段:万能的 & 符号 by Una Kravets
- & 符号:一个强大的 Sass 功能 by Joel Oliveira
你可以在 Stylus(一个经常被遗忘但仍然非常优秀的预处理器)中使用类似于 &(1) 的内容。
太棒了,我只知道最基本的用法。
我以前不知道
@at-root
,但它似乎是一个很好的选择,可以保持代码井井有条,而不会创建过长的选择器。感谢分享。我也是,这很棒。我喜欢嵌套,因为它允许我折叠/收起代码,但有时选择器会变得太长。
我尝试创建一个名为
nth-selector
的 Sass 函数来模拟 Stylus 中的部分引用选择器。https://gist.github.com/Rplus/0e029eeb0686fe81f874
:P
感谢你的客座文章!我之前也遇到过一些问题。我想我现在要分享我的顿悟了,这要感谢你。太棒了。
Sass 中的 & 符号有很大的力量,很高兴看到这里对它进行了如此详细的描述。
尽管如此,嵌套选择器(尤其是使用 & 符号的嵌套选择器)可能很痛苦,尤其是在团队中没有完全由 Sass 专家组成的情况下。使用 & 符号、@at-root 和其他方法来构建一致的选择器有很多吸引力,但它们通常难以阅读和修改。如果我发现自己正在写类似
.parent { &#{&} { property: value } }
的内容,这提醒我需要评估其他我可能做错的地方。太棒了,我之前不知道这个。
非常有用。我一直认为 & 符号必须出现在选择器的开头。
我以为我对 & 符号已经了如指掌了,但
&-primary
这个技巧真是很巧妙。我可能会提醒不要过度使用 & 符号。
.parent { &#{&} {} }
似乎过于繁琐,而.parent { &.parent {} }
既更容易理解,也更易于输入。我以前也对此很谨慎,但源代码映射消除了我以前遇到过的关于半选择器的问题。
不错的文章。非常有用。
我之前不知道
.button {
body.page-about & { }
}
这对于组织目的来说非常棒。超级棒!
一个很好的总结,我希望几年前就看到这篇文章。我们在工作中强制执行的样式表标准之一是,每个嵌套规则都必须包含一个 & 符号,无论它是否需要。这可能听起来有点奇怪,但它使 Less 更易于阅读,当你看到一个规则以 & 符号开头时,你可以预期它在其他选择器中也会有一个 & 符号,而无需花费时间查找。你也可以看到一个规则属于哪个父规则,尽管我们的另一个标准是几乎所有规则都包含在 mixin 中,从而防止出现孤儿规则。
我最喜欢的 & 符号用例是添加 Modernizr 父类。
效果很好。
不错的文章。我喜欢在 BEM 中使用它。节省了大量重复输入。
不错,非常有用。感谢!
首先,这篇文章很棒,提供了很好的见解。我查看了你关于“顿悟”部分的内容,有点困惑。你的两个 SCSS 示例不会编译成相同的内容,因为 Sass 嵌套规则。
SASS
编译为
CSS
不
注意 .parent 类之后的空格。
区别在于 & 符号表示如果元素具有此父类 AND 此子类,则子类样式将被添加到(或减去)父类。另一种方式表示具有 child 类的元素位于具有 parent 类的元素内部。
这是一个链接到 Pen, 它采用了你的原始示例并探讨了嵌套 Sass 编译的 3 种方式。
我不知道……。我不认为这是正确的。这是 Sassmeister 上的一个实时示例,你可以并排查看它们。
http://www.sassmeister.com/gist/7759547dc592fd129877
我最喜欢的
生成
现在,想象一下有 3 个选择器,或者更多。
感谢你的发布,很棒的文章。我在我的网站上使用以下代码。
.parent {
.child {
.grand-child & {
&.sibling { }
}
}
}