Compare BEM and the utility-first approach, their real trade-offs in a team, and structure your files with cascade layers.
Open this lesson in KodokonCSS doesn't break at the scale of a component, it breaks at the scale of a project: specificity climbing just to "win" against an existing rule, fear of deleting code whose reach you don't know, styles leaking from one screen to another. A CSS architecture is above all a strategy for managing specificity and scope. The two dominant schools, BEM and utility-first, answer the same problem through opposite paths.
BEM (Block, Element, Modifier) names every styled node: .card (a standalone block), .card__title (an element belonging to the block), .card--featured (a variant of the block). The convention guarantees flat specificity - a single class everywhere, never a descendant selector - so no ordering conflicts, and a name that documents ownership. The cost: constantly inventing names, and genuine duplication of values (the same margin-top: 16px rewritten in twenty blocks).
.card {
padding: 16px;
border-radius: 8px;
}
.card__title {
font-size: 1.25rem;
}
.card__title--muted {
color: #6b7280;
}
.card--featured {
border: 2px solid var(--brand);
}The utility-first approach (Tailwind being its dominant incarnation) flips the logic: no more names, just single-responsibility atomic classes composed in the HTML. The benefits are measurable: zero naming effort, styles colocated with the markup (deleting the component deletes its styles), and a final CSS bundle that stays almost constant in size since the utilities are shared. The trade-offs too: verbose HTML, duplication shifted to the markup that requires a component layer (React, Vue, partials) to stay DRY, and a learning curve for the vocabulary.
<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>These approaches are not mutually exclusive: many mature teams combine them - utilities for layout and spacing, component classes (BEM or CSS Modules) for complex patterns and states. As for file organization, the ITCSS principle remains the reference: order from generic to specific (reset, base elements, components, utilities). The native @layer rule turns this convention into an engine-level guarantee: priority between layers is independent of the specificity of the selectors they contain.
@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, what does the --muted segment denote?card__title elementcard__title@layer to the cascade?