Sass menggabungkan induk menggunakan ampersand (&) dengan pemilih tipe

100

Saya mengalami masalah saat bersarang di Sass. Katakanlah saya memiliki HTML berikut:

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

Ketika saya mencoba untuk menumpuk gaya saya berikut ini saya mendapatkan kesalahan kompilasi:

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

Bagaimana cara mereferensikan pemilih tipe sebelum pemilih induk ketika itu adalah bagian dari elemen yang sama?

McShaman
sumber

Jawaban:

156

Seperti yang ditunjukkan Kumar , ini telah dimungkinkan sejak Sass 3.3.0.rc.1 (Maptastic Maple).

Arahan @ at-root menyebabkan satu atau beberapa aturan dipancarkan di root dokumen, daripada ditempatkan di bawah pemilih induknya.

Kita dapat menggabungkan @at-rootarahan bersama dengan interpolasi#{} untuk sampai pada hasil yang diinginkan.

KELANCANGAN

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

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

Output CSS

.item {
    color: black;
}
a.item {
    color: blue;
}
Blaine
sumber
3
Ini harus menjadi solusi untuk pertanyaan ini.
Kayhadrin
Ini tidak berhasil untuk saya ... output keluar .item a.itemkarena beberapa alasan. Saya mencoba melakukannya a#{&}sendiri juga dan hasilnya tetap sama.
jaminroe
@jaminroe apakah Anda menggunakan Libsass? Ini akan diperbaiki di 3.3 .
Blaine
1
@jaminroe sepertinya menggunakan libsass (node-sass) di bawah tenda. Jika demikian, Anda harus menunggu hingga 3,3.
Blaine
1
Saya memiliki versi yang sedikit lebih sulit untuk dipecahkan, serupa, tetapi dengan banyak kelas, yang harus ditambahkan ke tag - siapa saja?
Frank Nocke
29

The @at-rootMetode -hanya tidak akan memecahkan masalah jika Anda berniat untuk memperpanjang pemilih terdekat sampai rantai. Sebagai contoh:

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

Akan dikompilasi ke:

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

Bagaimana jika Anda perlu menggabungkan tag Anda ke .elementalih-alih #id?

Ada fungsi di Sass yang disebut selector-unify()yang menyelesaikan ini. Menggunakan ini dengan @at-rootitu dimungkinkan untuk menargetkan .element.

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

Akan dikompilasi ke:

#id > div.element {
    color: blue;
}
Ben Fleming
sumber
1
Ini tidak memberi saya hasil yang diharapkan. Di Sass 3.4.11, ini menghasilkan #id > .element #id > div.element { color: blue; }. Pendekatan lain akan digunakan selector_replace, #id { > .element { @at-root #{selector-replace(&,'.element', 'div.element')} { color: blue;}}}. Berikut adalah Inti untuk keterbacaan yang lebih baik.
Blaine
@Blaine Anda telah menemukan bug yang mencolok, terima kasih. Saya telah mengedit jawaban saya dengan solusi yang berfungsi.
Ben Fleming
1
selector-replaceMeskipun demikian , ini juga merupakan cara lain untuk melakukannya, tetapi perlu mengetahui apa itu selektor. The selector-unifymetode memiliki manfaat yang digunakan dalam mixin.
Ben Fleming
Jawaban yang luar biasa.
Senthe
8

Sebagai permulaan, (pada saat menulis jawaban ini) tidak ada sintaks sass yang menggunakan selector & . Jika Anda akan melakukan sesuatu seperti itu, Anda memerlukan spasi antara pemilih dan simbol ampers. Sebagai contoh:

.item {
    .helper & {

    }
}

// compiles to:
.helper .item {

}

Cara lain untuk menggunakan ampersand mungkin adalah yang Anda (salah) cari:

.item {
    &.helper {

    }
}

// compiles to:
.item.helper {

}

Ini memungkinkan Anda untuk memperluas selektor dengan kelas lain, ID, pseudo-selektor, dll. Sayangnya untuk kasus Anda, ini secara teoritis akan dikompilasi ke sesuatu seperti .itema yang jelas tidak berfungsi.

Anda mungkin hanya ingin memikirkan kembali bagaimana Anda menulis CSS Anda. Apakah ada elemen induk yang dapat Anda gunakan?

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

Dengan cara ini, Anda dapat dengan mudah menulis SASS Anda dengan cara berikut:

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

(Catatan tambahan: Anda harus melihat html Anda. Anda mencampur tanda kutip tunggal dan ganda DAN meletakkan atribut href pada tag p.)

imjared
sumber
@ Lübnah Saya setuju tapi saya tidak mencoba untuk mendefinisikan praktik terbaik untuk perolehan kinerja mikro. Saya mencoba membuat seseorang yang memberi hreftag pada a puntuk menulis CSS yang berfungsi.
imjared
Sama sekali tidak ada dukungan untuk mengatakan & .selector adalah praktik yang buruk sama sekali, ada banyak kasus penggunaan persis seperti yang diposting OP.
Mike Mellor
@MikeMellor OP menulis .item { a& }dan tidak ada sintaks sass untuk itu (sejauh yang saya ketahui. Saya menyarankan dia mungkin mencari sesuatu seperti sintaks ampersand yang Anda jelaskan yang digunakan secara teratur di Sass. Namun, membangun contoh OP, .item { &a }adalah tidak valid dan akan dikompilasi.itema . Seperti yang saya katakan dalam jawaban saya. Apakah ada sesuatu yang saya lewatkan?
imjared
OP ingin .item { a& { ... } }yang sekarang bisa dilakukan seperti yang ditunjukkan @Blaine .item { @at-root a#{&} { ... } }. Intinya adalah jika Anda memiliki kelas pada elemen itu mudah dilakukan .item { &.class { ... } }jadi mengapa Anda tidak bisa melakukan hal yang sama dengan elemen html mentah. Hanya karena tidak ada cara untuk melakukannya pada saat OP diposting tidak berarti dia salah untuk menginginkan fungsionalitas tersebut benar-benar melakukannya.
Mike Mellor
4

AFAIK Jika Anda ingin menggabungkan ampersand untuk kelas dan tag pada saat yang sama, Anda perlu menggunakan sintaks ini:

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

akan dikompilasi ke

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

Kegunaan lain (seperti menggunakan kelas sebelumnya @at-rootatau menggunakan beberapa @at-root) akan menyebabkan kesalahan.

Semoga bermanfaat

Vahid
sumber
1
Saya baru saja menggunakan ini, sangat berguna untuk mixin di mana Anda ingin memvariasikan perilaku untuk elemen span atau div misalnya
santiago arizti
wow - sangat keren :-) Jadi pada #{&}dasarnya menipu kompiler - atau akankah ini selalu berhasil di masa depan !?
Simon_Weaver
@Simon_Weaver di sass, semua yang ada di dalamnya #{}dievaluasi. Juga &berarti pemilih saat ini. Jadi #{&}dievaluasi .c1.
Vahid
Tapi Anda menipunya dalam arti bahwa & alone tidak berfungsi ;-)
Simon_Weaver
1
@Simon_Weaver lihat link ini untuk lebih banyak contoh&
Vahid
3

Fitur ini telah hadir di versi terbaru Sass, 3.3.0.rc.1(Maptastic Maple)

Dua fitur terkait erat yang perlu Anda gunakan adalah scriptable &, yang dapat Anda interpolasi dalam gaya bertingkat untuk mereferensikan elemen induk, dan@at-root direktif, yang menempatkan selektor atau blok css berikut di root (tidak akan memiliki orang tua di css yang dikeluarkan)

Lihat masalah Github ini untuk lebih jelasnya

kumarharsh
sumber