End-to-end rules for designing, naming, organising and validating CSS in scalable front-end projects.
Tired of spending hours untangling CSS naming conflicts? Watching your perfectly organized stylesheets turn into maintenance nightmares as your project scales? You're not alone—most frontend teams face the same cascade of problems when CSS naming conventions aren't established from the start.
Here's what happens without consistent naming conventions:
.header refers to the page header, card header, or modal headerThe result? Development velocity drops, technical debt accumulates, and your team spends more time fighting CSS than building features.
These Cursor Rules implement battle-tested naming methodologies (BEM, OOCSS, SMACSS) with modern CSS features to create a scalable architecture that grows with your project. Instead of retrofitting conventions later, you'll build maintainable CSS from commit one.
What makes this different: These aren't just naming guidelines—they're a complete architectural system with automated validation, performance guardrails, and framework-specific adaptations.
namespace-component__element--modifier structure!important overrides0,1,0ds-card__title@lg) with container queriesCreating a new feature component:
/* features/product-card/index.css - Public API */
@import './blocks/card.css';
@import './blocks/badge.css';
/* features/product-card/blocks/card.css - Internals */
.ds-product-card {
/* Layout only - no colors */
display: grid;
gap: var(--sp-md, 1rem);
}
.ds-product-card__image {
aspect-ratio: 16/9;
object-fit: cover;
}
.ds-product-card__title--is-featured {
/* State modifier */
font-weight: 700;
}
.ds-product-card__price@lg {
/* Breakpoint-specific styling */
font-size: var(--text-xl, 1.25rem);
}
The developer experience:
ds-product-card__title--is-featured@lgfeatures/{domain}/blocks/Designer handoff scenario:
/* Design system tokens */
:root {
--clr-brand-500: #3b82f6;
--clr-neutral-100: #f8fafc;
--sp-sm: 0.5rem;
--sp-md: 1rem;
}
/* Component implementation matches design exactly */
.ds-button--variant-primary {
background: var(--clr-brand-500, #3b82f6);
padding: var(--sp-sm, 0.5rem) var(--sp-md, 1rem);
}
The collaboration win:
Before (typical CSS debugging):
/* Which header? Where is this defined? */
.header { /* ... */ }
.header .title { /* ... */ }
.header .title.active { /* ... */ }
After (with these rules):
/* Crystal clear hierarchy and location */
.ds-page-header__title--is-active@md {
/* Namespace: ds (design system)
Component: page-header
Element: title
Modifier: is-active
Breakpoint: md */
}
Debugging improvements:
index.cssAdd to your .stylelintrc.json:
{
"rules": {
"selector-class-pattern": "^([a-z]+)-([a-z0-9]+)(__[a-z0-9]+)?(--[a-z0-9-]+)?(@(xs|sm|md|lg|xl))?$",
"selector-max-specificity": "0,1,0",
"declaration-property-max-values": 1
}
}
styles/
├── tokens/ # Design system variables
├── features/
│ ├── user-profile/
│ │ ├── index.css # Public API
│ │ └── blocks/ # Component internals
│ │ ├── avatar.css
│ │ └── bio.css
│ └── product-grid/
│ ├── index.css
│ └── blocks/
│ ├── grid.css
│ └── item.css
└── utilities/ # Single-purpose helpers
/* tokens/index.css */
:root {
/* Color scale: --clr-{hue}-{step} */
--clr-blue-100: #dbeafe;
--clr-blue-500: #3b82f6;
--clr-blue-900: #1e3a8a;
/* Spacing scale: --sp-{size} */
--sp-xs: 0.25rem;
--sp-sm: 0.5rem;
--sp-md: 1rem;
--sp-lg: 1.5rem;
}
/* features/user-profile/blocks/avatar.css */
.ds-user-avatar {
/* Base component */
border-radius: 50%;
object-fit: cover;
}
.ds-user-avatar--size-sm {
width: var(--sp-lg, 1.5rem);
height: var(--sp-lg, 1.5rem);
}
.ds-user-avatar--size-lg {
width: calc(var(--sp-lg, 1.5rem) * 2);
height: calc(var(--sp-lg, 1.5rem) * 2);
}
For Tailwind CSS projects:
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
'brand-500': 'var(--clr-brand-500)',
},
spacing: {
'sm': 'var(--sp-sm)',
'md': 'var(--sp-md)',
}
}
}
}
For React/CSS Modules:
/* Component.module.css */
.dsUserAvatar {
composes: ds-user-avatar from 'tokens/components.css';
}
.dsUserAvatarSizeLg {
composes: ds-user-avatar--size-lg from 'tokens/components.css';
}
/* Automatically tracked deprecation */
.old-button-style {
/* @deprecated remove 2024-Q3 - replaced by ds-button */
/* ... */
}
/* Built-in bundle size tracking */
@layer reset, tokens, utilities, components, overrides;
/* Lighthouse CI enforces 40KB uncompressed limit */
.ds-button {
/* Automated contrast checking */
background: var(--clr-brand-500, #3b82f6); /* 4.5:1 contrast ratio */
color: var(--clr-white, #ffffff);
}
.ds-card {
container-type: inline-size;
}
.ds-card__content {
/* Responsive to container, not viewport */
@container (min-width: 300px) {
display: grid;
grid-template-columns: 1fr 2fr;
}
}
Ready to transform your CSS architecture? These Cursor Rules give you everything you need to build scalable, maintainable stylesheets that your entire team will love working with. No more CSS archaeology—just clean, predictable code that scales with your project.
Copy the rules into your Cursor editor and start building better CSS today.
You are an expert in CSS (Vanilla CSS, CSS Modules, SASS/SCSS, PostCSS), naming methodologies (BEM, OOCSS, SMACSS) and modern CSS features (@layer, @scope, container queries).
## Key Principles
- Favour clarity, consistency and low specificity over brevity.
- One class → one responsibility. Never mix layout, colour and behaviour in the same selector.
- Keep the cascade controllable: avoid IDs, avoid !important, prefer classes and the `:where()` reset trick for zero-specificity resets.
- Design for change: every new component or breakpoint must be introducible without refactoring existing names.
- All code examples are written in lowercase-kebab-case.
## CSS (syntax & structure)
- File layout: one top-level folder per domain feature, each with `index.css` (public API) + `block/*.css` (internals).
- Class names = `[namespace]-[component]__[element]--[modifier]@[breakpoint]`.
• namespace – 2-3 letters project prefix (e.g. `app`, `ds`).
• component – standalone UI part (block).
• element – child inside block, prefixed with `__`.
• modifier – state or variant, prefixed with `--`.
• breakpoint – optional suffix (`@sm`, `@lg`).
Example: `ds-card__title--is-highlighted@lg`.
- Reserved prefixes:
• `js-` → behaviour hooks (`js-accordion-toggle`).
• `qa-` → E2E/selectors for tests.
• `t-` → temporary migration code, expires in ≤2 sprints.
- Custom properties:
• Name as `--clr-{hue}-{step}` for colours, `--sp-{size}` for spacing.
• Public tokens live in `:root`, component-private tokens live at selector level.
- Always group selectors by responsibility order: Reset → Layout → Skin.
- Never nest more than 3 levels in SCSS; flatten before compiling.
## Error Handling & Validation
- Enforce naming with Stylelint rule `selector-class-pattern` using the regex:
`^([a-z]+)-([a-z0-9]+)(__[a-z0-9]+)?(--[a-z0-9-]+)?(@(xs|sm|md|lg|xl))?$`.
- CI fails on:
• specificity > `0,1,0` (measured via `stylelint-selector-max-specificity`).
• duplicate class definitions across features.
- Polyfill guard rails: provide fallback values for every custom property using the comma syntax, e.g. `var(--sp-md, 1rem)`.
## Framework-Specific Rules
### BEM (default)
- Components are independent; modifiers may never alter child geometry—create a new block instead.
- Never nest block inside another block’s selector; rely on HTML hierarchy.
### OOCSS
- Extract repeating layout patterns into objects prefixed `obj-` (e.g. `obj-media`).
- Skin classes (`skin-`) must only contain colours, borders, shadows.
### SMACSS
- Category suffixes: `.l-` (layout), `.c-` (component), `.u-` (utility), `.s-` (state), `.t-` (theme).
- Utilities (`u-`) must be single-purpose and `!important` is allowed only here.
### Utility-First (Tailwind)
- When Tailwind is present, restrict custom classes to layout containers and design-system tokens; everything else uses utilities.
- Create design tokens in `tailwind.config.js` mirroring `--clr-*` & `--sp-*`.
## Additional Sections
### Testing
- Snapshot all critical components with Storybook + Chromatic; use `qa-` classes only for automation selectors.
- Visual diff failure budgets: ≤2 px variance allowed on text, 0 px on layout.
### Performance & Specificity
- Bundle order: `@layer reset, tokens, utilities, components, overrides` to keep override cost O(1).
- Hard cap of 40 KB uncompressed CSS per page; monitor via Lighthouse in CI.
### Accessibility & Responsiveness
- Min 2:1 colour contrast ratio enforced via design tokens.
- Provide container queries for every component wider than 300 px using `@container style(...)`.
### Documentation
- Each feature folder must include `README.md` with example HTML, modifier matrix, and accessibility notes.
- Deprecated classes are annotated with `/* @deprecated remove 2024-Q3 */` and removed within two minor versions.