重大变更:扩展复合选择器

LibSass 目前允许像 .message.info 这样的复合选择器被扩展,但扩展的方式与 @extend 的预期工作方式不匹配。

Compatibility:
Dart Sass
LibSass
Ruby Sass

当一个选择器扩展另一个选择器时,Sass 会将匹配扩展器的所有元素样式化,就好像它们也匹配被扩展的类。换句话说,如果你编写 .heads-up {@extend .info},它的工作方式就像你在 HTML 中将 class="heads-up" 替换为 class="heads-up info"

按照这个逻辑,你会期望 .heads-up {@extend .message.info} 的工作方式类似于将 class="heads-up" 替换为 class="heads-up info message"。但这不是 LibSass 和 Ruby Sass 中当前的工作方式——它不是将 .heads-up 添加到具有*.info.message* 的每个选择器,而是仅添加到同时具有 .info.message 的选择器。

Playground

SCSS Syntax

// 这两个都应该被扩展,但它们不会。
.message {
  border: 1px solid black;
}
.info {
  font-size: 1.5rem;
}

.heads-up {
  @extend .message.info;
}
Playground

Sass Syntax

// 这两个都应该被扩展,但它们不会。
.message
  border: 1px solid black

.info
  font-size: 1.5rem


.heads-up
  @extend .message.info

为了解决这个问题,避免更多混淆,并保持实现的清晰和高效,Dart Sass 不支持扩展复合选择器,并且这一功能将在未来版本的 LibSass 中被移除。为了兼容性,用户应该分别扩展每个简单选择器:

Playground

SCSS Syntax

.message {
  border: 1px solid black;
}
.info {
  font-size: 1.5rem;
}

.heads-up {
  @extend .message, .info;
}
Playground

Sass Syntax

.message
  border: 1px solid black

.info
  font-size: 1.5rem


.heads-up
  @extend .message, .info

CSS Output

.message, .heads-up {
  border: 1px solid black;
}

.info, .heads-up {
  font-size: 1.5rem;
}



⚠️ Heads up!

因为 Sass 不知道 CSS 将要样式化的 HTML 的细节,任何 @extend 可能需要生成额外的选择器,这些选择器不会应用于你特定的 HTML。当切换away从扩展复合选择器时,这一点尤其明显。

大多数情况下,这些额外的选择器不会造成任何问题,并且只会在 gzipped CSS 中添加几个字节。但某些样式表可能更依赖于旧的行为。在这种情况下,我们建议将复合选择器替换为占位符选择器

Playground

SCSS Syntax

// 不仅仅是 `.message.info`。
%message-info, .message.info {
  border: 1px solid black;
  font-size: 1.5rem;
}

.heads-up {
  // 不是 `.message.info`。
  @extend %message-info;
}
Playground

Sass Syntax

// 不仅仅是 `.message.info`。
%message-info, .message.info
  border: 1px solid black
  font-size: 1.5rem


.heads-up
  // 不是 `.message.info`。
  @extend %message-info

CSS Output

.heads-up, .message.info {
  border: 1px solid black;
  font-size: 1.5rem;
}