ไวยากรณ์ที่แข่งขัน 2 รูปแบบต้องการความช่วยเหลือจากคุณในการพิจารณาว่าควรสนับสนุนข้อความใดที่มีคุณสมบัติตามเกณฑ์
การซ้อน CSS เป็นการเพิ่มไวยากรณ์ตามความสะดวกที่ช่วยให้เพิ่ม CSS ภายในชุดกฎได้ ถ้าคุณเคยใช้ SCSS, Less หรือ Stylus แสดงว่าคุณน่าจะเคยเห็น 2-3 รสชาติต่อไปนี้
.nesting {
color: hotpink;
> .is {
color: rebeccapurple;
> .awesome {
color: deeppink;
}
}
}
ซึ่งหลังจากที่ Preprocessor รวบรวมไปยัง CSS ปกติแล้ว ก็จะเปลี่ยนเป็น CSS ปกติดังนี้
.nesting {
color: hotpink;
}
.nesting > .is {
color: rebeccapurple;
}
.nesting > .is > .awesome {
color: deeppink;
}
เรากำลังพิจารณาเวอร์ชัน CSS อย่างเป็นทางการของไวยากรณ์นี้ และเราต้องการให้มีการแยกส่วนกัน เราต้องการใช้ความช่วยเหลือของชุมชนเพื่อทำลายความสัมพันธ์ ส่วนที่เหลือในโพสต์นี้จะนำเสนอตัวเลือกไวยากรณ์เพื่อให้คุณได้ทำแบบสำรวจในตอนท้าย
ทําไมตัวอย่างการซ้อนกันตามที่แสดงด้านบนจึงเป็นไวยากรณ์สําหรับการซ้อน CSS ไม่ได้
มีสาเหตุ 2-3 ประการที่ทำให้ไม่สามารถใช้ไวยากรณ์ที่ซ้อนกันซึ่งเป็นที่นิยมมากที่สุดได้ ดังนี้
การแยกวิเคราะห์ไม่ชัดเจน
ตัวเลือกที่ฝังอยู่บางตัวอาจมีลักษณะเหมือนพร็อพเพอร์ตี้และตัวประมวลผลล่วงหน้า แก้ไขและจัดการได้ในเวลาบิลด์ เครื่องมือของเบราว์เซอร์ไม่มีโอกาสแบบเดียวกัน ตัวเลือกจึงไม่ควรตีความแบบหลวมๆความขัดแย้งในการแยกวิเคราะห์ของผู้ประมวลผลข้อมูลล่วงหน้า
วิธีการซ้อนของ CSS นั้นไม่ควรละเมิดกระบวนการก่อนการประมวลผลหรือเวิร์กโฟลว์ที่ซ้อนกันของนักพัฒนาแอปที่มีอยู่ การดําเนินการนี้จะก่อให้เกิดการหยุดชะงักและไม่พิจารณา ระบบนิเวศและชุมชนเหล่านั้นกำลังรอ
:is()
การซ้อนพื้นฐานไม่จำเป็นต้องใช้:is()
แต่การซ้อนที่ซับซ้อนกว่านั้นทำได้ ดูตัวอย่างที่ 3 สำหรับข้อมูลเบื้องต้นเกี่ยวกับรายการตัวเลือกและการซ้อน สมมติว่ารายการตัวเลือกอยู่ตรงกลางของตัวเลือกแทนที่จะอยู่ช่วงต้น ในกรณีเหล่านั้น ต้องใช้:is()
เพื่อจัดกลุ่มเครื่องมือเลือกไว้ตรงกลางของตัวเลือกอื่น
ภาพรวมของสิ่งที่เรากำลังเปรียบเทียบ
เราต้องการให้ CSS มีการซ้อนอย่างถูกต้อง และด้วยเหตุนี้ เราจึงรวมชุมชนไว้ด้วย ส่วนต่อไปนี้จะช่วยอธิบายถึงเวอร์ชันที่เป็นไปได้ 3 เวอร์ชันที่เราประเมิน จากนั้นเราจะพูดถึงตัวอย่างการใช้งานเพื่อเปรียบเทียบ และในช่วงท้ายจะมีแบบสำรวจสั้นๆ ที่ถามคุณว่าโดยรวมคุณชอบอะไร
ตัวเลือกที่ 1: @nest
นี่คือไวยากรณ์ที่ระบุในปัจจุบันในการซ้อน CSS 1 วิธีนี้มอบวิธีที่สะดวกในการฝังสไตล์การต่อท้ายด้วยการเริ่มเครื่องมือเลือกแบบซ้อนใหม่ด้วย &
และยังมี @nest
เป็นวิธีวางบริบท &
ที่ใดก็ได้ภายในตัวเลือกใหม่ เช่น เมื่อคุณไม่ได้เพิ่มเฉพาะวัตถุ ตัวเลือกนี้มีความยืดหยุ่นและน้อย แต่ก็ต้องจ่ายค่าจำ @nest
หรือ &
ตามกรณีการใช้งานของคุณ
ตัวเลือกที่ 2: @nest ถูกจำกัด
นี่เป็นอีกทางเลือกหนึ่งที่เข้มงวดกว่า โดยพยายามลดค่าใช้จ่ายที่กล่าวถึงการจำวิธีการซ้อน 2 วิธีการ ไวยากรณ์ที่จำกัดนี้อนุญาตให้ซ้อนเกิดขึ้นหลัง @nest
เท่านั้น ดังนั้นจึงไม่มีรูปแบบความสะดวกสบายต่อท้ายเท่านั้น ขจัดความคลุมเครือของทางเลือก สร้างวิธีหนึ่งที่จดจำง่าย แต่มีความเสียสละเพื่อยึดถือตามธรรมเนียม
ตัวเลือกที่ 3: วงเล็บเหลี่ยม
Miriam Suzanne และ Elika Etemad ได้เสนอไวยากรณ์ทางเลือกที่ใช้วงเล็บปีกกาเพิ่มเติมเพื่อหลีกเลี่ยงไม่ให้รูปแบบ 2 ชั้นหรือทำให้สับสนเป็นพิเศษจากข้อเสนอ @nest
วิธีนี้ทำให้ไวยากรณ์มีความชัดเจน โดยใช้อักขระเพิ่มอีก 2 ตัว และไม่มีกฎใหม่ นอกจากนี้ยังช่วยให้สามารถจัดกลุ่มกฎที่ซ้อนกันตามประเภทของการซ้อนที่ต้องการ ซึ่งเป็นวิธีลดความซับซ้อนของตัวเลือกที่ซ้อนกันที่คล้ายกัน
ตัวอย่างที่ 1 - การซ้อนโดยตรง
@ฝัง
.foo {
color: #111;
& .bar {
color: #eee;
}
}
@nest เสมอ
.foo {
color: #111;
@nest & .bar {
color: #eee;
}
}
วงเล็บ
.foo {
color: #111;
{
& .bar {
color: #eee;
}
}
}
CSS ที่เทียบเท่า
.foo {
color: #111;
}
.foo .bar {
color: #eee;
}
ตัวอย่างที่ 2 - การฝังแบบผสม
@ฝัง
.foo {
color: blue;
&.bar {
color: red;
}
}
@nest เสมอ
.foo {
color: blue;
@nest &.bar {
color: red;
}
}
วงเล็บ
.foo {
color: blue;
{
&.bar {
color: red;
}
}
}
CSS ที่เทียบเท่า
.foo {
color: blue;
}
.foo.bar {
color: red;
}
ตัวอย่างที่ 3 - รายการตัวเลือกและการซ้อน
@ฝัง
.foo, .bar {
color: blue;
& + .baz,
&.qux {
color: red;
}
}
@nest เสมอ
.foo, .bar {
color: blue;
@nest & + .baz,
&.qux {
color: red;
}
}
วงเล็บ
.foo, .bar {
color: blue;
{
& + .baz,
&.qux {
color: red;
}
}
}
CSS ที่เทียบเท่า
.foo, .bar {
color: blue;
}
:is(.foo, .bar) + .baz,
:is(.foo, .bar).qux {
color: red;
}
ตัวอย่างที่ 4 - หลายระดับ
@ฝัง
figure {
margin: 0;
& > figcaption {
background: lightgray;
& > p {
font-size: .9rem;
}
}
}
@nest เสมอ
figure {
margin: 0;
@nest & > figcaption {
background: lightgray;
@nest & > p {
font-size: .9rem;
}
}
}
วงเล็บ
figure {
margin: 0;
{
& > figcaption {
background: lightgray;
{
& > p {
font-size: .9rem;
}
}
}
}
}
CSS ที่เทียบเท่า
figure {
margin: 0;
}
figure > figcaption {
background: hsl(0 0% 0% / 50%);
}
figure > figcaption > p {
font-size: .9rem;
}
ตัวอย่างที่ 5 - การซ้อนผู้ปกครองหรือการเปลี่ยนเรื่อง
@ฝัง
.foo {
color: red;
@nest .parent & {
color: blue;
}
}
@nest เสมอ
.foo {
color: red;
@nest .parent & {
color: blue;
}
}
วงเล็บ
.foo {
color: red;
{
.parent & {
color: blue;
}
}
}
CSS ที่เทียบเท่า
.foo {
color: red;
}
.parent .foo {
color: blue;
}
ตัวอย่างที่ 6 - การผสมโดยตรงและการซ้อนระดับบนสุด
@ฝัง
.foo {
color: blue;
@nest .bar & {
color: red;
&.baz {
color: green;
}
}
}
@nest เสมอ
.foo {
color: blue;
@nest .bar & {
color: red;
@nest &.baz {
color: green;
}
}
}
วงเล็บ
.foo {
color: blue;
{
.bar & {
color: red;
{
&.baz {
color: green;
}
}
}
}
}
CSS ที่เทียบเท่า
.foo {
color: blue;
}
.bar .foo {
color: red;
}
.bar .foo.baz {
color: green;
}
ตัวอย่างที่ 7 - การซ้อนคิวรี่สื่อ
@ฝัง
.foo {
display: grid;
@media (width => 30em) {
grid-auto-flow: column;
}
}
หรือชัดเจน / ขยาย
.foo {
display: grid;
@media (width => 30em) {
& {
grid-auto-flow: column;
}
}
}
@nest เสมอ (ชัดเจนเสมอ)
.foo {
display: grid;
@media (width => 30em) {
@nest & {
grid-auto-flow: column;
}
}
}
วงเล็บ
.foo {
display: grid;
@media (width => 30em) {
grid-auto-flow: column;
}
}
หรือชัดเจน / ขยาย
.foo {
display: grid;
@media (width => 30em) {
& {
grid-auto-flow: column;
}
}
}
CSS ที่เทียบเท่า
.foo {
display: grid;
}
@media (width => 30em) {
.foo {
grid-auto-flow: column;
}
}
ตัวอย่างที่ 8 - กลุ่มที่ซ้อนกัน
@ฝัง
fieldset {
border-radius: 10px;
&:focus-within {
border-color: hotpink;
}
& > legend {
font-size: .9em;
}
& > div {
& + div {
margin-block-start: 2ch;
}
& > label {
line-height: 1.5;
}
}
}
@nest เสมอ
fieldset {
border-radius: 10px;
@nest &:focus-within {
border-color: hotpink;
}
@nest & > legend {
font-size: .9em;
}
@nest & > div {
@nest & + div {
margin-block-start: 2ch;
}
@nest & > label {
line-height: 1.5;
}
}
}
วงเล็บ
fieldset {
border-radius: 10px;
{
&:focus-within {
border-color: hotpink;
}
}
> {
legend {
font-size: .9em;
}
div {
+ div {
margin-block-start: 2ch;
}
> label {
line-height: 1.5;
}
}}
}
}
CSS ที่เทียบเท่า
fieldset {
border-radius: 10px;
}
fieldset:focus-within {
border-color: hotpink;
}
fieldset > legend {
font-size: .9em;
}
fieldset > div + div {
margin-block-start: 2ch;
}
fieldset > div > label {
line-height: 1.5;
}
ตัวอย่างที่ 9 - กลุ่มที่ซ้อนกันแบบซ้อน "อ่างล้างจาน"
@ฝัง
dialog {
border: none;
&::backdrop {
backdrop-filter: blur(25px);
}
& > form {
display: grid;
& > :is(header, footer) {
align-items: flex-start;
}
}
@nest html:has(&[open]) {
overflow: hidden;
}
}
@nest เสมอ
dialog {
border: none;
@nest &::backdrop {
backdrop-filter: blur(25px);
}
@nest & > form {
display: grid;
@nest & > :is(header, footer) {
align-items: flex-start;
}
}
@nest html:has(&[open]) {
overflow: hidden;
}
}
วงเล็บ
dialog {
border: none;
{
&::backdrop {
backdrop-filter: blur(25px);
}
& > form {
display: grid;
{
& > :is(header, footer) {
align-items: flex-start;
}
}
}
}
{
html:has(&[open]) {
overflow: hidden;
}
}
}
CSS ที่เทียบเท่า
dialog {
border: none;
}
dialog::backdrop {
backdrop-filter: blur(25px);
}
dialog > form {
display: grid;
}
dialog > form > :is(header, footer) {
align-items: flex-start;
}
html:has(dialog[open]) {
overflow: hidden;
}
เวลาในการโหวต
หวังว่าคุณจะรู้สึกว่าเป็นการเปรียบเทียบที่ยุติธรรมและตัวอย่างตัวเลือกไวยากรณ์ที่เราประเมิน โปรดอ่านข้อกำหนดเหล่านี้อย่างละเอียดและแจ้งให้เราทราบ ว่าคุณต้องการอะไรทางด้านล่าง ขอขอบคุณที่ช่วยเราพัฒนาการฝัง CSS ในไวยากรณ์ที่เรา ทุกคนรู้จักและชื่นชอบ!