Lzh on GitHub

父选择器

父选择器 & 是 Sass 发明的一种特殊选择器,用于嵌套选择器中,以引用外部选择器。它使得以更复杂的方式重用外部选择器成为可能,例如添加 伪类 或在父级之前添加选择器。

父选择器 & 是 Sass 发明的一种特殊选择器,用于嵌套选择器中,以引用外部选择器。它使得以更复杂的方式重用外部选择器成为可能,例如添加 伪类 或在父级之前添加选择器。

当父选择器在内部选择器中使用时,它会被相应的外部选择器替换。这取代了正常的嵌套行为。

.alert {
  // The parent selector can be used to add pseudo-classes to the outer
  // selector.
  &:hover {
    font-weight: bold;
  }

  // It can also be used to style the outer selector in a certain context, such
  // as a body set to use a right-to-left language.
  [dir=rtl] & {
    margin-left: 0;
    margin-right: 10px;
  }

  // You can even use it as an argument to pseudo-class selectors.
  :not(&) {
    opacity: 0.8;
  }
}
由于父选择器可以被 h1 这样的类型选择器替换,因此它只允许在类型选择器也允许的复合选择器的开头使用。例如,span& 是不允许的。不过,我们正在研究放宽此限制。如果你想为此提供帮助,请查看这个 GitHub 问题。

添加后缀

你还可以使用父选择器为外部选择器添加额外的后缀。这在使用 BEM 等方法时特别有用,该方法使用高度结构化的类名。只要外部选择器以字母数字名称结尾(如类、ID 和元素选择器),你就可以使用父选择器来附加额外的文本。

.accordion {
  max-width: 600px;
  margin: 4rem auto;
  width: 90%;
  font-family: "Raleway", sans-serif;
  background: #f4f4f4;

  &__copy {
    display: none;
    padding: 1rem 1.5rem 2rem 1.5rem;
    color: gray;
    line-height: 1.6;
    font-size: 14px;
    font-weight: 500;

    &--open {
      display: block;
    }
  }
}

在 SassScript 中

父选择器也可以在 SassScript 中使用。它是一个特殊的表达式,以与选择器函数相同的格式返回当前父选择器:一个逗号分隔的列表(选择器列表),其中包含空格分隔的列表(复合选择器),这些列表又包含无引号的字符串(复合选择器)。

.main aside:hover,
.sidebar p {
  parent-selector: &;
  // => ((unquote(".main") unquote("aside:hover")),
  //     (unquote(".sidebar") unquote("p")))
}

如果在任何样式规则之外使用 & 表达式,它将返回 null。由于 null 是假值,这意味着你可以轻松地用它来判断混合宏是否在样式规则中被调用。

@mixin app-background($color) {
  #{if(&, '&.app-background', '.app-background')} {
    background-color: $color;
    color: rgba(#fff, 0.75);
  }
}

@include app-background(#036);

.sidebar {
  @include app-background(#c6538c);
}

高级嵌套

你可以将 & 作为正常的 SassScript 表达式使用,这意味着你可以将其传递给函数或包含在插值中——甚至在其他选择器中!将其与选择器函数和 @at-root 规则结合使用,可以让你以非常强大的方式嵌套选择器。

例如,假设你想编写一个匹配外部选择器和元素选择器的选择器。你可以编写一个像这样的混合宏,它使用 selector.unify() 函数将 & 与用户的选择器组合。

@use "sass:selector";

@mixin unify-parent($child) {
  @at-root #{selector.unify(&, $child)} {
    @content;
  }
}

.wrapper .field {
  @include unify-parent("input") {
    /* ... */
  }
  @include unify-parent("select") {
    /* ... */
  }
}
当 Sass 嵌套选择器时,它不知道用于生成它们的插值是什么。这意味着即使你将 & 用作 SassScript 表达式,它也会自动将外部选择器添加到内部选择器中。这就是为什么你需要显式使用 @at-root 规则来告诉 Sass 不要包含外部选择器的原因。