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

ฉันจะอ้างอิงตัวเลือกประเภทก่อนตัวเลือกหลักได้อย่างไรเมื่อเป็นส่วนหนึ่งขององค์ประกอบเดียวกัน

คำตอบ:


159

เป็นจุดมาร์ออกมานี้ได้รับเป็นไปได้ตั้งแต่ 3.3.0.rc.1 (Maptastic Maple)Sass

คำสั่ง @ 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
นี่น่าจะเป็นทางออกสำหรับคำถามนี้
Kayhadrin

สิ่งนี้ไม่ได้ผลสำหรับฉัน ... ผลลัพธ์ออกมา.item a.itemด้วยเหตุผลบางประการ ฉันลองทำa#{&}ด้วยตัวเองแล้วก็ยังได้ผลลัพธ์เหมือนเดิม
jaminroe

@jaminroe คุณใช้ Libsass อยู่หรือเปล่า? มันจะได้รับการแก้ไขใน 3.3
เบลน

1
@jaminroe ดูเหมือนว่าจะใช้ libsass (node-sass) ใต้ฝากระโปรง หากเป็นเช่นนั้นคุณจะต้องรอจนถึง 3.3
เบลน

1
ฉันมีเวอร์ชันที่ยากกว่าเล็กน้อยในการแก้ปัญหาคล้ายกัน แต่มีหลายคลาสที่ต้องต่อท้ายแท็ก - ใคร?
Frank Nocke

30

@at-rootวิธีเท่านั้นจะไม่แก้ปัญหาหากคุณตั้งใจที่จะขยายตัวเลือกที่อยู่ใกล้ขึ้นโซ่ ตัวอย่างเช่น:

#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;}}}
เบลน

@ เบลนคุณได้รับข้อผิดพลาดที่เห็นได้ชัดขอบคุณ ฉันได้แก้ไขคำตอบด้วยวิธีการแก้ปัญหาที่ใช้งานได้แล้ว
Ben Fleming

1
ที่กล่าวมาselector-replaceก็เป็นอีกวิธีหนึ่งเช่นกัน แต่ต้องรู้ว่าตัวเลือกคืออะไร selector-unifyวิธีมีประโยชน์ในการใช้งานใน mixins
Ben Fleming

คำตอบที่ยอดเยี่ยม
Senthe

8

สำหรับ starters, (ในขณะที่เขียนคำตอบนี้) ไม่มีไวยากรณ์เขื่องที่ใช้ตัวเลือกและ ถ้าคุณจะทำอะไรแบบนั้นคุณต้องมีช่องว่างระหว่างตัวเลือกกับเครื่องหมายและ ตัวอย่างเช่น:

.item {
    .helper & {

    }
}

// compiles to:
.helper .item {

}

วิธีอื่นในการใช้เครื่องหมายและอาจเป็นสิ่งที่คุณกำลังมองหา (ไม่ถูกต้อง):

.item {
    &.helper {

    }
}

// compiles to:
.item.helper {

}

สิ่งนี้ช่วยให้คุณสามารถขยายตัวเลือกด้วยคลาสอื่น ๆ ID ตัวเลือกหลอก ฯลฯ น่าเสียดายสำหรับกรณีของคุณสิ่งนี้จะรวบรวมในทางทฤษฎีกับบางสิ่งเช่น. 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 ที่ใช้งานได้
imjared

ไม่มีการสนับสนุนอย่างแน่นอนสำหรับการพูดว่า & .selector เป็นการปฏิบัติที่ไม่ดีเลยมีกรณีการใช้งานมากมายเหมือนกับที่ OP โพสต์
Mike Mellor

@ MikeMellor OP เขียน.item { a& }และไม่มีไวยากรณ์ sass สำหรับสิ่งนั้น (เท่าที่ฉันทราบฉันแนะนำว่าเขาอาจกำลังมองหาบางอย่างเช่นแอมเพอร์แซนด์ไวยากรณ์ที่คุณอธิบายไว้ซึ่งใช้เป็นประจำใน Sass อย่างไรก็ตามการสร้างจากตัวอย่างของ OP .item { &a }คือ ไม่ถูกต้องและจะรวบรวมให้.itemaเหมือนกับที่ฉันพูดในคำตอบของฉันมีบางอย่างที่ขาดหายไปหรือไม่?
imjared

OP ต้องการ.item { a& { ... } }ซึ่งขณะนี้สามารถทำได้เช่น @Blaine .item { @at-root a#{&} { ... } }ชี้ให้เห็นด้วย ประเด็นคือถ้าคุณมีคลาสในองค์ประกอบมันง่ายที่จะทำ.item { &.class { ... } }ทำไมคุณไม่สามารถทำสิ่งเดียวกันกับองค์ประกอบ html ดิบ เพียงเพราะไม่มีวิธีที่จะทำในขณะที่ OP โพสต์ไม่ได้หมายความว่าเขาไม่ถูกต้องที่ต้องการให้ฟังก์ชันทำงานได้จริง
Mike Mellor

4

AFAIK ในกรณีที่คุณต้องการรวมแอมเพอร์แซนด์สำหรับคลาสและแท็กในเวลาเดียวกันคุณต้องใช้ไวยากรณ์นี้:

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

จะคอมไพล์

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

การใช้งานอื่น ๆ (เช่นการใช้คลาสก่อนหน้า@at-rootหรือใช้หลาย ๆ@at-root ) จะทำให้เกิดข้อผิดพลาด

หวังว่าจะเป็นประโยชน์


1
ฉันเพิ่งใช้สิ่งนี้มีประโยชน์มากสำหรับมิกซ์อินที่คุณต้องการเปลี่ยนพฤติกรรมสำหรับองค์ประกอบช่วงหรือ div เช่น
santiago arizti

ว้าว - เจ๋งมาก :-) ดังนั้น#{&}โดยพื้นฐานแล้วการหลอกคอมไพเลอร์ - หรือจะใช้งานได้ในอนาคต!?
Simon_Weaver

@Simon_Weaver ใน sass ทุกอย่างภายใน#{}ได้รับการประเมิน ยัง&หมายถึงตัวเลือกปัจจุบัน ดังนั้นการประเมินเพื่อ#{&} .c1
Vahid

แต่คุณกำลังหลอกมันในความรู้สึกว่าอยู่คนเดียวและไม่ได้ทำงาน ;-)
Simon_Weaver

1
@Simon_Weaver ดูลิงค์นี้เพื่อดูตัวอย่างเพิ่มเติมของ&
Vahid

3

คุณลักษณะนี้มีอยู่ใน Sass เวอร์ชันใหม่ล่าสุด 3.3.0.rc.1(Maptastic Maple)

คุณลักษณะที่เกี่ยวข้องอย่างใกล้ชิดสองประการที่คุณต้องใช้คือสคริปต์&ซึ่งคุณสามารถแก้ไขภายในสไตล์ที่ซ้อนกันเพื่ออ้างอิงองค์ประกอบหลักและ@at-rootคำสั่งซึ่งจะวางตัวเลือกหรือบล็อกของ css ต่อไปนี้ไว้ที่รูททันที (จะไม่ มีผู้ปกครองคนใดอยู่ใน css ที่ยื่นออกมา)

ดูปัญหา Github นี้สำหรับรายละเอียดเพิ่มเติม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.