比较 BEM 与 utility-first 方案、它们在团队中真实的取舍,并用层叠层来组织你的文件。
在 Kodokon 中打开本课CSS 不是在一个组件的规模上崩溃,而是在一个项目的规模上崩溃:为了"战胜"某条既有规则而不断抬高特异性、不敢删除那些你不知道其影响范围的代码、样式从一个屏幕泄漏到另一个屏幕。CSS 架构首先是一套管理特异性与作用域的策略。两大主流学派——BEM 与 utility-first——用相反的路径回答同一个问题。
BEM(Block、Element、Modifier)为每一个带样式的节点命名:.card(一个独立的块)、.card__title(属于该块的一个元素)、.card--featured(该块的一个变体)。这套约定保证了扁平的特异性——处处都是单个类,从不使用后代选择器——因此不会有排序冲突,而且名称本身就记录了归属。代价是:不断地发明名称,以及真实存在的值重复(同一个 margin-top: 16px 在二十个块里被重写)。
.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 中组合起来的单一职责原子类。收益是可衡量的:零命名成本、样式与标记就近共处(删掉组件就删掉了它的样式),以及一个体积几乎恒定的最终 CSS 包,因为这些工具类是共享的。取舍也存在:冗长的 HTML、被转移到标记里的重复(这需要一个组件层——React、Vue、局部模板——来保持 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>这些方案并不互斥:许多成熟的团队会把它们结合起来——用工具类做布局和间距,用组件类(BEM 或 CSS Modules)处理复杂的模式和状态。至于文件组织,ITCSS 原则依旧是参照标准:从通用到具体地排序(重置、基础元素、组件、工具类)。原生的 @layer 规则把这套约定变成引擎级别的保证:层与层之间的优先级独立于它们所含选择器的特异性。
@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__title 元素的一个变体card__title 的一个子元素@layer 对层叠的主要贡献是什么?