เปรียบเทียบ BEM กับแนวทาง utility-first ข้อดีข้อเสียที่แท้จริงในทีม และจัดโครงสร้างไฟล์ของคุณด้วย cascade layers
เปิดบทเรียนนี้ใน KodokonCSS ไม่พังในระดับของ component มันพังในระดับของโปรเจกต์: specificity ที่ไต่สูงขึ้นเพียงเพื่อ "เอาชนะ" กฎที่มีอยู่แล้ว, ความกลัวที่จะลบโค้ดที่คุณไม่รู้ขอบเขตการเข้าถึง, สไตล์ที่รั่วจากหน้าจอหนึ่งไปอีกหน้าจอ สถาปัตยกรรม CSS ก่อนอื่นเลยคือ กลยุทธ์สำหรับจัดการ specificity และ scope สองสำนักที่ครองตลาด BEM กับ utility-first ตอบปัญหาเดียวกันด้วยเส้นทางที่ตรงกันข้าม
BEM (Block, Element, Modifier) ตั้งชื่อทุกโหนดที่ถูกจัดสไตล์: .card (block ที่อยู่ได้เอง), .card__title (element ที่เป็นของ block), .card--featured (variant ของ block) แบบแผนนี้รับประกัน specificity แบบ แบนราบ คลาสเดียวทุกที่ ไม่มี descendant selector เลย จึงไม่มีความขัดแย้งเรื่องลำดับ และชื่อที่บอกความเป็นเจ้าของ ต้นทุนคือ: ต้องคิดชื่อตลอดเวลา และการซ้ำซ้อนของค่าอย่างแท้จริง (margin-top: 16px เดียวกันถูกเขียนซ้ำในยี่สิบ block)
.card {
padding: 16px;
border-radius: 8px;
}
.card__title {
font-size: 1.25rem;
}
.card__title--muted {
color: #6b7280;
}
.card--featured {
border: 2px solid var(--brand);
}แนวทาง utility-first (โดยมี Tailwind เป็นตัวแทนที่ครองตลาด) พลิกตรรกะ: ไม่มีชื่ออีกต่อไป มีแค่คลาสอะตอมที่รับผิดชอบอย่างเดียวประกอบเข้าด้วยกันใน HTML ประโยชน์วัดได้จริง: ไม่ต้องออกแรงตั้งชื่อ, สไตล์อยู่ร่วมกับ markup (การลบ component ก็ลบสไตล์ของมันไปด้วย) และ CSS bundle สุดท้ายที่มีขนาดเกือบคงที่เพราะ utility ถูกใช้ร่วมกัน ข้อแลกเปลี่ยนก็มี: HTML ที่ยืดยาว, การซ้ำซ้อนที่ย้ายไปอยู่ที่ markup ซึ่งต้องมี component layer (React, Vue, partials) เพื่อให้คง DRY ไว้ และเส้นโค้งการเรียนรู้สำหรับคำศัพท์
<article class="flex flex-col gap-4 rounded-lg
border border-gray-200 p-4 shadow-sm">
<h2 class="text-lg font-semibold">Invoice</h2>
<p class="text-sm text-gray-600">
Paid on March 12
</p>
</article>แนวทางเหล่านี้ไม่ได้ใช้ทดแทนกันไม่ได้: ทีมที่โตเต็มที่หลายทีมผสมมันเข้าด้วยกัน utility สำหรับ layout และ spacing, คลาส component (BEM หรือ CSS Modules) สำหรับรูปแบบและสถานะที่ซับซ้อน ส่วนเรื่องการจัดระเบียบไฟล์ หลักการ ITCSS ยังคงเป็นมาตรฐานอ้างอิง: เรียงลำดับจากทั่วไปไปเฉพาะเจาะจง (reset, base elements, components, utilities) กฎ @layer แบบเนทีฟเปลี่ยนแบบแผนนี้ให้เป็นการรับประกันในระดับเอนจิน: ลำดับความสำคัญระหว่างเลเยอร์ เป็นอิสระจาก specificity ของ selector ที่มันบรรจุอยู่
@layer reset, base, components, utilities;
@layer base {
h2 { font-size: 1.5rem; }
}
@layer components {
#hero .btn { padding: 12px 24px; }
}
@layer utilities {
.p-0 { padding: 0; }
}.card__title--muted ส่วน --muted หมายถึงอะไร?card__titlecard__title@layer ต่อ cascade คืออะไร?