เมื่อต้องเจอการแก้ไข CSS หลายคนอาจจะเคยพบเจอ !important ทุกที่มาแล้ว เพราะไม่รู้จะแก้ปัญหายังไง เขียน CSS เพิ่มเข้าไปแล้วหน้าตามันก็ไม่เปลี่ยนสักที การเขียน CSS แบบเก่ามันอ้างอิงจากการไล่อ่าน Selector ที่ถูกโหลดเข้ามาต่อกันเรื่อยๆ แล้วปัญหามันจะเริ่มเกิดเมื่อไฟล์ CSS มันยาวมากเกินไปจนหาที่แก้ไม่ถูก สุดท้ายก็จิ้มเอาตรง Inspect ที่บราวเวอร์แล้วก็ซัด !important ลงไปเลย
หากใครกำลังจะรื้อระบบวางโครงสร้าง CSS ใหม่ หรือกำลังทำ Design System อยู่ก็อยากจะแนะนำให้เอา @layer ของ CSS มาใช้ เพื่อความเป็นระเบียบเรียบร้อยเพิ่มยิ่งขึ้นของการเขียน
สมมุติว่าเราตกลงกันในทีมจะวางโครงสร้างไฟล์ CSS แบบนี้
- Setting ใช้สำหรับพวกจัดการค่า default ของ css ที่ต่างกันในแต่ละ User Agent
- Framework ถ้าเราเริ่มสร้าง framework ต่างๆ เอาเข้ามาใส่ตรงนี้ พวกการจัดการ layout การแสดงผลโครงสร้างใหญ่ๆ
- Design System เอาไว้สำหรับการสั่งงานระบบ Atomic UI ที่กำหนดใน design system ของเราหรืออื่นๆ
- Theme ใช้สำหรับ Override และเพิ่มเติม utilities อื่นๆ หรือเราแก้ธีมใหม่ให้ลูกค้าโดยใช้โครงสร้างพื้นฐานจากชุด Framework และ Design System เดิม
เราเอามาเขียนเป็น Layer แบบนี้
@layer settings, framework, design-system, theme;
โครงสร้างจะถูกอ่านแบบ override กันไปเรื่อยๆ โดยที่ theme จะสำคัญที่สุด

ตัวอย่าง หากเราจะเขียนโครงสร้างแยกแล้วนำแต่ละส่วนมาใช้งาน ขอยกตัวอย่าง button สักอัน
<button>Primary Button</button>
โครงสร้าง CSS ที่เขียนได้ประมาณนี้
@layer settings, framework, design-system, theme;
@layer settings {
*,
*::before,
*::after {
box-sizing: border-box;
}
* {
margin: 0;
}
body {
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
img,
picture,
video,
canvas,
svg {
display: block;
max-width: 100%;
}
input,
button,
textarea,
select {
font: inherit;
}
p,
h1,
h2,
h3,
h4,
h5,
h6 {
overflow-wrap: break-word;
}
button {
border: none;
}
}
@layer framework {
:root {
--primary-btn-txt: hsla(0 0% 20% / 1);
--primary-btn-bg: hsla(0 0% 80% / 1);
--btn-rsdius: 0.5em;
--btn-space: 0.5em 1em;
}
body {
font-family: "Roboto", sans-serif;
}
button {
padding: var(--btn-space);
border-radius: var(--btn-rsdius);
}
}
@layer design-system {
:root {
--primary-btn-txt: hsla(50 82% 57% / 1);
--primary-btn-bg: hsla(247 86% 55% / 1);
--btn-rsdius: 0.75em;
--btn-space: 0.5em 1.2em;
}
button {
color: var(--primary-btn-txt);
background-color: var(--primary-btn-bg);
border-radius: var(--btn-rsdius);
}
}
@layer theme {
:root {
--primary-btn-txt: hsla(0 0% 100% / 1);
--primary-btn-bg: hsla(265 82% 57%/ 1);
--btn-rsdius: 40em;
}
button {
color: var(--primary-btn-txt);
background-color: var(--primary-btn-bg);
border-radius: var(--btn-rsdius);
text-transform: uppercase;
}
}
ตรงที่เป็น Layer settings นั้นเอาไว้สั่งงาน reset ค่าต่างๆ ให้แต่ละ user agent เข้าใจตรงกัน การแสดงผลจริงๆ จะเริ่มตั้งแต่ framwork ไปยัง design-system แล้วไปยัง theme

หากเราจะเรียกใช้ไฟล์ style.css ในงานแล้วเรามี css ไฟล์อื่นๆ แยกอยู่เราก็สามรถดึงเข้ามารวมกันแล้วสั่งให้มันทำ layer
เราใช้ @import ไฟล์เข้ามาสั่ง @layer ให้มันตามโครงสร้างที่วางเอาไว้ ก็สามารถสั่งต่อท้ายไฟล์ที่ import เข้ามาได้เลย เช่น
@import reset.css layer(settings);
@import main-layout.css layer(framework);
@import design.css layer(design-system);
@import typo.css layer(design-system);
@import client.css layer(theme);
แล้วในฟล์ style.css หากเราเขียน CSS ลงไปโดยไม่ @layer ให้มัน มันจะ override ทุกอย่างที่กล่าวมา แล้วเราก็จะจัดหนักกับ !important ให้มันเหมือนเดิม ผ่าง!
มีความสุขกับการใช้ชีวิตครับ
อ่านเพิ่มเติม
CSS Cascading and Inheritance Level 5
Leave a Reply