Episode 1 — Fundamentals / 1.10 — CSS Architecture and Project Structure
1.10.d — Real-World Folder Structure
In one sentence: How you organise CSS files determines how quickly a team can find, edit, and delete styles — the right folder structure makes the codebase navigable at a glance.
Navigation: ← 1.10.c — Utility vs Component Classes · 1.10.e — Debugging with DevTools →
1. Why folder structure matters
A single styles.css file works for a personal landing page. The moment a second developer touches it — or the page count hits double digits — a flat file becomes:
- Hard to navigate — scrolling through 2 000 lines to find button styles.
- Merge-conflict prone — two people editing the same file at the same time.
- Full of dead code — nobody deletes selectors they did not write.
Splitting styles into focused files with clear responsibilities solves all three.
2. Common folder categories
| Folder | Contents | Examples |
|---|---|---|
base/ | Resets, typography defaults, global box-sizing | _reset.css, _typography.css |
abstracts/ (or helpers/) | Variables, mixins, functions, design tokens — no output CSS | _variables.scss, _mixins.scss |
layout/ | Page-level structure: grids, header, footer, sidebar wrappers | _grid.css, _header.css |
components/ | Self-contained UI blocks | _card.css, _button.css, _modal.css |
utilities/ | Single-purpose helper classes | _spacing.css, _text.css, _display.css |
vendors/ | Third-party styles (normalize, library overrides) | _normalize.css, _prism-theme.css |
pages/ (optional) | Page-specific overrides that don't belong in a component | _home.css, _checkout.css |
3. The 7-1 SASS pattern
The most referenced CSS architecture uses seven folders and one main entry file:
scss/
├── abstracts/
│ ├── _variables.scss
│ ├── _mixins.scss
│ └── _functions.scss
├── base/
│ ├── _reset.scss
│ ├── _typography.scss
│ └── _animations.scss
├── components/
│ ├── _button.scss
│ ├── _card.scss
│ ├── _modal.scss
│ └── _form.scss
├── layout/
│ ├── _grid.scss
│ ├── _header.scss
│ ├── _footer.scss
│ └── _sidebar.scss
├── pages/
│ ├── _home.scss
│ └── _contact.scss
├── themes/
│ ├── _default.scss
│ └── _dark.scss
├── vendors/
│ ├── _normalize.scss
│ └── _prism.scss
└── main.scss ← single entry point
The entry file: main.scss
// 1. Abstracts (no CSS output)
@use 'abstracts/variables';
@use 'abstracts/mixins';
@use 'abstracts/functions';
// 2. Vendors
@use 'vendors/normalize';
// 3. Base
@use 'base/reset';
@use 'base/typography';
@use 'base/animations';
// 4. Layout
@use 'layout/grid';
@use 'layout/header';
@use 'layout/footer';
@use 'layout/sidebar';
// 5. Components
@use 'components/button';
@use 'components/card';
@use 'components/modal';
@use 'components/form';
// 6. Pages
@use 'pages/home';
@use 'pages/contact';
// 7. Themes
@use 'themes/default';
Import order matters. Abstracts first (so variables are available everywhere), vendors next (so your base/components can override if needed), then increasing specificity: base → layout → components → pages → themes.
4. Flat vs nested structures
Flat (small projects)
css/
├── variables.css
├── reset.css
├── layout.css
├── components.css
├── utilities.css
└── main.css
Works for projects with < 20 components. Every file is one scroll away.
Nested (medium–large projects)
css/
├── abstracts/
├── base/
├── components/
│ ├── _button.css
│ ├── _card.css
│ └── _modal.css
├── layout/
└── main.css
Use nesting when the components/ folder alone would have 10+ files.
Deep nesting (avoid)
css/components/cards/variants/featured/_card-featured-dark.css ← too deep
If you need more than two levels, rethink the categorisation.
5. File naming conventions
| Convention | Example | When to use |
|---|---|---|
| Underscore prefix (SASS partials) | _button.scss | SASS/SCSS projects — tells the compiler "don't emit a standalone file" |
| Kebab-case | feature-list.css | Universal; most common in CSS |
| Component-match | Name the file after the BEM block | _card.scss → .card, .card__title, .card--featured |
| Index file | components/index.scss that @forwards all siblings | Cleaner imports: @use 'components' |
6. How modern frameworks change the structure
| Tool | What happens to folders |
|---|---|
| Tailwind CSS | Most folders disappear. You keep tailwind.config.js (tokens), a small base.css (directives), and component extraction via @apply or framework templates. |
| CSS Modules (React, Next.js) | Styles live next to their component: Button.module.css beside Button.tsx. No global components/ folder needed. |
| Vue SFC | <style scoped> lives inside .vue files — one file = template + script + style. |
| Styled-components / Emotion | No CSS files at all. Styles are JS objects or tagged template literals co-located with components. |
| Vanilla Extract | TypeScript files (.css.ts) co-located with components; type-safe tokens replace _variables.scss. |
The 7-1 pattern and similar structures are most relevant for multi-page apps using SASS without a component framework. In framework-heavy projects, co-location (style next to component) usually wins.
7. Practical checklist for choosing a structure
- < 5 pages, solo dev → flat structure, one
styles.cssis fine. - 5–20 pages, small team → base / components / layout / utilities split.
- Large app, multiple developers → 7-1 or similar; enforce with linting.
- Component framework (React, Vue, Svelte) → co-locate styles; global folder only for tokens and resets.
- Tailwind → minimal CSS files;
tailwind.config.jsis your architecture.
8. Key takeaways
- Split by responsibility, not by page —
components/,layout/,base/,utilities/. - Import order matters: abstracts → vendors → base → layout → components → pages → themes.
- The 7-1 SASS pattern is the classic reference; adapt it to your project size.
- Modern frameworks favour co-location (style file beside component file).
- Two levels of nesting is enough — deeper nesting creates more problems than it solves.
Explain-It Challenge
Explain without notes:
- Why should
abstracts/be imported first in the main entry file? - Sketch a folder structure for a 10-page marketing site using SASS (list at least 4 folders).
- How does CSS Modules change where you put component styles compared to the 7-1 pattern?
Navigation: ← 1.10.c — Utility vs Component Classes · 1.10.e — Debugging with DevTools →