CSS Architecture & Best Practices
Why CSS architecture matters
On small projects, you can write CSS however you want. But as projects grow — hundreds of components, multiple developers, thousands of lines — unstructured CSS becomes a nightmare. Styles conflict, specificity wars break out, and nobody dares touch shared classes.
Good CSS architecture prevents this.
The global reset
Start every project with a consistent baseline:
CSS
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
-webkit-text-size-adjust: 100%;
}
body {
min-height: 100vh;
line-height: 1.6;
font-family: system-ui, -apple-system, sans-serif;
-webkit-font-smoothing: antialiased;
}
img, picture, video, canvas, svg {
display: block;
max-width: 100%;
}
input, button, textarea, select {
font: inherit;
}This eliminates browser inconsistencies and saves you from debugging why padding doesn't match across browsers.
Naming conventions: BEM
BEM (Block, Element, Modifier) is the most widely used naming convention:
CSS
/* Block */
.card { }
/* Element (part of the block) */
.card__title { }
.card__body { }
.card__footer { }
/* Modifier (variation of block or element) */
.card--featured { }
.card__title--large { }HTML
<div class="card card--featured">
<h2 class="card__title card__title--large">Title</h2>
<p class="card__body">Content</p>
</div>BEM keeps selectors flat (no nesting), avoids specificity issues, and makes relationships clear.
Design tokens with CSS variables
Create a systematic design system:
CSS
:root {
/* Colors */
--color-primary: #2563eb;
--color-primary-dark: #1d4ed8;
--color-success: #22c55e;
--color-danger: #dc2626;
--color-text: #1e293b;
--color-text-muted: #64748b;
--color-bg: #ffffff;
--color-border: #e2e8f0;
/* Typography */
--font-sans: system-ui, -apple-system, sans-serif;
--font-mono: 'JetBrains Mono', monospace;
/* Spacing scale */
--space-1: 0.25rem;
--space-2: 0.5rem;
--space-3: 0.75rem;
--space-4: 1rem;
--space-6: 1.5rem;
--space-8: 2rem;
--space-12: 3rem;
/* Sizing */
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-full: 999px;
--max-width: 1200px;
}Every component references these tokens instead of hardcoding values. Want to change the primary color? One line.
File organization
For larger projects, split CSS into logical files:
Code
styles/
_reset.css /* Global reset */
_tokens.css /* Design tokens (variables) */
_typography.css /* Base text styles */
_layout.css /* Grid, container, page layout */
_components.css /* Buttons, cards, forms, etc. */
_utilities.css /* Helper classes (.hidden, .text-center) */
main.css /* Imports all above */Import order matters — later files can override earlier ones:
CSS
/* main.css */
@import '_reset.css';
@import '_tokens.css';
@import '_typography.css';
@import '_layout.css';
@import '_components.css';
@import '_utilities.css';Utility classes
Small, single-purpose classes for common patterns:
CSS
.flex { display: flex; }
.flex-col { flex-direction: column; }
.items-center { align-items: center; }
.gap-2 { gap: var(--space-2); }
.gap-4 { gap: var(--space-4); }
.text-center { text-align: center; }
.text-muted { color: var(--color-text-muted); }
.hidden { display: none; }
.sr-only {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
}Utility classes are composable — combine them in HTML instead of writing new CSS for every layout variation.
Avoiding common mistakes
1. Over-nesting selectors
CSS
/* Bad — too specific, hard to override */
.page .content .sidebar .widget .title { }
/* Good — flat and predictable */
.widget__title { }2. Using !important
If you need
!important, your architecture has a problem. Fix the specificity issue instead.3. Magic numbers
CSS
/* Bad — what does 47px mean? */
.header { height: 47px; }
/* Good — intentional */
.header { height: var(--header-height, 3rem); }4. Styling by element type in components
CSS
/* Bad — breaks if you change the tag */
.card p { margin-bottom: 1rem; }
/* Good — explicit class */
.card__text { margin-bottom: 1rem; }Performance tips
- Avoid
@importin production — it creates waterfall requests. Use a build tool to bundle CSS. - Remove unused CSS — tools like PurgeCSS scan your HTML and remove unused rules.
- Minimize repaints — avoid animating
width,height,top,left. Usetransformandopacity. - Use
containfor complex components — tells the browser a component's layout is independent:
CSS
.card {
contain: layout style;
}Key takeaway
Good CSS architecture is about consistency and scalability. Use a reset, define design tokens as variables, follow a naming convention (BEM), organize files logically, and create utility classes for common patterns. These practices prevent the "CSS spaghetti" that plagues most projects.