SASS CSS: 从子类到目标父类

我正在使用 SASS,发现有一点不方便,下面是我正在尝试做的事情的一个例子:

.message-error {
background-color: red;


p& {
background-color: yellow
}
}

预期的 CSS:

.message-error {
background-color: red;
}
p.message-error {
background-color: yellow ;
}

这个想法: 所有的元素与。Message-error 将是红色的,除非它是 p.message-error。这不是真实的情况,只是举个例子。

SASS 无法编译这个,我甚至尝试了字符串串联。有没有什么插件可以做同样的事情?

注意: 我知道我可以用另一个 CSS 定义,比如:

p.message-error{....}

... 下,但我想避免这一点,并使用一个地方为所有。消息错误定义。

谢谢。

176638 次浏览

最好的办法可能是这样做(假设你在你的。消息错误类不仅仅是背景颜色。

.message-error {
background-color: red;
}


p.message-error {
@extend .message-error;
background-color: yellow
}

这种方法没有提供那种紧密的分组,但是您可以让它们彼此靠得很近。

我认为,如果你想让它们按照父选择器分组,你可能需要添加一个共同的父选择器:

body {
& .message-error {background-color: red;}
& p.message-error {background-color: yellow}
}

当然,body可以替换为其他一些常见的父节点,如 #Content或另一个包含所有错误消息的 div名称。

更新(另一个想法)

如果你利用 @ for清单,那么它似乎应该工作(我不确定的是,如果列表将允许 .(周期)。

@for $i from 1 to 3 {
nth(. p. ul., #{$i})message-error {
background-color: nth(red yellow cyan, #{$i}));
}
}

应该编译成这样的东西:

.message-error {
background-color: red;}
p.message-error {
background-color: yellow;}
ul.message-error {
background-color: cyan;}

这招也许管用

 {
$and: .message-error;
#{$and} {
background-color: red;
}


p#{$and} {
background-color: yellow
}
}

您甚至可以使用 $&作为变量名,但我不能100% 确定它不会抛出错误。

SASS 有内置的范围,这样就不必担心 $and的值泄露给样式表的其他部分

变量仅在嵌套选择器级别内可用 如果它们被定义在嵌套之外呢 选择器,到处都有。

@ Zeljko 通过 SASS 是不可能做到你想做的事情的。

见 Nex3评论: https://github.com/nex3/sass/issues/286#issuecomment-7496412

关键是“ &”前面的空格:

.message-error {
background-color: red;


p & {
background-color: yellow
}
}

而不是:

.message-error {
background-color: red;


p& {
background-color: yellow
}
}

我以前也遇到过这种情况。Bootstrap 3使用父选择器黑客技术处理这个问题。我为了自己的目的稍微调整了一下。

@mixin message-error() {
$class: '.message-error';
#{$class} {
background-color: red;
}
p#{$class} {
background-color: yellow;
}
}
@include message-error();

Wheresrys 使用了类似的方法,但是有一些粗鲁的错误。上面的代码允许您将其作为一个块进行管理,并在编辑器中将其折叠。嵌套变量还使其成为本地变量,这样您就可以在需要应用此技巧的所有实例中重用 $class。下面是一个工作样本..。

Http://sassmeister.com/gist/318dce458a9eb3991b13

从 Sass 3.4开始,现在支持这种方式:

.message-error {
background-color: red;


@at-root p#{&} {
background-color: yellow
}
}

注意 @at-root指令和与号上的插值语法。未能包含 @at-root指令将导致选择器像 .message-error p.message-error而不是 p.message-error

在当前版本中: 选择性的 Steve (3.4.14)现在是可能的,只需要更新一点你的代码:

.message-error {
background-color: red;
p &{
background-color: yellow
}
}

这只有当你是一个级别嵌套,例如,它不工作,如果你有这样的东西:

.messages{
.message-error {
background-color: red;
p &{
background-color: yellow
}
}
}

我做了一个混合器来解决这个问题。

https://github.com/imkremen/sass-parent-append

例子: https://codepen.io/imkremen/pen/RMVBvq


用法:

.ancestor {
display: inline-flex;


.grandparent {
padding: 32px;
background-color: lightgreen;


.parent {
padding: 32px;
background-color: blue;


.elem {
padding: 16px;
background-color: white;


@include parent-append(":focus", 3) {
box-shadow: inset 0 0 0 8px aqua;
}


@include parent-append(":hover") {
background-color: fuchsia;
}


@include parent-append("p", 0, true) {
background-color: green;
}
}
}
}
}

结果(css) :

.ancestor {
display: inline-flex;
}
.ancestor .grandparent {
padding: 32px;
background-color: lightgreen;
}
.ancestor .grandparent .parent {
padding: 32px;
background-color: blue;
}
.ancestor .grandparent .parent .elem {
padding: 16px;
background-color: white;
}
.ancestor:focus .grandparent .parent .elem {
box-shadow: inset 0 0 0 8px aqua;
}
.ancestor .grandparent .parent:hover .elem {
background-color: fuchsia;
}
.ancestor .grandparent .parent p.elem {
background-color: green;
}

我也有同样的问题,所以我做了一个混音器。

@mixin tag($tag) {
$ampersand: & + '';
$selectors: simple-selectors(str-replace($ampersand, ' ', ''));


$main-selector: nth($selectors, -1);
$previous-selectors: str-replace($ampersand, $main-selector, '');


@at-root {
#{$previous-selectors}#{$tag}#{$main-selector} {
@content;
}
}
}

为了让它工作,你还需要一个 字符串替换函数字符串替换函数(来自 Hugo Giraudel) :

@function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
@if $index {
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
@return $string;
}

工作原理:

SCSS

.foo {
color: blue;


@include tag(p) {
color: red;
}
}

输出

.foo {
color: blue;
}


p.foo {
color: red;
}

用例
此方法适用于嵌套选择器,但不适用于复合选择器。

我用一个类似的解决方案创建了 package/Mixin:)(也许它会对你有所帮助)

Https://github.com/darex1991/bem-parent-selector

所以写作:

.calendar-container--theme-second-2 {
.calendar-reservation {
@include BEM-parent-selector('&__checkout-wrapper:not(&--modifier):before') {
content: 'abc';
}
}
}

这个 mix 只会为最后一个父节点添加选择器:

.calendar-container--theme-second-2 .calendar-reservation__checkout-wrapper:not(.calendar-reservation--modifier):before {
content: 'abc';
}

更多关于回购的信息。

您可以将当前选择器分配给一个变量,然后在任何深度使用它:

.Parent {
$p: &;


&-Child {
#{$p}:focus & {
border: 1px solid red;
}


#{$p}--disabled & {
background-color: grey;
}
}
}

当我需要更改中间的某个元素时,我使用@Mixin 函数,如下所示 无礼的大树。

第一个参数是父元素、目标,第二个参数是应该具有的类。

SASS

@mixin parentClass($parentTarget, $aditionalCLass) {


@at-root #{selector-replace(&, $parentTarget, $parentTarget + $aditionalCLass)} {
@content;
}
}
样本,

像我需要改善字体大小在一个强大的标签,当。 txt-target 有。 txt-太强

HTML

   <section class="sample">
<h1 class="txt-target txt-bold">Sample<strong>Bold</strong>Text</h1>
</section>

SASS

section{
.txt-target{
strong{
@include parentClass('.txt-target','.txt-bold'){
font-weight:bold;
font-size:30px;
}
}
}
}

字体:

Https://sass-lang.com/documentation/at-rules/at-root

在这里,您可以看到一个名为@Mixin uniy-father ($child)的函数,它看起来像这样