Day 17: CSS Architecture: BEM, Reset, DevTools, Performance
✅ Today you will learn
- Why CSS gets messy in real projects
- BEM: Block__Element--Modifier naming
- A project structure: tokens, base, layout, components, utilities
- Debugging with DevTools: computed styles, layout overlays, coverage
- Performance, minification and a review checklist
🏢 In the real world
You join a company and open their style.css: 6,000 lines, selectors like #main div ul li a span.red, 214 uses of !important and nobody dares to delete anything. This is the norm, not the exception. Today you learn the habits that keep CSS clean – the difference between a coder and a professional front-end developer.
Why CSS rots
BEM: names that explain themselves
/* Block = a standalone component */
.card { }
/* Element = a part of the block: block__element */
.card__image { }
.card__title { }
.card__price { }
/* Modifier = a variation: block--modifier or block__element--modifier */
.card--featured { }
.card__price--sale { }<style>
.card { width: 220px; border: 1px solid #e2e8f0; border-radius: 14px; overflow: hidden; background: #fff; display: inline-block; vertical-align: top; margin: 4px; }
.card__image { display: block; width: 100%; }
.card__body { padding: 12px; }
.card__title { margin: 0 0 4px; font-size: 1rem; }
.card__price { font-weight: 800; color: #0f172a; }
.card__price--sale { color: #b91c1c; }
.card--featured { border: 2px solid #f59e0b; box-shadow: 0 10px 24px rgb(245 158 11 / 25%); }
</style>
<article class="card">
<img class="card__image" src="images/ghewar-400.webp" alt="Ghewar">
<div class="card__body"><h3 class="card__title">Ghewar</h3><span class="card__price">₹650/kg</span></div>
</article>
<article class="card card--featured">
<img class="card__image" src="images/kaju-katli-400.webp" alt="Kaju katli">
<div class="card__body"><h3 class="card__title">Kaju Katli</h3><span class="card__price card__price--sale">₹810/kg (10% off)</span></div>
</article>Before
- #products .grid div.item h3 span.red
- Specificity 1,3,3 – impossible to override
- Breaks if HTML structure changes
- Can’t tell where it is used
After (BEM)
- .card__price--sale
- Specificity 0,1,0 – easy to reason about
- Works wherever the class is used
- Search the class name → find every usage
A professional file structure
css/ ├── main.css ← the only file linked in HTML (imports the rest, or is built from them) ├── 1-tokens.css ← :root variables: colours, spacing, fonts, radius, shadows ├── 2-base.css ← reset, body, headings, links, images ├── 3-layout.css ← .container, header, footer, grid helpers ├── 4-components/ │ ├── button.css │ ├── card.css │ ├── form.css │ └── modal.css ├── 5-pages/ ← rare page-specific tweaks (home.css, menu.css) └── 6-utilities.css ← .sr-only, .text-center, .mt-0 … (last, may use !important)
Generic rules first (tokens, element selectors), specific ones last (components, utilities). Then later rules naturally override earlier ones and you almost never need !important. For small sites, one style.css with these sections as comments is fine.
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; }
body { min-height: 100vh; line-height: 1.6; font-family: var(--font-body); color: var(--text); background: var(--bg); }
img, picture, video, svg { display: block; max-width: 100%; height: auto; }
input, button, textarea, select { font: inherit; }
p, h1, h2, h3 { overflow-wrap: break-word; }
h1, h2, h3 { line-height: 1.2; text-wrap: balance; }
:focus-visible { outline: 3px solid var(--focus, #f59e0b); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; } }Utility classes – small and few
| Utility | CSS | Use |
|---|---|---|
| .sr-only | Visually hidden, readable by screen readers | Icon buttons, skip text |
| .container | max-width + margin auto + padding | Page width |
| .stack > * + * | margin-top: var(--space) | Vertical rhythm between children |
| .text-center | text-align: center | One-off alignment |
| .visually-hidden-mobile | Inside a media query | Hide extras on phones |
<style>
.stack > * + * { margin-top: var(--space, 12px); } /* the "lobotomised owl" */
.box { background: #eef2ff; padding: 10px; border-radius: 8px; }
</style>
<div class="stack" style="--space:16px">
<div class="box">Every child after the first…</div>
<div class="box">…gets the same top margin…</div>
<div class="box">…from ONE rule. Change --space to change the rhythm.</div>
</div>Debugging like a pro in DevTools
| Tool | Where | Solves |
|---|---|---|
| Computed tab | Elements → Computed | Final value of a property and which rule set it |
| Grid / Flex badges | Click “grid” or “flex” next to an element | Shows tracks, gaps and line numbers |
| :hov button | Styles pane | Force :hover, :focus to style states |
| Box model diagram | Computed tab top | See exact margin/padding/border sizes |
| Coverage | Ctrl+Shift+P → “Coverage” | Percentage of unused CSS on the page |
| Rendering → Emulate | Ctrl+Shift+P → “Rendering” | Test dark mode, reduced motion, print |
Performance checklist
- Link one CSS file in the <head> (render-blocking but needed) – avoid @import chains in production; bundle instead.
- Remove unused CSS (Coverage tab); keep framework builds trimmed.
- Minify for production (cssnano, esbuild, or an online minifier): often 20–30% smaller.
- Enable gzip/brotli on the server and long cache headers with versioned file names (style.v3.css).
- Animate only transform/opacity; avoid huge box-shadows on hundreds of elements.
- Load fonts with display=swap and only needed weights.
Code-review checklist (print it!)
- No IDs and no !important in component CSS
- Max 2 levels of nesting; mostly single-class selectors
- Colours, spacing and radius come from variables
- Mobile-first media queries, no fixed widths that overflow
- Visible focus styles; contrast ≥ 4.5:1
- Names describe purpose (.btn--danger), not looks (.red-btn)
- Comments explain WHY for non-obvious rules
- Validated with the W3C CSS validator / Stylelint
🏅 Job skills unlocked today
Practice tasks
🏋️ Practice – do it yourself
#menu ul li a.active, .box .title.big, .box img.Show solution
Quick quiz
🧠 Quick Quiz – test yourself
Interview corner
💼 Interview Corner
What is BEM and why use it?
Block__Element--Modifier is a naming convention that gives every element a single, unique, descriptive class. It keeps specificity flat, avoids leaks between components, makes CSS searchable and lets teams work without breaking each other’s styles.
How do you organise CSS in a large project?
Layered from generic to specific: tokens (variables), base/reset, layout, components (one file each, BEM), page overrides, utilities last – bundled and minified into one file for production, with linting and a review checklist. Optionally cascade layers (@layer) to make the order explicit.
Summary
- CSS rots from global scope, deep specificity and magic numbers.
- BEM: one flat class per element – block__element--modifier.
- Files from generic to specific: tokens → base → layout → components → utilities.
- Debug with DevTools, measure with Coverage, ship minified.
Day 18: CSS frameworks – Bootstrap and Tailwind, when to use them and how they compare to hand-written CSS.
