Sass объединяет родительский элемент с помощью амперсанда (&) с селекторами типов

101

У меня проблемы с вложением в Sass. Скажем, у меня есть следующий HTML-код:

<p href="#" class="item">Text</p>
<p href="#" class="item">Text</p>
<a href="#" class="item">Link</a>

Когда я пытаюсь вложить свои стили в следующее, я получаю ошибку компиляции:

.item {
    color: black;
    a& {
        color:blue;
   }
}

Как мне сослаться на селектор типа перед родительским селектором, если он является частью того же элемента?

МакШаман
источник

Ответы:

157

Как указывает Кумар , это стало возможным со времен Sass 3.3.0.rc.1 (Maptastic Maple).

Директива @ at-root приводит к тому, что одно или несколько правил генерируются в корне документа, а не вложены в их родительские селекторы.

Мы можем комбинировать @at-rootдирективу с интерполяцией,#{} чтобы достичь желаемого результата.

SASS

.item {
    color: black;
    @at-root {
        a#{&} {
            color:blue;
        }
    }
}

// Can also be written like this.
.item {
    color: black;
    @at-root a#{&} {
        color:blue;
    }
}

Выходной CSS

.item {
    color: black;
}
a.item {
    color: blue;
}
Блейн
источник
3
Это должно быть решением этого вопроса.
Кайхадрин
У меня это не работает ... .item a.itemпо какой-то причине выводится . Я тоже пробовал делать a#{&}это самостоятельно, и результат тот же.
jaminroe
@jaminroe вы используете Libsass? Это будет исправлено в 3.3 .
Blaine
1
@jaminroe похоже, что он использует libsass (node-sass) под капотом. Если это так, вам нужно подождать до 3.3.
Блейн,
1
У меня есть немного более сложная версия для решения, похожая, но с несколькими классами, которую нужно добавить к тегу - кто-нибудь?
Фрэнк
29

Метод @at-root-only не решит проблему, если вы собираетесь расширить ближайший селектор вверх по цепочке. Например:

#id > .element {
    @at-root div#{&} {
        color: blue;
    }
}

Будет компилироваться в:

div#id > .element {
    color: blue;
}

Что делать, если вам нужно присоединить свой тег к .elementвместо #id?

В Sass есть функция, selector-unify()которая решает эту проблему. Используя это @at-root, можно нацеливаться .element.

#id > .element {
    @at-root #{selector-unify(&, div)} {
        color: blue;
    }
}

Будет компилироваться в:

#id > div.element {
    color: blue;
}
Бен Флеминг
источник
1
Это не дало мне ожидаемого результата. В Sass 3.4.11 это выводится в #id > .element #id > div.element { color: blue; }. Другой подход заключается в использовании selector_replace, #id { > .element { @at-root #{selector-replace(&,'.element', 'div.element')} { color: blue;}}}. Вот суть для лучшей читаемости.
Blaine
@Blaine Вы обнаружили вопиющий баг, спасибо. Я отредактировал свой ответ рабочим решением.
Бен Флеминг,
1
Тем не менее, selector-replaceэто еще один способ сделать это, но для этого нужно знать, что такое селектор. Преимущество этого selector-unifyметода в том, что он используется в миксинах.
Бен Флеминг,
Отличный ответ.
Senthe
8

Для начала (на момент написания этого ответа) нет синтаксиса sass, который использует селектор & . Если вы собирались сделать что-то подобное, вам понадобится пробел между селектором и амперсандом. Например:

.item {
    .helper & {

    }
}

// compiles to:
.helper .item {

}

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

.item {
    &.helper {

    }
}

// compiles to:
.item.helper {

}

Это позволяет вам расширять селекторы другими классами, идентификаторами, псевдоселекторами и т. Д. К сожалению для вашего случая, это теоретически компилируется в нечто вроде .itema, что, очевидно, не работает.

Вы можете просто переосмыслить, как вы пишете свой CSS. Есть ли родительский элемент, который вы могли бы использовать?

<div class="item">
    <p>text</p>
    <p>text</p>
    <a href="#">a link</a>
</div>

Таким образом, вы можете легко написать свой SASS следующим образом:

.item {
    p {
        // paragraph styles here
    }
    a {
        // anchor styles here
    }
}

(Боковое примечание: вы должны взглянуть на свой html. Вы смешиваете одинарные и двойные кавычки И помещаете атрибуты href в теги p.)

imjared
источник
@ Lübnah Я согласен, но я не пытаюсь определить передовые методы повышения производительности на микроуровне. Я пытаюсь заставить кого-то, кто ставит hrefтег на a, pнаписать рабочий CSS.
imjared
Нет абсолютно никакой поддержки для того, чтобы сказать, что & .selector - это вообще плохая практика, существует множество вариантов использования, точно таких же, как один OP, опубликованный.
Майк Меллор
@MikeMellor OP написал, .item { a& }и для этого нет синтаксиса sass (насколько мне известно. Я предположил, что он, вероятно, искал что-то вроде синтаксиса амперсанда, который вы описали, который довольно часто используется в Sass. Однако, основываясь на примере OP, .item { &a }это недействителен и будет компилироваться в.itema . Как я уже сказал в своем ответе. Что-то мне не хватает?
imjared
.item { a& { ... } }Требуется OP, что теперь можно сделать, как указывает @Blaine .item { @at-root a#{&} { ... } }. Дело в том, что если у вас есть класс для элемента, это легко сделать, .item { &.class { ... } }так почему бы вам не сделать то же самое с необработанным элементом html. То, что на момент публикации OP не было возможности сделать это, не означает, что он был неправ, желая, чтобы функциональность действительно выполняла это.
Майк Меллор
4

AFAIK Если вы хотите объединить амперсанд для класса и тегов одновременно, вам необходимо использовать этот синтаксис:

.c1 {
  @at-root h1#{&},
    h2#{&}
    &.c2, {
    color: #aaa;
  }
}

будет компилироваться в

h1.c1,
h2.c1,
.c1.c2 {
  color: #aaa;
}

Другое использование (например, использование класса до @at-rootили использование нескольких @at-roots) приведет к ошибкам.

Надеюсь, это будет полезно

Вахид
источник
1
Я просто использовал это, очень полезно для миксинов, где вы хотите, например, изменять поведение для элементов span или div
santiago arizti
вау - очень круто :-) Так что, #{&}по сути, компилятор обманывает - или это всегда будет работать в будущем !?
Simon_Weaver
@Simon_Weaver в sass, все внутри #{}оценивается. Также &означает текущий селектор. Так #{&}оценивается .c1.
Вахид
Но вы обманываете его в том смысле, что один & не работает ;-)
Simon_Weaver
1
@Simon_Weaver см. Эту ссылку, чтобы увидеть больше примеров&
Вахид
3

Эта функция появилась в последней версии Sass, 3.3.0.rc.1(Maptastic Maple)

Две тесно связанные функции, которые вам необходимо использовать, - это скрипт &, который вы можете интерполировать во вложенных стилях для ссылки на родительские элементы, и @at-rootдиректива, которая помещает следующий за ним селектор или блок CSS в корень (это не будет есть родители в выведенном css)

См. Эту проблему Github для получения более подробной информации.

кумархарш
источник