sass css: целевой родительский класс от дочернего - PullRequest
40 голосов
/ 15 февраля 2012

Я использую sass и обнаружил проблему.Это пример того, что я пытаюсь сделать:

.message-error {
    background-color: red;

    p& {
        background-color: yellow
     }
  }

Ожидаемый css:

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

Идея: все элементы с ошибкой .message будут красного цвета, кроме случаев, когдаявляется p.message-error.Это не реальная ситуация, просто чтобы показать пример.

SASS не может скомпилировать это, я даже пытался объединить строки.Есть ли какой-нибудь плагин, который будет делать то же самое?

ПРИМЕЧАНИЕ. Я знаю, что могу добавить другое определение CSS, например

p.message-error{....}

, но я хотел бы избежать этого и использовать одно местодля всех определений .message-error.

Спасибо.

Ответы [ 10 ]

32 голосов
/ 02 декабря 2014

Начиная с 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.

20 голосов
/ 20 февраля 2012

Натали Вейзенбаум (ведущий дизайнер и разработчик Sass) говорит, что она никогда не будет поддерживаться:

В настоящее время & синтаксически совпадает с селектором элемента, поэтому не может появиться рядом с одним. Я думаю, что это помогает уточнить, где это может быть используемый; например, foo&bar никогда не будет действительным селектором (или будет возможно будет эквивалентно foo& bar или foo &bar). Я не думаю, что это использование дело достаточно сильное, чтобы оправдать его изменение.

Источник: # 282 - Селектор родительского элемента

Насколько мне известно, возможного обходного пути нет.

9 голосов
/ 21 февраля 2012

Лучше всего было бы сделать следующее (при условии, что в вашем классе .message-error у вас немного больше, чем просто цвет фона.

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

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

Этот подход не предлагает такой тесной группировки, но вы можете просто держать их близко друг к другу.

2 голосов
/ 05 марта 2013

@ 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
     }
  }
2 голосов
/ 22 февраля 2012

Я думаю, что если вы хотите, чтобы они были сгруппированы по родительскому селектору, вам может потребоваться добавить общего родителя:

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;}
1 голос
/ 21 сентября 2018

У меня была такая же проблема, поэтому я сделал миксин для этого.

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

Чтобы это работало, вам понадобится также функция замены строки ( изХьюго Жираудель ):

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

Вариант использования
Этот метод работает с вложенными селекторами, но не с составными.

0 голосов
/ 22 марта 2018

Я сделал миксин, который решает эту проблему.

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;
}
0 голосов
/ 10 июня 2015

В текущей версии: Селективный Стив (3.4.14) это теперь возможно, просто нужно немного обновить свой код:

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

это работает, только если вы вложены на один уровень, например, оно не работает, если у вас есть что-то вроде этого:

.messages{
    .message-error {
        background-color: red;
        p &{
            background-color: yellow
         }
     }
 }
0 голосов
/ 02 декабря 2014

Я сталкивался с этим и раньше. Bootstrap 3 обрабатывает это, используя хак для родительского селектора. Я немного подправил его для своих собственных целей ...

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

wheresrhys использует аналогичный подход выше, но с некоторыми грубыми ошибками. Приведенный выше код позволяет вам управлять им как одним блоком и свернуть его в редакторе. Вложенность переменной также делает ее локальной, поэтому вы можете повторно использовать $ class для всех случаев, когда вам нужно применить этот хак. Ниже приведен рабочий образец ...

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

0 голосов
/ 23 февраля 2012

Этот чит может работать

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

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

Возможно, вы даже сможете использовать $& в качестве имени переменной, но я не уверен на 100%, что она не выдаст ошибку.

И SASS имеет встроенную область видимости, что устраняет необходимость беспокоиться о значении $and, просачивающемся к остальной части вашей таблицы стилей

Переменные доступны только на уровне вложенных селекторов где они определены. Если они определены вне любого вложенного селекторы, они доступны везде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...