sass css:来自孩子的目标父类

时间:2012-02-15 12:59:23

标签: css sass

我正在使用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定义使用一个地方。

感谢。

12 个答案:

答案 0 :(得分:28)

截至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的选择器。

答案 1 :(得分:20)

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

  

目前,&在语法上与元素选择器相同,所以它   不能一起出现。我认为这有助于澄清它的位置   用过的;例如,foo&bar永远不会是一个有效的选择器(或者会   也许相当于foo& barfoo &bar)。 我不认为这样用   案件足够强大,可以保证改变它。

来源:#282 – Element.parent selector

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

答案 2 :(得分:9)

最好的办法可能就是这样(假设你的.message-error类中的内容多于背景颜色。

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

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

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

答案 3 :(得分:2)

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

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

当然,body可以替换为其他公共父级,例如#Content或其他div名称,其中包含所有错误消息。

更新(另一个想法)

如果您使用@forlists,那么它似乎应该可行(我不确定的是该列表是否允许.(句号)。< / p>

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

答案 4 :(得分:2)

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

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

关键是'&amp;'之前的空格:

.message-error {
    background-color: red;

    p & {
        background-color: yellow
     }
  }

而不是:

.message-error {
    background-color: red;

    p& {
        background-color: yellow
     }
  }

答案 5 :(得分:0)

我之前也遇到了这个问题。 Bootstrap 3使用父选择器hack处理此问题。为了我自己的目的,我稍微调整了一下......

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

wheresrhys使用了类似的方法,但有一些sass错误。上面的代码允许您将其作为一个块进行管理并在编辑器中将其折叠。嵌套变量也使其成为本地变量,因此您可以为需要应用此hack的所有实例重用$ class。请参阅下面的工作样本......

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

答案 6 :(得分:0)

我做了一个解决这个问题的混音。

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

答案 7 :(得分:0)

我遇到了同样的问题,所以为此做了一个混音。

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

要使其正常工作,您还需要一个字符串替换功能from 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;
}
  

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

答案 8 :(得分:0)

我使用类似的解决方案创建了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';
    }
  }
}

此mixin将仅为最后一个父项添加选择器:

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

有关回购的更多信息。

答案 9 :(得分:0)

这就是您的操作方式

.Parent {
  $parentClass: &;

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

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

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

答案 10 :(得分:-1)

这个作弊可能有用

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

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

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

并且SASS内置了范围,这使得不必担心$and泄漏到样式表其余部分的价值

  

变量仅在嵌套选择器级别内可用   他们被定义的地方。如果它们是在任何嵌套之外定义的   选择器,它们随处可用。

答案 11 :(得分:-1)

在当前版本中:选择性史蒂夫(3.4.14)现在可以使用,只需要更新一下你的代码:

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

这仅适用于嵌套的一个级别,例如,如果你有这样的东西它不起作用:

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