CSS Layers
Split project-wide CSS into the following three layers.
| Layer | Role |
|---|---|
| Global | Site-wide values, functions, mixins, utilities |
| Page | Per-page entry CSS (component placement) |
| Component | Component design with Block/Element + Variant/State |
Global Layer
Responsible for site-wide settings, functions, mixins, resets, and utilities.
Exclude shared partials via Stylelint
ignoreFiles; keep shared keyframes linted.
Details: Stylelint setup.
File structure by role
| Category | Files | Role |
|---|---|---|
| Settings | variables.scss, global/config.scss | Colors, typography, spacing, breakpoints |
| Functions/Mixins | global/function.scss, global/mixin.scss | Numeric conversions, media query generation, etc. |
| Base styles | reset.scss, base.scss, print.scss | Resets, element styles, print styles |
| Utilities | utilities.scss | Single-purpose classes like .u-hidden, .u-sr-only |
| Shared animations | keyframes.scss | @keyframes used across multiple components (kf- prefix) |
Utility classes
Sparingly define single-purpose classes that don’t depend on structure or skin.
u-prefix required (e.g..u-hidden,.u-sr-only)- Separate category from Block/Element (not subject to two-word/one-word rules)
- Keep to the minimum reused site-wide
Shared animations
Centralize @keyframes used across multiple components in keyframes.scss.
- Use a prefix like
kf- - Place at root level only (not inside
@media/@layer)
Component-specific
@keyframesgo in each component’s SCSS.
See File Management for details.
Page Layer
Per-page entry SCSS (e.g. home.scss, about.scss).
Role
- Import components (
@use) - Place child Blocks inside the page root class (e.g.
.main-container) - Page-specific spacing, backgrounds, etc.
Scope
| Does | Does not |
|---|---|
| Import and place components | Define component internals |
| Adjust spacing between Blocks | Define Block internal layout |
The page layer focuses on placing imported components. If you add page-layer classes, follow the same Block/Element rules and avoid styling internals of imported components.
Example
@use "@styles/partials/global" as *;@use "@components/hero/hero-container";
.main-container { > .hero-container { // @components/hero/hero-container.scss margin-top: 0; }}Extract repeating page structures as shared components under
components/parts/.
Page-layer root classes (e.g.
.main-container) are not subject to “one Block per file”. Keep them within each page’s entry SCSS.
Component Layer
Consistent rules for Block/Element structure, Variant/State separation, SCSS sections, and file management.
- Block (two words): the component itself (e.g.
.hero-container) - Element (one word): an element within a Block (e.g.
.title) - Variant / State: data attributes (default) or class mode
- One Block per file: each Block maps to one SCSS file
- @keyframes: component-specific ones go at root level, end of file
See Components for details.
Directory structure example
src/├── styles/ # Global layer│ └── partials/│ ├── global/│ │ ├── config.scss│ │ ├── function.scss│ │ ├── index.scss│ │ └── mixin.scss│ ├── base.scss│ ├── keyframes.scss│ ├── print.scss│ ├── reset.scss│ ├── utilities.scss│ └── variables.scss├── components/ # Component layer│ ├── common/ # Site-wide shared│ │ └── site-header/│ │ └── site-header.scss│ ├── parts/ # Multi-page shared│ │ └── hero-banner/│ │ └── hero-banner.scss│ └── pages/ # Page-specific│ ├── home/│ │ └── home-hero/│ │ └── home-hero.scss│ └── about/│ └── about-intro/│ └── about-intro.scss└── assets/ └── css/ # Page layer ├── home.scss └── about.scss