การเรียงซ้อนเลเยอร์จะพร้อมใช้งานในเบราว์เซอร์ของคุณ

การเรียงซ้อนเลเยอร์ (@layer กฎ CSS) จะพร้อมใช้งานใน Chromium 99, Firefox 97 และ Safari 15.4 เบต้า โฆษณาประเภทนี้ช่วยให้ควบคุมไฟล์ CSS ของคุณได้ชัดเจนยิ่งขึ้นเพื่อป้องกันความขัดแย้งของสไตล์ที่เจาะจง ซึ่งมีประโยชน์มากโดยเฉพาะสำหรับโค้ดเบสขนาดใหญ่ ระบบออกแบบ และจัดการรูปแบบของบุคคลที่สามในแอปพลิเคชัน

การวางเลเยอร์ CSS อย่างชัดเจนช่วยป้องกันการลบล้างสไตล์ที่ไม่คาดคิดและส่งเสริมสถาปัตยกรรม CSS ที่ดีขึ้น

ความเฉพาะเจาะจง CSS และ Cascade

ความเฉพาะเจาะจงของ CSS คือวิธีที่ CSS ตัดสินใจเลือกรูปแบบที่จะใช้กับองค์ประกอบ ตัวเลือกรูปแบบต่างๆ ที่คุณใช้จะกำหนดความเฉพาะเจาะจงของกฎสไตล์ใดก็ได้ เช่น องค์ประกอบมีความเฉพาะเจาะจงน้อยกว่าคลาสหรือแอตทริบิวต์ ซึ่งก็มีความเฉพาะเจาะจงน้อยกว่ารหัส นี่คือองค์ประกอบสำคัญของการเรียนรู้ CSS

ผู้ใช้หันมาใช้แบบแผนการตั้งชื่อ CSS เช่น BEM เพื่อป้องกันการลบล้างความเฉพาะเจาะจงโดยไม่ได้ตั้งใจ เมื่อคุณตั้งชื่อคลาสเพียงชื่อเดียว ทุกอย่างจะปรากฏในระนาบที่เฉพาะเจาะจงเดียวกัน อย่างไรก็ตาม ก็อาจไม่สามารถคงไว้ซึ่งสไตล์ที่เป็นระเบียบเช่นนี้ได้ โดยเฉพาะเมื่อต้องทำงานกับโค้ดและระบบการออกแบบของบุคคลที่สาม

ภาพ BEM ของการ์ดที่มีคลาส
ตัวอย่างภาพประกอบการตั้งชื่อ BEM จาก keepinguptodate.com

การเรียงซ้อนเลเยอร์มีจุดประสงค์เพื่อแก้ไขปัญหานี้ โดยได้แนะนำเลเยอร์ใหม่ให้กับการเรียงซ้อนของ CSS เมื่อใช้สไตล์แบบเลเยอร์ การให้ความสำคัญกับเลเยอร์จะเหนือกว่าความจำเพาะของตัวเลือกเสมอ

เช่น ตัวเลือก .post a.link มีความเฉพาะเจาะจงสูงกว่า .card a หากพยายามจัดรูปแบบลิงก์ คุณจะเห็นตัวเลือกที่เจาะจงมากขึ้นภายในการ์ดในโพสต์

เมื่อใช้ @layer คุณจะระบุสไตล์ที่เจาะจงของสไตล์แต่ละรายการได้อย่างชัดเจนยิ่งขึ้น และตรวจสอบว่าสไตล์ของลิงก์การ์ดลบล้างรูปแบบของลิงก์โพสต์ แม้ว่าความเฉพาะเจาะจงอาจต่ำกว่าตัวเลขหาก CSS ทั้งหมดอยู่ในระนาบเดียวกัน เนื่องจากลำดับความสำคัญแบบ Cascade รูปแบบที่มีเลเยอร์จะสร้าง "เครื่องบิน" แบบ Cascade ใหม่

ภาพประกอบจากการสาธิตโปรเจ็กต์เกี่ยวกับการแบ่ง UI

@layer กำลังดำเนินการ

การสาธิตแสดงสีลิงก์พร้อมการนำเข้า
ดูการสาธิตเกี่ยวกับ Codepen

ตัวอย่างนี้แสดงถึงประสิทธิภาพของเลเยอร์การเรียงซ้อนโดยใช้ @layer มีลิงก์ที่แสดงหลายลิงก์ ได้แก่ ลิงก์บางรายการไม่มีชื่อชั้นเรียนเพิ่มเติม ลิงก์ที่มีชั้นเรียน .link และอีกลิงก์หนึ่งมีชั้นเรียน .pink จากนั้น CSS จะเพิ่มเลเยอร์ 3 เลเยอร์ ได้แก่ base, typography และ utilities ดังนี้

@layer base {
  a {
    font-weight: 800;
    color: red; /* ignored */
  }

  .link {
    color: blue; /* ignored */
  }
}

@layer typography {
  a {
    color: green; /* styles *all* links */
  }
}

@layer utilities {
  .pink {
    color: hotpink;  /* styles *all* .pink's */
  }
}

สุดท้ายแล้ว ลิงก์ทั้งหมดจะเป็นสีเขียวหรือสีชมพู เพราะแม้ว่า .link จะมีความเฉพาะเจาะจงระดับตัวเลือกสูงกว่า a แต่มีรูปแบบสีบน a ที่มีลำดับความสำคัญสูงกว่า @layer a { color: green } จะลบล้าง .link { color: blue } เมื่อกฎสีเขียวอยู่ในเลเยอร์หลังกฎสีน้ำเงิน

ลำดับความสำคัญของเลเยอร์เหนือกว่าความจำเพาะขององค์ประกอบ

การจัดระเบียบเลเยอร์

คุณสามารถจัดระเบียบเลเยอร์บนหน้าเว็บโดยตรง ดังที่แสดงด้านบน หรือจัดระเบียบเลเยอร์ที่ด้านบนสุดของไฟล์ก็ได้

ระบบจะเรียงลำดับเลเยอร์ในครั้งแรกที่ชื่อเลเยอร์แต่ละชื่อปรากฏในโค้ด

ซึ่งหมายความว่าหากคุณเพิ่มลิงก์ต่อไปนี้ที่ด้านบนสุดของไฟล์ ลิงก์ทั้งหมดจะปรากฏเป็นสีแดง และลิงก์ที่มีคลาส .link จะปรากฏเป็นสีน้ำเงิน

@layer utilities, typography, base;

เนื่องจากตอนนี้ลำดับเลเยอร์ได้กลับกันแล้ว โดยให้ยูทิลิตีขึ้นเป็นอันดับแรกและลำดับฐานเป็นลำดับสุดท้าย ดังนั้น กฎรูปแบบในเลเยอร์ base จะมีความจำเพาะสูงกว่ากฎของรูปแบบในเลเยอร์แบบอักษรเสมอ โดยจะไม่เป็นลิงก์สีเขียวอีกต่อไป แต่เปลี่ยนให้เป็นสีแดงหรือสีน้ำเงินแทน

ภาพหน้าจอของ Codepen Project
ดูการสาธิตเกี่ยวกับ Codepen

การจัดระเบียบการนำเข้า

การใช้ @layer อีกวิธีหนึ่งคือใช้ไฟล์นำเข้า คุณสามารถดำเนินการนี้ได้โดยตรงเมื่อนำเข้ารูปแบบ โดยใช้ฟังก์ชัน layer() ตามตัวอย่างต่อไปนี้:

/* Base */
@import '../styles/base/normalize.css' layer(base); /* normalize or rest file */
@import '../styles/base/base.css' layer(base); /* body and base styles */
@import '../styles/base/theme.css' layer(theme); /* theme variables */
@import '../styles/base/typography.css' layer(theme); /* theme typography */
@import '../styles/base/utilities.css' layer(utilities); /* base utilities */

/* Layouts */
@import '../styles/components/post.css' layer(layouts); /* post layout */

/* Components */
@import '../styles/components/cards.css' layer(components); /* imports card */
@import '../styles/components/footer.css' layer(components); /* footer component */

ข้อมูลโค้ดด้านบนมี 3 เลเยอร์ ได้แก่ base,layouts และ components ไฟล์การทำให้เป็นมาตรฐาน ธีม และตัวอักษรใน base ด้วยไฟล์ post ใน layouts และ cards และ footer ทั้งใน components เมื่อนำเข้าไฟล์ ระบบจะสร้างอินสแตนซ์เลเยอร์ด้วยฟังก์ชันเลเยอร์ อีกวิธีหนึ่งคือ จัดระเบียบเลเยอร์ที่ด้านบนของไฟล์ โดยประกาศเลเยอร์ก่อนการนำเข้า

@layer base,
       theme,
       layouts,
       components,
       utilities;

ตอนนี้ลำดับที่คุณ@importสไตล์จะไม่สำคัญต่อลำดับเลเยอร์ เพราะระบบกำหนดรูปแบบไว้แล้วที่อินสแตนซ์แรกของชื่อเลเยอร์ นั่นคือเรื่องที่ต้องกังวลน้อยลงอีก 1 เรื่อง คุณยังคงสามารถตั้งค่าไฟล์ที่นำเข้าไปยังเลเยอร์ที่เฉพาะเจาะจงได้ แต่มีการกำหนดลำดับไว้แล้ว

ภาพหน้าจอจาก Codepen Project
สำรวจโปรเจ็กต์ใน Codepen

เลเยอร์และน้ำตก

ลองย้อนกลับไปดูจุดที่มีการใช้เลเยอร์เนื่องจากมีความเกี่ยวข้องกับ Cascade ที่กว้างกว่า:

ภาพเรียงซ้อน

ลำดับความสำคัญมีดังนี้

  • User Agent ปกติ (ลำดับความสำคัญต่ำสุด)
  • ผู้ใช้ภายใน @layer
  • ผู้ใช้ภายในปกติ
  • ผู้เขียน @layers
  • ผู้เขียนปกติ
  • ผู้เขียน !important
  • ผู้เขียน @layer !important
  • ผู้ใช้ภายใน !important
  • User Agent !important** (ลำดับความสำคัญสูงสุด)

คุณอาจเห็นว่ามีการกลับสไตล์ @layer !important รูปแบบ แทนที่จะมีความเฉพาะเจาะจงน้อยกว่าสไตล์ที่ไม่ได้กำหนดเลเยอร์ (ปกติ) สไตล์จะมีความสำคัญสูงกว่า เนื่องจากวิธีการทำงานของ !important ใน Cascade คือทำให้การ Cascad ปกติในสไตล์ชีตของคุณกลับคืนความจำเพาะระดับเลเยอร์ตามปกติ (ลำดับความสำคัญ)

เลเยอร์ที่ซ้อนกัน

เลเยอร์ยังสามารถซ้อนอยู่ภายในเลเยอร์อื่นๆ ได้ด้วย ตัวอย่างต่อไปนี้มาจากคำอธิบาย Cascade เลเยอร์ จาก Miriam Suzanne

@layer default {
  p { max-width: 70ch; }
}

@layer framework {
  @layer default {
    p { margin-block: 0.75em; }
  }

  p { margin-bottom: 1em; }
}

ในข้อมูลโค้ดด้านบน คุณสามารถเข้าถึง framework.default โดยใช้ . เป็นเครื่องหมายของเลเยอร์ default ที่ซ้อนอยู่ภายใน framework คุณยังสามารถเขียนสิ่งนี้ในรูปแบบที่สั้นลงอีกได้ด้วย:

@layer framework.default {
  p { margin-block: 0.75em }
}

เลเยอร์ที่ได้และลำดับของเลเยอร์มีดังนี้

  • ค่าเริ่มต้น
  • framework.default
  • ไม่ได้เลเยอร์ framework แล้ว
  • ไม่ได้เลเยอร์

สิ่งที่ต้องระวัง

การเรียงซ้อนเลเยอร์อาจมีประโยชน์หากใช้อย่างถูกต้อง แต่ก็อาจสร้างความสับสนและผลลัพธ์ที่ไม่คาดคิดได้มากขึ้น ให้ระวังสิ่งต่อไปนี้เมื่อทํางานกับเลเยอร์การเรียงซ้อน

กฎข้อที่ 1: อย่าใช้ @layer เพื่อกำหนดขอบเขต

การเรียงซ้อนเลเยอร์ไม่สามารถแก้ไขขอบเขตได้ หากคุณมีไฟล์ CSS ที่มี @layer เช่น card.css และต้องการจัดรูปแบบลิงก์ทั้งหมดภายในการ์ด โปรดอย่าเขียนรูปแบบ เช่น

a {
  …
}

ซึ่งจะทําให้แท็ก a ทั้งหมดในไฟล์ได้รับการลบล้างนี้ คุณยังคงต้องกำหนดขอบเขตรูปแบบให้ถูกต้อง

.card a {
  …
}

กฎข้อที่ 2: เลเยอร์การเรียงซ้อนจะเรียงลำดับอยู่หลัง CSS ที่ไม่ได้เลเยอร์

โปรดทราบว่าไฟล์ CSS ที่มีเลเยอร์จะไม่ลบล้าง CSS ที่ไม่ได้กำหนดเลเยอร์ การตัดสินใจนี้เกิดจากเจตนารมณ์ของการนำเลเยอร์ต่างๆ มาใช้เพื่อให้ทำงานร่วมกับฐานของโค้ดที่มีอยู่ได้อย่างมีประสิทธิภาพมากขึ้น ตัวอย่างเช่น การใช้ไฟล์ reset.css เป็นจุดเริ่มต้นที่ดีและกรณีการใช้งานสำหรับ Cascade เลเยอร์ต่างๆ

กฎที่ 3: !important กลับค่าความเฉพาะเจาะจงแบบ Cascade

แม้ว่ารูปแบบที่มีเลเยอร์จะเฉพาะเจาะจงน้อยกว่ารูปแบบที่ไม่มีเลเยอร์โดยทั่วไป แต่การใช้ !important จะย้อนกลับสิ่งนี้ ในเลเยอร์ การประกาศที่มีกฎ !important จะเจาะจงมากกว่าสไตล์ที่ไม่มีเลเยอร์

ในกรณีดังกล่าว รูปแบบ !important จะกลับค่าความเฉพาะเจาะจง แผนภาพด้านบนแสดงการอ้างอิงนี้: ผู้เขียน @layers มีความสำคัญน้อยกว่าของผู้เขียนปกติ ซึ่งมีความสำคัญน้อยกว่าผู้เขียน !important ซึ่งมีความสำคัญน้อยกว่าผู้เขียน @layer !important

หากคุณมีหลายเลเยอร์ เลเยอร์แรกที่มี !important จะมีลำดับความสำคัญเหนือกว่า !important และเป็นรูปแบบที่เจาะจงที่สุด

กฎที่ 4: ทำความเข้าใจจุดแทรก

เนื่องจากระบบจะสร้างลำดับเลเยอร์ในครั้งแรกที่ชื่อเลเยอร์แต่ละชื่อปรากฏในโค้ดของคุณ หากคุณใส่การประกาศ @layer หลังจากนำเข้าและตั้งค่าของ layer() หรือหลังจากคำสั่ง @layer อื่น คุณจะละเว้นการประกาศดังกล่าวได้ ระบบจะเรียงลำดับการเรียงซ้อนในอินสแตนซ์แรก ซึ่งแตกต่างจากใน CSS ที่กฎสไตล์ที่เริ่มจากด้านล่างของหน้าเว็บจะใช้กับเลเยอร์แบบเรียงซ้อน

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

กฎข้อที่ 5: ตรวจสอบความเฉพาะเจาะจงของคุณ

เมื่อใช้การเรียงซ้อนเลเยอร์ ตัวเลือกที่เจาะจงน้อยกว่า (เช่น a) จะลบล้างตัวเลือกที่เจาะจงมากขึ้น (เช่น .link) หากตัวเลือกที่เจาะจงน้อยกว่าอยู่ในเลเยอร์ที่เจาะจงมากกว่า ลองพิจารณาสิ่งเหล่านี้

a ใน layer(components) จะลบล้าง .pink ใน layer(utilities) หากมีการระบุ @layer utilities, components แม้ว่านี่จะเป็นส่วนที่เจตนาของ API แต่สิ่งนี้อาจทำให้สับสนและน่าหงุดหงิดหากคุณไม่คาดหวัง

ดังนั้นหากคุณเขียนคลาสยูทิลิตี ให้ใส่คลาสเหล่านั้นเป็นเลเยอร์ลำดับที่สูงกว่าคอมโพเนนต์ที่ต้องการใช้จะลบล้างด้วย คุณอาจคิดว่า "ฉันเพิ่งเพิ่มคลาส .pink นี้เพื่อเปลี่ยนสีแต่ตอนนี้ไม่ได้ใช้อยู่"

ดูข้อมูลเพิ่มเติมเกี่ยวกับเลเยอร์การเรียงซ้อน

คุณยังสามารถดูแหล่งข้อมูลเหล่านี้เพื่อเรียนรู้เพิ่มเติมเกี่ยวกับการเรียงซ้อนเลเยอร์: