CSS has no real namespacing or encapsulation by default — every rule is global, which is exactly why large codebases without discipline eventually accumulate thousands of lines nobody dares delete.
Practices That Actually Help
- A consistent naming convention (BEM or similar) — makes a class’s scope and purpose obvious from its name alone
- Component-scoped files — one CSS file per component, co-located with its markup, so it’s obvious what depends on what
- CSS custom properties for design tokens — colors, spacing, and typography defined once, referenced everywhere, changed in one place
- Avoiding deep selector nesting —
.a .b .c .dis both a specificity trap and a maintenance headache when the markup structure ever changes
Tools That Enforce Discipline
/* CSS Modules: class names are scoped to the file automatically at build time,
eliminating the "did I accidentally reuse this class name elsewhere" problem */
.card {
padding: 1rem;
}
/* compiles to something like .Card_card__a3f9x, guaranteed unique */
Whether via CSS Modules, Shadow DOM, or CSS-in-JS, the underlying goal is the same: give CSS the encapsulation it doesn’t have natively, so a change in one component’s styles can’t silently break an unrelated one elsewhere in a large codebase.