1.10 — CSS Architecture & Project Structure: Quick Revision
Compact cheat sheet. Print-friendly.
How to use this material (instructions)
- Skim top-to-bottom in one pass before interviews or exams.
- If a row feels fuzzy — reopen the matching lesson:
README.md → 1.10.a…1.10.e.
- Drills —
1.10-Exercise-Questions.md.
- Polished answers —
1.10-Interview-Questions.md.
1.10.a BEM Naming Convention
BEM Syntax
| Part | Pattern | Example |
|---|
| Block | .block | .card |
| Element | .block__element | .card__title |
| Modifier | .block--modifier | .card--featured |
| Element + Modifier | .block__element--modifier | .card__title--large |
Key Rules
- Elements belong to the block, never nested:
.card__title not .card__body__title.
- Always apply the base class alongside a modifier:
class="card card--featured".
- Every BEM selector is a single class → specificity is always
0-1-0.
- SASS
& compiles flat: &__title → .card__title.
BEM Alternatives
| Name | Core Idea |
|---|
| OOCSS | Separate structure from skin |
| SMACSS | Categorise: base, layout, module, state, theme |
| ITCSS | Layer by specificity (inverted triangle) |
1.10.b Component-Based CSS
Component API (3 Layers)
Base class → .alert (default appearance)
Modifiers → .alert--success (visual variant)
States → .alert.is-visible (dynamic condition)
Principles
- One component = one file, one job. No layout logic inside.
- Never style bare tags inside a component (
.card h2 { } leaks).
- Compose complex UI from small independent components.
- Spacing / positioning = parent's responsibility.
Scoping Strategies
| Strategy | Mechanism |
|---|
| BEM | Convention (developer discipline) |
| CSS Modules | Build-tool hashing (.card → .card_a3f2x) |
Vue scoped | Auto-added [data-v-xxxx] attribute |
| Shadow DOM | True browser encapsulation |
| CSS-in-JS | Runtime/build-time hashed styles |
1.10.c Utility vs Component Classes
Side-by-Side
Component: <button class="btn btn--primary">Go</button>
Utility: <button class="bg-blue-600 text-white py-2 px-4 rounded">Go</button>
Comparison Table
| Utility | Component |
|---|
| CSS per class | 1 declaration | Many declarations |
| HTML verbosity | High | Low |
| CSS file size | Small (purged) | Can grow |
| Consistency | Token-enforced | Convention-dependent |
| Refactoring | Change HTML | Change CSS |
Utilities ≠ Inline Styles
- Utilities support media queries (
md:flex), pseudo-classes (hover:bg-blue-700), and design constraints (only mt-2, mt-4 — not arbitrary values).
Hybrid Rule of Thumb
- Repeated patterns → component class.
- One-off spacing / alignment → utility class.
- Layout primitives (flex, grid, gap) → utility class often wins.
1.10.d Real-World Folder Structure
The 7-1 SASS Pattern
scss/
├── abstracts/ ← variables, mixins, functions (no output)
├── vendors/ ← third-party (normalize, etc.)
├── base/ ← resets, typography, global defaults
├── layout/ ← header, footer, grid, sidebar
├── components/ ← button, card, modal, form
├── pages/ ← page-specific overrides
├── themes/ ← dark mode, high contrast
└── main.scss ← single entry, imports all ↑
Import Order
abstracts → vendors → base → layout → components → pages → themes
Abstracts first (variables available everywhere). Increasing specificity left → right.
File Naming
| Convention | Example |
|---|
| Underscore prefix (SASS partial) | _button.scss |
| Kebab-case | feature-list.css |
| Match BEM block name | _card.scss → .card |
Modern Frameworks
| Tool | Styles live… |
|---|
| CSS Modules | Next to component: Button.module.css |
| Vue SFC | Inside .vue file: <style scoped> |
| Tailwind | tailwind.config.js + minimal base.css |
| CSS-in-JS | Inside JS/TS component files |
1.10.e Debugging with DevTools
Debugging Checklist
| Step | Action |
|---|
| 1 | Inspect element → Styles panel |
| 2 | Look for struck-through rules (overridden) |
| 3 | If rule is missing → selector is wrong or stylesheet not loaded |
| 4 | Check Computed panel for final resolved values |
| 5 | Click arrow on computed value to jump to winning rule |
Quick Tools
| Tool / Trick | Purpose |
|---|
* { outline: 1px solid red; } | Find overflow / layout issues (doesn't affect box model) |
:hov button in Styles toolbar | Force :hover, :focus, :active states |
| Flex / Grid badges | Visual axis, track, gap, and space inspection |
| Rendering → Layout Shift Regions | Flash blue on CLS shifts |
| Performance panel (green bars) | Paint cost; purple bars = layout / reflow |
Common Bugs → Fixes
| Bug | Fix |
|---|
| Rule struck-through | Higher-specificity rule wins — find it above in Styles |
z-index not working | Element needs position set; check stacking context |
| Flex item overflow | min-width: auto default → set min-width: 0 |
| Grid column blowout | 1fr with unbreakable content → use minmax(0, 1fr) |
| Horizontal scrollbar | Likely 100vw + scrollbar or negative margins |
| Collapsed margins | Adjacent vertical margins merge — use padding or gap instead |
One-Line Cheat Sheet
BEM = block__element--modifier | Flat specificity, grepable names
Component = one file, one job | Base + modifier + state API
Utility = one class, one rule | Composed in HTML, token-constrained
Folders = abstracts → vendors → base → layout → components → pages → themes
Debug = Inspect → Styles → Computed → outline trick → force states → perf panel