CSS at scale is hard. Global namespace; specificity battles; the dreaded !important. Several methodologies attempt to make CSS manageable at scale. Each has trade-offs.
This page covers the major patterns and the modern consensus.
Without methodology, CSS at scale produces:
.button defined in 5 files).modal .button.primary vs. .button.primary.large)The methodologies try to prevent this.
A naming convention:
.card { } /* Block */
.card__title { } /* Element */
.card__title--large { } /* Modifier */
Names encode hierarchy. Global namespace; conflicts are visible in names.
<div class="card card--featured">
<h2 class="card__title card__title--large">Title</h2>
<div class="card__body">Body</div>
</div>
Pros:
Cons:
Was popular 2015-2020; less common now.
Locally-scoped class names. The build tool transforms:
/* Card.module.css */
.title { color: blue; }
import styles from './Card.module.css';
<h2 className={styles.title}>Title</h2>
The build outputs unique class names per file; no global conflicts.
Pros:
Cons:
Common in React projects.
Styles in JS:
// styled-components
const Button = styled.button`
background: ${props => props.primary ? 'blue' : 'gray'};
color: white;
padding: 8px 16px;
`;
// emotion
const buttonStyle = css`
background: blue;
`;
Pros:
Cons:
CSS-in-JS dominated 2018-2022 in React; some teams are moving away due to performance.
Single-purpose utility classes:
<button class="bg-blue-500 hover:bg-blue-700 text-white px-4 py-2 rounded">
Click me
</button>
Each class does one thing. No custom CSS for this button.
Pros:
Cons:
Tailwind is the dominant atomic CSS implementation. Has become the modern default for many React/Vue projects.
Just write CSS. No conventions; rely on developer discipline.
Pros: simple; no tooling. Cons: doesn't scale; conflicts pile up.
For tiny projects, fine. Beyond a few hundred lines, methodology helps.
For most new React/Vue/Svelte projects (2024+):
CSS-in-JS adoption has slowed for new projects. The performance issues and the complexity haven't justified the dynamic-styling benefits for many teams.
For design systems or component libraries, Web Components with shadow DOM provide their own isolation; can use plain CSS.
If you need !important, you're doing something wrong. Restructure or use a methodology that prevents specificity conflicts.
normalize.css or similar. Provides consistent baseline across browsers.
CSS Grid, Flexbox, custom properties (CSS variables), container queries. Modern CSS is much more capable than 2010 CSS.
CSS is render-blocking. Smaller is better. Don't ship 500 KB of CSS.
CSS variables + media query is the modern approach:
:root {
--bg: white;
--text: black;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: black;
--text: white;
}
}
body {
background: var(--bg);
color: var(--text);
}