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

FolderContentsExamples
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

ConventionExampleWhen to use
Underscore prefix (SASS partials)_button.scssSASS/SCSS projects — tells the compiler "don't emit a standalone file"
Kebab-casefeature-list.cssUniversal; most common in CSS
Component-matchName the file after the BEM block_card.scss.card, .card__title, .card--featured
Index filecomponents/index.scss that @forwards all siblingsCleaner imports: @use 'components'

6. How modern frameworks change the structure

ToolWhat happens to folders
Tailwind CSSMost 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 / EmotionNo CSS files at all. Styles are JS objects or tagged template literals co-located with components.
Vanilla ExtractTypeScript 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

  1. < 5 pages, solo dev → flat structure, one styles.css is fine.
  2. 5–20 pages, small team → base / components / layout / utilities split.
  3. Large app, multiple developers → 7-1 or similar; enforce with linting.
  4. Component framework (React, Vue, Svelte) → co-locate styles; global folder only for tokens and resets.
  5. Tailwind → minimal CSS files; tailwind.config.js is your architecture.

8. Key takeaways

  1. Split by responsibility, not by page — components/, layout/, base/, utilities/.
  2. Import order matters: abstracts → vendors → base → layout → components → pages → themes.
  3. The 7-1 SASS pattern is the classic reference; adapt it to your project size.
  4. Modern frameworks favour co-location (style file beside component file).
  5. Two levels of nesting is enough — deeper nesting creates more problems than it solves.

Explain-It Challenge

Explain without notes:

  1. Why should abstracts/ be imported first in the main entry file?
  2. Sketch a folder structure for a 10-page marketing site using SASS (list at least 4 folders).
  3. 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 →