หนึ่งในฟีเจอร์สำหรับผู้ประมวลผลข้อมูลล่วงหน้า CSS ที่เราชื่นชอบมีอยู่ในภาษาแล้ว นั่นคือการซ้อนกฎรูปแบบ
ก่อนการซ้อน ตัวเลือกทุกรายการต้องได้รับการประกาศอย่างชัดเจนแยกต่างหากจากตัวเลือกอื่น ซึ่งทำให้เกิดการทำซ้ำ กลุ่มสไตล์ชีต และประสบการณ์การเขียนที่กระจัดกระจาย
.nesting { color: hotpink; } .nesting > .is { color: rebeccapurple; } .nesting > .is > .awesome { color: deeppink; }
หลังจากซ้อนตัวเลือกแล้ว คุณจะดำเนินการต่อได้และกฎรูปแบบที่เกี่ยวข้องจะจัดกลุ่มไว้ภายในได้
.nesting { color: hotpink; > .is { color: rebeccapurple; > .awesome { color: deeppink; } } }
การฝังจะช่วยนักพัฒนาซอฟต์แวร์โดยการลดความจำเป็นในการสร้างตัวเลือกซ้ำขณะที่ค้นหากฎรูปแบบสำหรับองค์ประกอบที่เกี่ยวข้องร่วมกันด้วย นอกจากนี้ยังช่วยให้สไตล์ต่างๆ ตรงกับ
HTML ที่กำหนดเป้าหมายอีกด้วย หากมีการนำคอมโพเนนต์ .nesting
ในตัวอย่างก่อนหน้าออกจากโปรเจ็กต์ คุณก็ลบทั้งกลุ่มแทนที่จะค้นหาไฟล์สำหรับอินสแตนซ์ตัวเลือกที่เกี่ยวข้องได้
การซ้อนกันสามารถช่วยในเรื่องต่อไปนี้ - องค์กร - การลดขนาดไฟล์ - การเปลี่ยนโครงสร้างภายในโค้ด
การทำ Nest มีให้บริการใน Chrome 112 และยังลองใช้ใน Safari Technical Preview 162 ได้อีกด้วย
การเริ่มต้นใช้งาน 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;
}
}
ทั้ง 2 ตัวอย่างมีฟังก์ชันการทำงานเทียบเท่ากัน และเหตุผลที่คุณมีตัวเลือกจะชัดเจนขึ้นเมื่อมีการสำรวจตัวอย่างขั้นสูงขึ้นในบทความนี้
การเลือกแวดวง
สำหรับตัวอย่างแรกนี้ งานคือการเพิ่มรูปแบบเพื่อจางลงและเบลอเฉพาะวงกลมภายในการสาธิต
เมื่อไม่ได้ซ้อน 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
จะถูกเบลอออกและแทบจะมองไม่เห็นเลย
![ตารางกริดหลากสีของรูปร่างต่างๆ ไม่มีวงกลมอีกต่อไป ซึ่งมีจางๆ อยู่ในเบื้องหลัง](https://developer.chrome.com/static/docs/css-ui/css-nesting/image/the-colorful-grid-shapes-f1beac5a4a5be.png?authuser=6&hl=th)
การเลือกสามเหลี่ยมและสี่เหลี่ยมจัตุรัส
งานนี้ต้องเลือกองค์ประกอบที่ฝังหลายรายการ หรือเรียกอีกอย่างว่าตัวเลือกกลุ่ม
เมื่อไม่มีการซ้อน 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
:
![ตารางกริดหลากสีสันของรูปร่างต่างๆ จะเหลือแต่วงกลมเท่านั้น รูปร่างอื่นๆ แทบจะมองไม่เห็นเลย](https://developer.chrome.com/static/docs/css-ui/css-nesting/image/the-colorful-grid-shapes-5baea09e41652.png?authuser=6&hl=th)
การเลือกสามเหลี่ยมและวงกลมขนาดใหญ่
งานนี้ต้องมีตัวเลือกแบบผสม ซึ่งองค์ประกอบต้องมีทั้ง 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
:
![ตารางกริดหลากสีมองเห็นรูปร่างขนาดเล็กและขนาดกลางเท่านั้น](https://developer.chrome.com/static/docs/css-ui/css-nesting/image/the-colorful-grid-has-sm-5a9e56b5c62b4.png?authuser=6&hl=th)
เคล็ดลับมือโปรเกี่ยวกับตัวเลือกแบบผสมและการซ้อน
สัญลักษณ์ &
คือเพื่อนของคุณซึ่งแสดงให้เห็นอย่างชัดเจนถึงวิธีการผนวกตัวเลือกที่ซ้อนกัน ลองพิจารณาตัวอย่างต่อไปนี้
.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
:
![ตารางกริดหลากสีเปลี่ยนเป็นแบบโมโนโครมและแสดงเฉพาะรูปร่างสีชมพู](https://developer.chrome.com/static/docs/css-ui/css-nesting/image/the-colorful-grid-is-mon-0203fb32e8aea.png?authuser=6&hl=th)
ความแม่นยำและความยืดหยุ่นด้วย &
สมมติว่าคุณต้องการกำหนดเป้าหมาย .demo
ด้วยตัวเลือก :not()
&
จำเป็นสำหรับการดำเนินการดังกล่าว
.demo {
&:not() {
...
}
}
สารประกอบนี้ .demo
และ :not()
เป็น .demo:not()
ซึ่งตรงข้ามกับตัวอย่างก่อนหน้านี้ที่ต้องใช้ .demo :not()
การช่วยเตือนนี้สำคัญมากเมื่อ
ต้องการฝังการโต้ตอบของ :hover
.demo {
&:hover {
/* .demo:hover */
}
:hover {
/* .demo :hover */
}
}
ตัวอย่างการฝังเพิ่มเติม
ข้อกำหนดของ CSS สำหรับการซ้อนมีตัวอย่างเพิ่มเติมมากมาย หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับไวยากรณ์ ผ่านตัวอย่าง เราจะพูดถึงตัวอย่างที่ถูกต้องและไม่ถูกต้องจำนวนมาก
ตัวอย่างเล็กๆ น้อยๆ ต่อไปนี้จะแนะนำฟีเจอร์ซ้อน 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
ด้วย เพื่อแสดงให้เห็นว่าฟีเจอร์การซ้อนอื่นๆ ยังคงทำงานต่อไป
ดูข้อมูลเพิ่มเติมเกี่ยวกับการฝัง @rules
ซ้อนทุกตำแหน่ง
ตัวอย่างทั้งหมดจนถึงตอนนี้ยังคงปรากฏอยู่หรือต่อท้ายบริบทก่อนหน้า คุณสามารถเปลี่ยนหรือจัดเรียงบริบทใหม่ได้ตามต้องการ
.card {
.featured & {
/* .featured .card */
}
}
สัญลักษณ์ &
แสดงถึงการอ้างอิงออบเจ็กต์ตัวเลือก (ไม่ใช่สตริง) และนำไปวางที่ใดก็ได้ในตัวเลือกที่ฝัง โดยสามารถวางหลายครั้งได้
ดังนี้
.card {
.featured & & & {
/* .featured .card .card .card */
}
}
แม้ว่าตัวอย่างนี้จะดูไม่มีประโยชน์นัก แต่ก็มีบางสถานการณ์ที่ความสามารถในการสร้างบริบทตัวเลือกซ้ำจะเป็นประโยชน์
ตัวอย่างการซ้อนที่ไม่ถูกต้อง
มีสถานการณ์ไวยากรณ์ที่ซ้อนกันอยู่ 2-3 แบบที่ไม่ถูกต้องและอาจทำให้คุณประหลาดใจหากคุณได้ซ้อนอยู่ในตัวประมวลผลล่วงหน้า
การซ้อนและการเชื่อมต่อ
แบบแผนการตั้งชื่อคลาส 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 แบบใน &
ซึ่งคงลำดับแบบ Cascade ตามที่ผู้เขียนตั้งใจไว้ สีขององค์ประกอบ .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
ร่วมกัน ทั้งหมดน่าตื่นเต้นมากเลย