CSS Methodologies: BEM, CSS-in-JS & Tailwind
18 min read
BEMCSS ModulesCSS-in-JSTailwind CSSCSS NestingShadow DOM::part()Atomic CSS
Organizing CSS at Scale
As projects grow, CSS becomes unmanageable without a clear methodology. Here are the major approaches:
Methodology Comparison
| Approach | Scoping | Bundle Size | DX | Best For |
|---|---|---|---|---|
| BEM | Convention-based | Can grow large | Clear naming | Traditional websites |
| CSS Modules | Build-tool scoped | Moderate | Import as object | React/Vue apps |
| CSS-in-JS | Runtime scoped | Larger (JS overhead) | Co-located with components | Dynamic styling needs |
| Tailwind CSS | Utility classes | Small (purged) | Fast prototyping | Rapid development |
| Atomic CSS | Single-purpose classes | Very small | Steep learning curve | High-traffic sites |
BEM (Block Element Modifier)
A naming convention that makes CSS relationships explicit:
- Block: The component itself →
.card - Element: A part of the block →
.card__title(double underscore) - Modifier: A variation →
.card--featured(double dash)
CSS Nesting (Native)
Modern browsers now support native CSS nesting, eliminating the need for preprocessors just for nesting:
.card {
padding: 1rem;
&__title { font-weight: bold; }
&--featured { border: 2px solid var(--primary); }
&:hover { transform: translateY(-2px); }
@media (width >= 768px) { padding: 2rem; }
}Tailwind CSS Philosophy
Utility-first: compose designs directly in HTML using small, single-purpose classes. Benefits:
- No naming fatigue — classes describe what they do
- Dead code elimination (tree shaking) produces tiny CSS bundles
- No specificity conflicts — all utilities have equal specificity
- Responsive and state variants built-in:
md:flex hover:bg-blue-500
Shadow DOM Styling
| Selector | Purpose |
|---|---|
::part(name) | Style exposed parts of a shadow DOM |
::slotted(selector) | Style slotted (projected) content |
:host | Style the shadow DOM host element |
:host-context(.dark) | Style based on ancestor context |