Sass поєднує батьківський за допомогою амперсанда (&) та селекторів типу


100

У мене проблеми з вкладанням в Сасс. Скажімо, у мене є такий 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;
   }
}

Як зробити посилання на селектор типу перед батьківським селектором, коли він є частиною того самого елемента?

Відповіді:


156

Як зазначає Кумар , це стало можливим з часів Сасса 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 .
Блейн

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 Ви підхопили кричущу помилку, дякую. Я відредагував свою відповідь робочим рішенням.
Бен Флемінг,

1
Тим не менш, selector-replaceце також ще один спосіб зробити це, але для цього потрібно знати, що таке селектор. selector-unifyМетод має перевагу використовується в Mixins.
Бен Флемінг

Чудова відповідь.
Відправляв

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.)


@ Lübnah Я погоджуюсь, але я не намагаюся визначити найкращі практики для досягнення мікроефективності. Я намагаюся змусити когось, хто ставить hrefтег на, pнаписати робочий CSS.
імджер

Існує абсолютно ніяка підтримка твердження & .selector - це взагалі погана практика, існує безліч випадків використання, точно таких, як той, який ОП публікував.
Mike Mellor

@MikeMellor OP писав .item { a& }і там немає Sass синтаксису , що (наскільки я знаю. Я припустив , що він, ймовірно , шукав що - щось на зразок синтаксису амперсанда ви описали , який використовуються досить регулярно в Sass. Однак, грунтуючись на прикладі OP, в .item { &a }це не дійсний і буде компілювати.itema . Так само, як я вже сказав у своїй відповіді. Чи щось мені не вистачає?
imjared

OP розшукується, .item { a& { ... } }що тепер можна зробити, як зазначає @Blaine .item { @at-root a#{&} { ... } }. Справа в тому, що якщо у вас є клас з елементом, це легко зробити, .item { &.class { ... } }то чому б вам не зробити те саме з необробленим елементом html. Те, що станом на той час, коли ОП розміщував це не було можливості це зробити, не означає, що він помилково хотів, щоб функціонал насправді це робив.
Mike Mellor

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 для отримання більш докладної інформації

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.