CSS Best Practices
Habits that keep a growing stylesheet maintainable — naming, organization, and knowing when to simplify.
អាន 2 នាទី
Writing a CSS rule that works is easy. Writing CSS that's still easy to change six months and several contributors later is the real skill. A few habits make the difference.
Prefer classes over IDs and deep nesting
/* Fragile: high specificity, hard to override later */
#main #sidebar .widget-list li.item { color: black; }
/* Better: flat, low specificity, reusable */
.widget-item { color: black; }Flat, class-based selectors keep specificity low and predictable, which means future overrides don't need to escalate into a specificity war (see the previous lesson). As a rule of thumb, if a selector needs more than two or three parts chained together, it's usually a sign the element deserves its own class instead.
Adopt a naming convention
.card { }
.card__title { }
.card__title--large { }
.card--featured { }This is BEM (Block, Element, Modifier) naming: .card__title is a part of the card, .card--featured is a variant of the card. You don't have to use BEM specifically, but some consistent, predictable naming convention prevents class names like .title2 or .blue-box-fix from creeping in under deadline pressure — names that mean nothing to the next person reading them.
Group related declarations logically
.card {
/* Positioning */
position: relative;
/* Box model */
padding: 16px;
border-radius: 8px;
/* Typography */
font-size: 1rem;
line-height: 1.5;
/* Visual */
background: white;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
/* Motion */
transition: box-shadow 0.2s ease;
}A consistent internal order (position, box model, typography, visual, motion — or any order your team agrees on) makes a long declaration block scannable at a glance, rather than a random-looking pile of properties.
Don't fight the cascade — use it
:root {
--text-color: #111827;
}
body {
color: var(--text-color);
font-family: system-ui, sans-serif;
}Set sensible defaults high up (on body or :root) and let them inherit down, rather than repeating color and font-family on every single component. Override only where a component genuinely needs to differ — that's the cascade doing its job, not a problem to route around.
Extract repeated values into custom properties
:root {
--space-sm: 8px;
--space-md: 16px;
--space-lg: 32px;
--radius: 8px;
}A small, shared scale of spacing, radius, and color values (via custom properties) keeps a design visually consistent and makes a global tweak — like widening every card's radius — a one-line change instead of a find-and-replace across the whole codebase.
Delete before you add
The single highest-leverage CSS best practice isn't a technique at all: before adding a new override to fix something, check whether an existing rule is actually necessary, or whether removing it (or simplifying an overly specific selector) fixes the problem more directly. Stylesheets tend to only grow over a project's life — periodically pruning unused or redundant rules is what keeps one from turning into an unreadable pile no one wants to touch.