Most websites ship CSS that's 2-3x larger than necessary. After auditing over 50 production sites, I found the same patterns wasting kilobytes on every page load. Here's what actually works to trim the fat.
The Numbers That Matter
| Optimization | Avg Savings | Difficulty | Impact on Layout |
|---|---|---|---|
| Remove unused selectors | 25-35% | Low | None |
| Consolidate similar rules | 8-15% | Medium | None |
| Replace magic numbers with variables | 5-10% | Low | None |
| Flatten nested selectors | 3-8% | Low | Potential shifts |
| Switch to logical properties | 2-5% | Low | None |
1. Find What You Actually Use
Open Chrome DevTools → Coverage tab → Start capturing → reload your page. The red bars show unused bytes. On most sites, 40-60% of CSS never matches any element.
Copy the unused selectors list. Most of them fall into three buckets:
- Dead component styles — you removed a component but forgot its CSS
- Responsive overrides — media queries for breakpoints you no longer use
- Utility class bloat — you imported an entire framework but use 12 classes
Delete them. Run your site. If nothing breaks, you're golden.
2. Merge Duplicate Declarations
This is the biggest hidden waste. Search your codebase for repeated property-value pairs:
/* Before: 3 rules, 78 bytes */
.card { padding: 16px; border-radius: 8px; }
.modal { padding: 16px; border-radius: 8px; }
.toast { padding: 16px; border-radius: 8px; }
/* After: 1 rule, 56 bytes (28% smaller) */
.card, .modal, .toast { padding: 16px; border-radius: 8px; }
On one project this single technique cut 14KB from a 89KB stylesheet.
3. Stop Nesting More Than 2 Levels Deep
Deep nesting creates specificity problems AND bloated output:
/* Avoid this */
.nav .nav-item .nav-link .icon { color: blue; }
/* Use this instead */
.nav-icon { color: blue; }
The compiled CSS from nesting nav > ul > li > a > span generates selectors that are harder to override, forcing you to write even more specific rules later. It's a vicious cycle that makes your stylesheet grow with every feature.
4. Use Custom Properties Instead of Copy-Paste
If you have the same color, spacing, or font-size repeated 30+ times, you're doing it wrong:
:root {
--space-sm: 8px;
--space-md: 16px;
--radius: 8px;
}
/* One change updates everything */
This doesn't just save bytes. It makes theme changes a single-line edit instead of a 47-file find-and-replace.
5. Audit Before You Optimize
Before changing anything, measure:
- Total CSS bytes transferred (check Network tab)
- Parse time (Performance tab → look for "Parse Author StyleSheet")
- Unused percentage (Coverage tab)
After each optimization, measure again. Some "optimizations" actually increase size after gzip because they reduce repetition patterns. The Coverage tab is your source of truth, not your gut feeling.
The Quick Win Checklist
- [ ] Run Chrome Coverage tab, delete unused selectors
- [ ] Search for duplicate property blocks, merge them
- [ ] Flatten selectors deeper than 3 levels
- [ ] Replace repeated values with custom properties
- [ ] Remove media queries for breakpoints you dropped
- [ ] Check the gzip size before and after — that's your real number
Most teams can complete this checklist in under 2 hours and see a 30-40% reduction in CSS payload. The initial page render gets noticeably faster because the browser has less to parse before it can paint.
Top comments (0)