Sass łączy rodzica za pomocą znaku handlowego „i” (&) z selektorami typów

101

Mam problem z zagnieżdżeniem w Sassie. Powiedzmy, że mam następujący kod HTML:

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

Kiedy próbuję zagnieździć moje style w następujący sposób, pojawia się błąd kompilacji:

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

Jak odwołać się do selektora typu przed selektorem nadrzędnym, gdy jest on częścią tego samego elementu?

McShaman
źródło

Odpowiedzi:

157

Jak podkreśla Kumar , było to możliwe od czasów Sassa 3.3.0.rc.1 (Maptastic Maple).

Dyrektywa @ at-root powoduje, że jedna lub więcej reguł jest emitowanych w katalogu głównym dokumentu, zamiast być zagnieżdżonych pod ich selektorami nadrzędnymi.

Możemy połączyć @at-rootdyrektywę z interpolacją,#{} aby osiągnąć zamierzony rezultat.

SASS

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

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

Wyjście CSS

.item {
    color: black;
}
a.item {
    color: blue;
}
Blaine
źródło
3
To powinno być rozwiązanie tego pytania.
Kayhadrin
To nie działa dla mnie ... wyjście wychodzi z .item a.itemjakiegoś powodu. Próbowałem też robić a#{&}to samodzielnie i wciąż ten sam wynik.
jaminroe
@jaminroe czy używasz Libsass? Zostanie to naprawione w 3.3 .
Blaine
1
@jaminroe wygląda tak, jakby używał libsass (node-sass) pod maską. W takim przypadku musisz poczekać do 3.3.
Blaine,
1
Mam nieco trudniejszą wersję tego do rozwiązania, podobną, ale z wieloma klasami, którą trzeba dołączyć do tagu - ktoś?
Frank Nocke
29

Metoda @at-root-only nie rozwiąże problemu, jeśli zamierzasz przedłużyć najbliższy selektor w górę łańcucha. Jako przykład:

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

Skompiluje się do:

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

A co, jeśli .elementzamiast tego musisz dołączyć do swojego tagu #id?

W Sass jest funkcja o nazwie, selector-unify()która rozwiązuje ten problem. Używając tego z @at-root, można celować .element.

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

Skompiluje się do:

#id > div.element {
    color: blue;
}
Ben Fleming
źródło
1
To nie przyniosło zamierzonego wyniku. W Sass 3.4.11 wysyła to do #id > .element #id > div.element { color: blue; }. Innym podejściem byłoby użycie selector_replacerozszerzenia #id { > .element { @at-root #{selector-replace(&,'.element', 'div.element')} { color: blue;}}}. Oto streszczenie dla lepszej czytelności.
Blaine,
@Blaine Wykryłeś rażący błąd, dziękuję. Zmieniłem odpowiedź za pomocą działającego rozwiązania.
Ben Fleming
1
To powiedziawszy, selector-replacejest też innym sposobem, aby to zrobić, ale wymaga znajomości tego selektora. Ta selector-unifymetoda ma tę zaletę, że jest stosowana w mieszankach.
Ben Fleming
Świetna odpowiedź.
Senthe
8

Na początek (w czasie pisania tej odpowiedzi) nie ma składni sass, która używa selektora & . Jeśli zamierzałeś zrobić coś takiego, potrzebowałbyś spacji między selektorem a ampersandem. Na przykład:

.item {
    .helper & {

    }
}

// compiles to:
.helper .item {

}

Innym sposobem użycia znaku ampersand jest prawdopodobnie to, czego (niepoprawnie) szukasz:

.item {
    &.helper {

    }
}

// compiles to:
.item.helper {

}

Pozwala to na rozszerzenie selektorów o inne klasy, identyfikatory, pseudoselektory itp. Niestety w twoim przypadku teoretycznie skompilowałoby się to do czegoś takiego jak .itema, co oczywiście nie działa.

Możesz po prostu przemyśleć, jak piszesz CSS. Czy istnieje element nadrzędny, którego możesz użyć?

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

W ten sposób możesz łatwo napisać SASS w następujący sposób:

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

(Uwaga dodatkowa: powinieneś przyjrzeć się swojemu htmlowi. Łączysz pojedyncze i podwójne cudzysłowy ORAZ umieszczasz atrybuty href w tagach p).

imjared
źródło
@ Lübnah Zgadzam się, ale nie próbuję definiować najlepszych praktyk w zakresie zysków mikro-wydajności. Próbuję przekonać kogoś, kto umieszcza hreftag na a, pżeby napisał działający CSS.
imjared
Nie ma absolutnie żadnego wsparcia dla mówienia, że ​​& .selector jest złą praktyką, jest mnóstwo przypadków użycia dokładnie takich, jak ten, który opublikował OP.
Mike Mellor
@MikeMellor OP napisał .item { a& }i nie ma do tego składni sass (o ile wiem. Sugerowałem, że prawdopodobnie szukał czegoś takiego jak składnia ampersand, którą opisałeś, która jest używana dość regularnie w Sass. Jednak opierając się na przykładzie OP, .item { &a }to nieważne i zostanie skompilowane do.itema . Tak jak powiedziałem w mojej odpowiedzi. Czy jest coś, czego mi brakuje?
imjared
.item { a& { ... } }Potrzebny był OP, który teraz można zrobić, jak wskazuje @Blaine .item { @at-root a#{&} { ... } }. Chodzi o to, że jeśli masz klasę w elemencie, jest to łatwe do zrobienia, .item { &.class { ... } }więc dlaczego nie miałbyś być w stanie zrobić tego samego z surowym elementem html. Tylko dlatego, że nie było sposobu, aby to zrobić w momencie opublikowania OP, nie oznacza, że ​​nie miał racji, chcąc, aby ta funkcja faktycznie to robiła.
Mike Mellor
4

AFAIK W przypadku, gdy chcesz połączyć ampersand dla klasy i tagów w tym samym czasie, musisz użyć następującej składni:

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

skompiluje się do

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

Inne zastosowania (takie jak użycie klasy wcześniej @at-rootlub użycie wielu @at-root) doprowadzą do błędów.

Mam nadzieję, że to się przyda

Vahid
źródło
1
I właśnie używane to bardzo przydatne dla wstawek, w którym chcesz zmienić zachowanie dla rozpiętości lub elementów div na przykład
Santiago arizti
wow - bardzo fajnie :-) Więc w #{&}zasadzie oszukuje kompilator - czy to zawsze będzie działać w przyszłości !?
Simon_Weaver
@Simon_Weaver w sassie, wszystko w środku #{}jest oceniane. &Oznacza również aktualny selektor. Więc #{&}jest oceniany do .c1.
Vahid
Ale oszukujesz to w tym sensie, że & sam nie działa ;-)
Simon_Weaver
1
@Simon_Weaver patrz ten link, aby uzyskać więcej przykładów&
Vahid
3

Ta funkcja pojawiła się w najnowszej wersji Sass, 3.3.0.rc.1(Maptastic Maple)

Dwie ściśle powiązane funkcje, których będziesz potrzebować, to skryptowalny &, który możesz interpolować w zagnieżdżonych stylach, aby odwołać się do elementów nadrzędnych, oraz @at-rootdyrektywa, która umieszcza bezpośrednio następujący selektor lub blok css w katalogu głównym (nie będzie mieć rodziców w wyjściowym pliku css)

Więcej informacji znajdziesz w tym numerze na Githubie

kumarharsh
źródło