เมื่อต้องเจอการแก้ไข 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