sass css:从子级目标父类

CSS

西里Sam

2020-03-19

我正在使用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{....}

下面,但我想避免这种情况,并在所有.message-error定义中使用一个位置。

谢谢。

第2229篇《sass css:从子级目标父类》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

9个回答
十三Harry神无 2020.03.19

在当前版本:选择性的史蒂夫(3.4.14)中,现在可以这样做,只需要更新一点代码即可:

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

这仅在您是一级嵌套的情况下才有效,例如,如果您具有以下内容,则它将无效:

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

这种作弊可能有效

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

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

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

And SASS has inbuilt scoping, which removes having to worry about the value of $and leaking out to the rest of your stylesheet

Variables are only available within the level of nested selectors where they’re defined. If they’re defined outside of any nested selectors, they’re available everywhere.

Mandy村村Harry 2020.03.19

我做了一个mixin来解决这个问题。

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

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


用法(scss):

.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;
}
ㄏ囧囧ㄟ 2020.03.19

这就是你的做法

.Parent {
  $parentClass: &;

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

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

它可以在任何级别的afaik上运行,无论您想深入多深。

凯小哥 2020.03.19

我认为,如果要按父选择器对它们进行分组,则可能需要添加一个公共父:

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

当然,body可以用其他一些通用父代替换,例如#Contentdiv包含所有错误消息的其他名称。

更新(另一个想法)

如果您使用@forlist,那么这似乎应该工作(我不确定的是列表是否允许.(句点)。

@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;}
Gil番长Stafan 2020.03.19

我有同样的问题,所以为此做了一个混入。

@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;
}

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

米亚Gil 2020.03.19

最好的办法可能是这样做(假设您在.message-error类中有更多的东西,而不仅仅是背景色。

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

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

这种方法不提供这种紧密的分组,但是您可以使它们彼此靠近。

村村Tony 2020.03.19

Natalie Weizenbaum(Sass的首席设计师和开发人员)表示,它将永远不会得到支持:

当前,&在语法上与元素选择器相同,因此它不能出现在一个元素选择器旁边。我认为这有助于弄清在哪里可以使用它。例如,foo&bar永远不会是有效的选择器(或者可能等同于foo& barfoo &bar)。我认为此用例不足以保证对此进行更改。

资料来源:#282 – Element.parent选择器

据我所知,没有可能的解决方法。

前端Stafan阿飞 2020.03.19

从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

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android