หนึ่งในฟีเจอร์ตัวประมวลผล CSS ที่เราชื่นชอบพร้อมให้ใช้งานในปัจจุบัน ได้แก่ การซ้อนกฎรูปแบบ
ก่อนที่จะซ้อน ตัวเลือกทั้งหมดจำเป็นต้องประกาศอย่างชัดเจน โดยแยกออกจากอีกตัวเลือกหนึ่ง ซึ่งทำให้เกิดการกล่าวซ้ำๆ สไตล์ชีตจำนวนมาก และประสบการณ์การเขียนที่กระจัดกระจาย
.nesting { color: hotpink; } .nesting > .is { color: rebeccapurple; } .nesting > .is > .awesome { color: deeppink; }
หลังจากซ้อนแล้ว ตัวเลือกจะดำเนินการต่อได้ และกฎรูปแบบที่เกี่ยวข้องจะจัดกลุ่มได้ภายใน
.nesting { color: hotpink; > .is { color: rebeccapurple; > .awesome { color: deeppink; } } }
การซ้อนกันช่วยให้นักพัฒนาซอฟต์แวร์ไม่จำเป็นต้องทำซ้ำตัวเลือก ขณะเดียวกันก็ระบุตำแหน่งกฎสไตล์สำหรับองค์ประกอบที่เกี่ยวข้องร่วมกัน และยังช่วยให้สไตล์เข้ากับ
HTML เป้าหมายได้ด้วย หากนำคอมโพเนนต์ .nesting
ในตัวอย่างก่อนหน้านี้ออกจากโปรเจ็กต์ คุณจะลบทั้งกลุ่มได้โดยไม่ต้องค้นหาไฟล์สำหรับอินสแตนซ์ตัวเลือกที่เกี่ยวข้อง
การฝังมีประโยชน์ดังนี้ - องค์กร - การลดขนาดไฟล์ - การปรับโครงสร้าง
การ Nesting มีให้ใช้งานใน Chrome 112 และคุณยังลองใช้ใน Technical Preview 162 ของ Safari ได้ด้วย
เริ่มต้นใช้งาน CSS Nesting
ในช่วงที่เหลือของโพสต์นี้ เราจะใช้แซนด์บ็อกซ์สาธิตต่อไปนี้เพื่อช่วยให้คุณเห็นภาพของรายการที่เลือก ในสถานะเริ่มต้นนี้ จะไม่มีการเลือก และทุกอย่างจะมองเห็นได้ การเลือกรูปร่างและขนาดต่างๆ ทำให้คุณสามารถฝึกไวยากรณ์และเห็นการใช้งานจริง
ภายในแซนด์บ็อกซ์จะมีวงกลม สามเหลี่ยม และสี่เหลี่ยมจัตุรัส บ้างก็เล็ก กลาง หรือใหญ่ ส่วนแอตทริบิวต์อื่นๆ จะมีสีน้ำเงิน สีชมพู หรือสีม่วง ทั้งหมดอยู่ใน .demo
ที่มีเอลิเมนต์ ต่อไปนี้เป็นตัวอย่างองค์ประกอบ HTML ที่คุณจะกำหนดเป้าหมาย
<div class="demo">
<div class="sm triangle pink"></div>
<div class="sm triangle blue"></div>
<div class="square blue"></div>
<div class="sm square pink"></div>
<div class="sm square blue"></div>
<div class="circle pink"></div>
…
</div>
ตัวอย่างการฝัง
การซ้อน CSS ให้คุณกำหนดสไตล์สำหรับองค์ประกอบภายในบริบทของตัวเลือกอื่น
.parent {
color: blue;
.child {
color: red;
}
}
ในตัวอย่างนี้ ตัวเลือกคลาส .child
จะฝังอยู่ในตัวเลือกคลาส .parent
ซึ่งหมายความว่าตัวเลือก .child
ที่ฝังไว้จะมีผลกับองค์ประกอบที่เป็นระดับย่อยขององค์ประกอบที่มีคลาส .parent
เท่านั้น
ตัวอย่างนี้อาจใช้สัญลักษณ์ &
แทนก็ได้ เพื่อบ่งบอกว่าควรวางคลาสหลักไว้ที่ไหน
.parent {
color: blue;
& .child {
color: red;
}
}
ตัวอย่างทั้งสองนี้มีฟังก์ชันการทำงานที่เทียบเท่ากัน และเหตุผลที่คุณมีตัวเลือก จะชัดเจนขึ้นเมื่อมีการดูตัวอย่างขั้นสูงขึ้นในบทความนี้
การเลือกแวดวง
สำหรับตัวอย่างแรกนี้ งานคือการเพิ่มรูปแบบให้จางลงและเบลอเฉพาะวงกลมภายในการสาธิต
โดยไม่ซ้อน CSS ในวันนี้
.demo .circle {
opacity: .25;
filter: blur(25px);
}
การซ้อนทำได้ 2 วิธีดังนี้
/* & is explicitly placed in front of .circle */
.demo {
& .circle {
opacity: .25;
filter: blur(25px);
}
}
หรือ
/* & + " " space is added for you */
.demo {
.circle {
opacity: .25;
filter: blur(25px);
}
}
ผลลัพธ์ องค์ประกอบทั้งหมดใน .demo
ที่มีคลาส .circle
จะเบลอและแทบไม่ปรากฏ ดังนี้
การเลือกสามเหลี่ยมและสี่เหลี่ยมจัตุรัส
งานนี้ต้องมีการเลือกองค์ประกอบที่ซ้อนกันหลายรายการ หรือที่เรียกว่าตัวเลือกกลุ่ม
CSS ในปัจจุบันมี 2 วิธีคือการไม่ซ้อน
.demo .triangle,
.demo .square {
opacity: .25;
filter: blur(25px);
}
หรือใช้ :is()
/* grouped with :is() */
.demo :is(.triangle, .square) {
opacity: .25;
filter: blur(25px);
}
เมื่อใช้การซ้อน มี 2 วิธีที่ใช้ได้ดังนี้
.demo {
& .triangle,
& .square {
opacity: .25;
filter: blur(25px);
}
}
หรือ
.demo {
.triangle, .square {
opacity: .25;
filter: blur(25px);
}
}
ผลลัพธ์ มีเพียง .circle
องค์ประกอบยังคงอยู่ภายใน .demo
:
การเลือกรูปสามเหลี่ยมและวงกลมขนาดใหญ่
งานนี้ต้องใช้ตัวเลือกแบบผสม ซึ่งองค์ประกอบจะต้องมีทั้ง 2 คลาสจึงจะเลือกได้
โดยไม่ซ้อน CSS ในวันนี้
.demo .lg.triangle,
.demo .lg.square {
opacity: .25;
filter: blur(25px);
}
หรือ
.demo .lg:is(.triangle, .circle) {
opacity: .25;
filter: blur(25px);
}
เมื่อใช้การซ้อน มี 2 วิธีที่ใช้ได้ดังนี้
.demo {
.lg.triangle,
.lg.circle {
opacity: .25;
filter: blur(25px);
}
}
หรือ
.demo {
.lg {
&.triangle,
&.circle {
opacity: .25;
filter: blur(25px);
}
}
}
ผลลัพธ์ สามเหลี่ยมขนาดใหญ่และวงกลมทั้งหมดจะถูกซ่อนใน .demo
:
เคล็ดลับมือโปรพร้อมตัวเลือกสารประกอบและการซ้อนกัน
สัญลักษณ์ &
คือเพื่อนของคุณในที่นี้เนื่องจากแสดงให้เห็นวิธีติดกับตัวเลือกที่ซ้อนกันอย่างชัดเจน ลองพิจารณาตัวอย่างต่อไปนี้
.demo {
.lg {
.triangle,
.circle {
opacity: .25;
filter: blur(25px);
}
}
}
แม้ว่าวิธีการซ้อนที่ถูกต้อง แต่ผลลัพธ์จะไม่ตรงกับองค์ประกอบที่คุณคาดไว้
เนื่องจากหากไม่ใส่ &
เพื่อระบุผลลัพธ์ที่ต้องการของ .lg.triangle,
.lg.circle
รวมเข้าด้วยกัน ผลลัพธ์จริงจะเป็น .lg .triangle, .lg
.circle
และตัวเลือกองค์ประกอบสืบทอด
เลือกรูปทั้งหมดยกเว้นรูปสีชมพู
งานนี้ต้องใช้คลาสสมมติของนิเสธ ซึ่งองค์ประกอบต้องไม่มีตัวเลือกที่ระบุ
โดยไม่ซ้อน CSS ในวันนี้
.demo :not(.pink) {
opacity: .25;
filter: blur(25px);
}
เมื่อใช้การซ้อน มี 2 วิธีที่ใช้ได้ดังนี้
.demo {
:not(.pink) {
opacity: .25;
filter: blur(25px);
}
}
หรือ
.demo {
& :not(.pink) {
opacity: .25;
filter: blur(25px);
}
}
ผลลัพธ์ รูปร่างทั้งหมดที่ไม่ใช่สีชมพูจะซ่อนอยู่ใน .demo
:
ความแม่นยำและความยืดหยุ่นด้วย &
สมมติว่าคุณต้องการกำหนดเป้าหมายเป็น .demo
ด้วยตัวเลือก :not()
&
ต้องระบุสำหรับกรณีต่อไปนี้
.demo {
&:not() {
...
}
}
สารประกอบนี้ .demo
และ :not()
เป็น .demo:not()
ซึ่งตรงข้ามกับตัวอย่างก่อนหน้านี้ซึ่งต้องการ .demo :not()
การช่วยเตือนนี้สำคัญมากเมื่อต้องการซ้อนการโต้ตอบ :hover
.demo {
&:hover {
/* .demo:hover */
}
:hover {
/* .demo :hover */
}
}
ตัวอย่างการซ้อนอื่นๆ
ข้อมูลจำเพาะของ CSS สำหรับการซ้อนมีตัวอย่างเพิ่มเติมแล้ว หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับไวยากรณ์ผ่านตัวอย่าง ก็จะมีตัวอย่างที่ถูกต้องและไม่ถูกต้องมากมาย
ตัวอย่าง 2-3 ข้อต่อไปนี้จะแนะนำฟีเจอร์การฝัง CSS คร่าวๆ เพื่อช่วยให้คุณเข้าใจความสามารถที่ครอบคลุม
กำลังซ้อน @media
การย้ายไปยังพื้นที่อื่นของสไตล์ชีตเพื่อหาเงื่อนไขคำค้นหาสื่อที่แก้ไขตัวเลือกและสไตล์อาจเป็นเรื่องน่ารำคาญใจมาก สิ่งที่จะทำให้เสียสมาธิได้นั้น หมดไปโดยความสามารถในการฝังเงื่อนไขต่างๆ ไว้ภายในบริบทโดยตรง
เพื่อความสะดวกของไวยากรณ์ หากคิวรี่สื่อที่ซ้อนกันแก้ไขเฉพาะรูปแบบสำหรับบริบทตัวเลือกปัจจุบันเท่านั้น คุณจะสามารถใช้ไวยากรณ์ที่น้อยที่สุดได้
.card {
font-size: 1rem;
@media (width >= 1024px) {
font-size: 1.25rem;
}
}
การใช้ &
อย่างชัดแจ้งจะใช้ทำสิ่งต่อไปนี้ได้ด้วย
.card {
font-size: 1rem;
@media (width >= 1024px) {
&.large {
font-size: 1.25rem;
}
}
}
ตัวอย่างนี้แสดงไวยากรณ์แบบขยายด้วย &
พร้อมกับกําหนดเป้าหมายการ์ด .large
เพื่อแสดงฟีเจอร์การวางซ้อนเพิ่มเติมที่ยังทํางานต่อไป
ดูข้อมูลเพิ่มเติมเกี่ยวกับการซ้อน @กฎ
ซ้อนได้ทุกที่
ตัวอย่างทั้งหมดจนถึงจุดนี้ยังคงปรากฏต่อหรือต่อท้ายบริบทก่อนหน้า คุณสามารถเปลี่ยนแปลงหรือจัดเรียงบริบทใหม่ทั้งหมดได้หากต้องการ
.card {
.featured & {
/* .featured .card */
}
}
สัญลักษณ์ &
แสดงถึงการอ้างอิงออบเจ็กต์ตัวเลือก (ไม่ใช่สตริง) และจะวางไว้ที่ใดก็ได้ในตัวเลือกที่ซ้อนกัน สามารถวางไว้ได้หลายครั้ง ดังนี้
.card {
.featured & & & {
/* .featured .card .card .card */
}
}
แม้ว่าตัวอย่างนี้จะดูไม่มีประโยชน์ แต่ก็มีบางสถานการณ์ที่การสามารถอธิบายบริบทตัวเลือกซ้ำได้ก็ช่วยได้มาก
ตัวอย่างการซ้อนที่ไม่ถูกต้อง
มีไวยากรณ์ที่ซ้อนกันอยู่บางสถานการณ์ที่ไม่ถูกต้องและอาจทำให้คุณประหลาดใจหากคุณซ้อนอยู่ในตัวประมวลผลล่วงหน้า
การฝังและการเชื่อมต่อ
แบบแผนการตั้งชื่อคลาส CSS จำนวนมากใช้การซ้อนกันที่สามารถเชื่อมต่อหรือผนวกตัวเลือกเสมือนกับสตริงได้ วิธีนี้ไม่ได้ผลในการซ้อน CSS เนื่องจาก ตัวเลือกไม่ใช่สตริง แต่เป็นการอ้างอิงออบเจ็กต์
.card {
&--header {
/* is not equal to ".card--header" */
}
}
ดูคำอธิบายเชิงลึกเพิ่มเติมได้ในข้อกำหนด
ตัวอย่างการซ้อนที่หลอกลวง
การฝังภายในรายการตัวเลือกและ :is()
ลองใช้บล็อก CSS ที่ซ้อนกันต่อไปนี้
.one, #two {
.three {
/* some styles */
}
}
นี่คือตัวอย่างแรกที่เริ่มต้นด้วยรายการตัวเลือก จากนั้นจะซ้อนต่อไปอีก ตัวอย่างก่อนหน้านี้จบลงด้วยรายการตัวเลือกเท่านั้น ตัวอย่างการซ้อนไม่มีอะไรที่ไม่ถูกต้อง แต่มีรายละเอียดการใช้งานที่ค่อนข้างซับซ้อนเกี่ยวกับการซ้อนภายในรายการตัวเลือก โดยเฉพาะรายการที่มีตัวเลือกรหัส
เบราว์เซอร์จะรวม :is()
ในรายการตัวเลือกที่ไม่ใช่การซ้อนที่อยู่ภายในมากที่สุดเพื่อให้ความตั้งใจของการซ้อนทำงานได้ การตัดข้อความนี้จะคงการจัดกลุ่มรายการตัวเลือกภายในบริบทที่สร้างขึ้น ผลข้างเคียงของการจัดกลุ่มนี้ :is(.one, #two)
คือใช้ความเฉพาะเจาะจงของคะแนนสูงสุดภายในตัวเลือกภายในวงเล็บ นี่คือวิธีที่ :is()
ทำงานอยู่เสมอ แต่อาจทำให้คุณแปลกใจเมื่อใช้ไวยากรณ์ที่ซ้อนกัน เนื่องจากไม่ใช่สิ่งที่เขียนขึ้นมาจริงๆ เคล็ดลับที่สรุปก็คือ การซ้อนกับรหัสและรายการตัวเลือกอาจทําให้ตัวเลือกความเฉพาะเจาะจงสูงมาก
หากต้องการสรุปตัวอย่างที่ซับซ้อนให้ชัดเจน ระบบจะใช้บล็อกที่ซ้อนกันก่อนหน้ากับเอกสารดังนี้
:is(.one, #two) .three {
/* some styles */
}
ให้คอยสังเกตหรือสอนให้โปรแกรมรวบรวมข้อมูลเตือนเมื่อซ้อนอยู่ในรายการตัวเลือกที่ใช้ตัวเลือกรหัส ข้อมูลจำเพาะของการซ้อนทั้งหมดภายในรายการตัวเลือกนั้นจะอยู่ในระดับสูง
การผสมการซ้อนและการประกาศ
ลองใช้บล็อก CSS ที่ซ้อนกันต่อไปนี้
.card {
color: green;
& { color: blue; }
color: red;
}
สีขององค์ประกอบ .card
จะเป็น blue
การประกาศสไตล์ที่แทรกเข้ามาจะยกกลับไปอยู่ด้านบน เหมือนกับว่าการประกาศนั้นสร้างขึ้นก่อนที่จะมีการซ้อนเกิดขึ้น ดูรายละเอียดเพิ่มเติมได้ในข้อกำหนด
แต่มีหลายวิธี รายการต่อไปนี้จะรวมรูปแบบสี 3 สีใน &
ซึ่งยังคงเรียงลำดับการเรียงซ้อนตามที่ผู้เขียนตั้งใจไว้ สีขององค์ประกอบ .card
จะเป็นสีแดง
.card {
color: green;
& { color: blue; }
& { color: red; }
}
อันที่จริงแล้ว แนวทางปฏิบัติที่ดีคือการรวมสไตล์ใดๆ ที่ต่อจากการฝังด้วย &
.card {
color: green;
@media (prefers-color-scheme: dark) {
color: lightgreen;
}
& {
aspect-ratio: 4/3;
}
}
การตรวจหาฟีเจอร์
ฟีเจอร์การตรวจหาการซ้อน CSS มี 2 วิธีอันยอดเยี่ยม ได้แก่ การใช้การซ้อนหรือใช้ @supports
เพื่อตรวจสอบความสามารถในการแยกวิเคราะห์ตัวเลือกการซ้อน
การใช้การซ้อน:
html {
.has-nesting {
display: block;
}
.no-nesting {
display: none;
}
}
ใช้ @supports
:
@supports (selector(&)) {
/* nesting parsing available */
}
เพื่อนร่วมงานของฉัน Bramus มี Codepen ที่ยอดเยี่ยมซึ่งแสดงกลยุทธ์นี้
การแก้ไขข้อบกพร่องด้วยเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome
ปัจจุบันการรองรับการซ้อนในเครื่องมือสำหรับนักพัฒนาเว็บมีปริมาณน้อยที่สุด ขณะนี้คุณจะเห็นรูปแบบแสดงในแผงรูปแบบตามที่คาดไว้ แต่ยังไม่รองรับการติดตามการซ้อนและบริบทตัวเลือกแบบเต็มรูปแบบ เรามีการออกแบบและแผนที่จะทำส่วนนี้ ให้มีความโปร่งใสและชัดเจน
Chrome 113 มีแผนที่จะรองรับการซ้อน CSS เพิ่มเติม โปรดอดใจรอ
อนาคต
CSS Nesting เป็นเวอร์ชัน 1 เท่านั้น เวอร์ชัน 2 จะมีน้ำตาลแบบไวยากรณ์มากขึ้นและมีกฎให้จำน้อยกว่า มีความต้องการจำนวนมากในการแยกวิเคราะห์การวางซ้อนที่ไม่จำกัดหรือมีช่วงเวลาที่ซับซ้อน
การวางซ้อนนี้ถือเป็นการเพิ่มประสิทธิภาพครั้งใหญ่สำหรับภาษา CSS ซึ่งมีนัยยะเกี่ยวข้องกับ สถาปัตยกรรมเกือบทุกด้านของ CSS คุณจึงต้องศึกษาและทำความเข้าใจผลกระทบครั้งใหญ่นี้อย่างละเอียดก่อน จึงจะระบุเวอร์ชัน 2 ได้อย่างมีประสิทธิภาพ
สุดท้ายนี้ นี่คือการสาธิต
ที่ใช้ @scope
, การวางซ้อน และ @layer
รวมกัน เป็นเรื่องที่น่าตื่นเต้นมาก