ฟีเจอร์หนึ่งในเครื่องมือเตรียม CSS ที่เราชื่นชอบตอนนี้ได้รวมอยู่ในภาษาแล้ว ซึ่งก็คือกฎสไตล์ที่ฝังอยู่
ก่อนที่จะฝัง คุณต้องประกาศตัวเลือกทุกรายการอย่างชัดเจนแยกจากกัน ซึ่งส่งผลให้มีการใช้ซ้ำ ไฟล์สไตล์ชีตจำนวนมาก และประสบการณ์การเขียนที่กระจัดกระจาย
.nesting { color: hotpink; } .nesting > .is { color: rebeccapurple; } .nesting > .is > .awesome { color: deeppink; }
หลังจากการฝังแล้ว คุณจะใช้ตัวเลือกต่อและจัดกลุ่มกฎสไตล์ที่เกี่ยวข้องไว้ด้วยกันได้
.nesting { color: hotpink; > .is { color: rebeccapurple; > .awesome { color: deeppink; } } }
การฝังช่วยให้นักพัฒนาซอฟต์แวร์ไม่ต้องใช้ตัวเลือกซ้ำๆ และวางกฎสไตล์สำหรับองค์ประกอบที่เกี่ยวข้องไว้ด้วยกัน และยังช่วยให้สไตล์ตรงกับ HTML ที่กําหนดเป้าหมายได้ด้วย หากคอมโพเนนต์ .nesting
ในตัวอย่างก่อนหน้านี้ถูกนําออกจากโปรเจ็กต์ คุณสามารถลบทั้งกลุ่มแทนการค้นหาอินสแตนซ์ตัวเลือกที่เกี่ยวข้องในไฟล์
การฝังจะช่วยในเรื่องต่อไปนี้ - การจัดระเบียบ - การลดขนาดไฟล์ - การจัดระเบียบใหม่
การจัดกลุ่มใช้ได้ใน Chrome 112 และลองใช้ใน Safari Technical Preview 162 ได้ด้วย
เริ่มต้นใช้งานการฝัง CSS
ตลอดทั้งโพสต์นี้ เราจะใช้แซนด์บ็อกซ์สาธิตต่อไปนี้เพื่อช่วยให้คุณเห็นภาพตัวเลือกต่างๆ ในสถานะเริ่มต้นนี้ จะไม่มีการเลือกรายการใดไว้และทุกอย่างจะแสดงอยู่ การเลือกรูปทรงและขนาดต่างๆ จะช่วยให้คุณฝึกไวยากรณ์และดูการใช้งานได้
ภายในแซนด์บ็อกซ์มีวงกลม สามเหลี่ยม และสี่เหลี่ยม บางห้องมีขนาดเล็ก กลาง หรือใหญ่ ส่วนอีกกลุ่มเป็นสีน้ำเงิน สีชมพู หรือสีม่วง ทั้งหมดอยู่ภายในองค์ประกอบ .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
จะเบลอและแทบมองไม่เห็น
การเลือกสามเหลี่ยมและสี่เหลี่ยมจัตุรัส
งานนี้ต้องเลือกองค์ประกอบที่ฝังอยู่หลายรายการ หรือที่เรียกว่าตัวเลือกกลุ่ม
หากไม่มีการวางซ้อน 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 สำหรับการฝังมีตัวอย่างเพิ่มเติมมากมาย หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับไวยากรณ์ผ่านตัวอย่าง เรามีตัวอย่างที่ถูกต้องและไม่ถูกต้องมากมาย
ตัวอย่างต่อไปนี้จะแนะนำฟีเจอร์การฝัง CSS โดยย่อ เพื่อช่วยให้คุณเข้าใจความสามารถที่หลากหลายของฟีเจอร์นี้
การฝัง @media
การย้ายไปยังส่วนอื่นของสไตลชีตเพื่อค้นหาเงื่อนไขของ Media Query ที่แก้ไขตัวเลือกและสไตล์ของตัวเลือกนั้นอาจทำให้เสียสมาธิ ปัญหาดังกล่าวจะหมดไปเมื่อคุณฝังเงื่อนไขไว้ในบริบทได้โดยตรง
หากข้อความค้นหาสื่อที่ฝังอยู่แก้ไขเฉพาะสไตล์สำหรับบริบทตัวเลือกปัจจุบัน คุณจะใช้ไวยากรณ์แบบย่อได้เพื่อความสะดวก
.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 */
}
}
แม้ว่าตัวอย่างนี้อาจดูไร้ประโยชน์ แต่ก็มีบางสถานการณ์ที่การทําซ้ำบริบทตัวเลือกจะมีประโยชน์
ตัวอย่างการซ้อนที่ไม่ถูกต้อง
รูปแบบนิพจน์ซ้อนกันบางรูปแบบไม่ถูกต้องและอาจทำให้คุณประหลาดใจหากคุณวางซ้อนในโปรแกรมประมวลผลข้อมูลล่วงหน้า
การฝังและการต่อเชื่อม
รูปแบบการตั้งชื่อคลาส 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 มีเพียงเวอร์ชัน 1 เท่านั้น เวอร์ชัน 2 จะเพิ่มรูปแบบคำสั่งที่อ่านง่ายขึ้นและอาจลดกฎที่ต้องจำ ผู้ใช้จำนวนมากต้องการให้การแยกวิเคราะห์การฝังไม่จํากัดหรือมีช่วงเวลาที่ยุ่งยาก
การฝังเป็นการเพิ่มประสิทธิภาพที่สำคัญมากสำหรับภาษา CSS ซึ่งส่งผลต่อผู้เขียนเกือบทุกแง่มุมของสถาปัตยกรรม CSS ผลกระทบที่ยิ่งใหญ่นี้ต้องได้รับการสำรวจและทำความเข้าใจอย่างละเอียดก่อนที่จะระบุเวอร์ชัน 2 ได้อย่างมีประสิทธิภาพ
สุดท้ายนี้ นี่คือตัวอย่างที่ใช้ @scope
, การฝัง และ @layer
ร่วมกัน ทุกอย่างน่าตื่นเต้นมาก