Architecture

CSS architecture

Good CSS architecture should reduce decisions, not create weekly debates about where a button belongs. Structure should make ownership obvious and maintenance boring in the best possible way.

File structure

TEXT code example
css/
    site.css

    settings/
    base/
    utilities/
    layout/
    components/
    theme/
    legacy/
    hacks/

Root files should be import maps, not giant dumping grounds. Each component should own its own partial instead of disappearing inside one oversized stylesheet that is hard to maintain.

Root file as import map

CSS code example
@layer legacy, settings, base, utilities,
layout, components, theme, hacks;

@import './legacy/vendor.css' layer(legacy);
@import './settings/variables.css' layer(settings);
@import './layout/page-shell.css' layer(layout);
@import './components/product-card.css' layer(components);
@import './theme/brand.css' layer(theme);

The main stylesheet should define layer order first, then import files into the correct place. If the root file becomes a working area instead of an import map, architecture starts leaking.

On this site, .page-shell sets width and horizontal centering for any shell (including the site header). Section-sized vertical padding is scoped to main.page-shell so the header can reuse the same class without inheriting main-column rhythm.

Component partials

One component, one partial. Each file should contain stable styles, child selectors, modifiers, state, and breakpoint changes for that component only.

File size and cognitive load

Most component partials should stay small enough to understand quickly. Around 50 to 250 lines is common. Larger complex components may reach 300 to 400 lines, but that should trigger review, not pride.

Large files usually hide sub-components, repeated patterns, old hacks, or responsibilities that should have moved out months ago.

Media query organisation

Put shared styles first. Then add breakpoint rules only where something changes. Breakpoints should describe differences, not restate the entire component unnecessarily.

CSS code example
.modal {
    /* Shared styles first */

    &--large {
        /* Modifier styles */
    }

    @media (--desktop) {
        /* Only what changes */
    }

    @media (--tablet) {
        /* Only what changes */
    }

    @media (--mobile) {
        /* Only what changes */
    }
}

  • Shared styles first.
  • Only changed values inside breakpoints.
  • Keep modifier and state breakpoint changes nearby.
  • Keep child selector changes near the child selector they affect.
  • Use named custom media queries, not remembered magic numbers.

Working rules

  • If a group of rules feels like its own component, it probably is.
  • Do not hide temporary fixes inside normal component files.
  • Do not let third-party CSS sit outside the legacy layer.
  • Do not use utility chains instead of actual ownership.
  • Large files trigger review, not acceptance.
  • If the project becomes difficult to explain, it becomes worse to maintain.