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
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
@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.
.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.