A layered CSS naming system for MVC projects.
Three layers β one convention β zero ambiguity.
| Layer | Name | Pattern | Scope |
|---|---|---|---|
| 1 | Template (rsBEM) | folder-file__element--modifier |
Styles for a single .tpl file |
| 2 | Component (BEM) | block__element--modifier |
Shared, reusable UI components |
| 3 | Utility | prefix-value |
Single-purpose global helper classes |
Is this style for a single template file?
βββ YES β Layer 1 (Template / rsBEM)
β .sale-return_request__save-btn
βββ NO β Is it a reusable UI component (library or project-specific)?
βββ YES β Layer 2 (Component / BEM)
β .modal__header .btn--pri .admin-heading__title
βββ NO β Is it a single-purpose CSS property?
βββ YES β Layer 3 (Utility)
.d-flex .padding-sm .text-center
Why hyphen as the separator? Underscores are used within folder and file names (snake_case).
The hyphen (-) is reserved exclusively as the folderβfile separator, making parsing unambiguous.
| Segment | Separator | Case | Description |
|---|---|---|---|
| folder | start | preserves original | Template directory name (keeps snake_case if the directory uses it) |
| file_name | - after folder |
preserves original | Template file name (keeps snake_case if the file uses it) |
| element-name | __ |
kebab-case | Describes what the element is |
| modifier | -- |
kebab-case | State or variant |
The class prefix maps 1:1 to the template path. A Ctrl + Shift + F search on any class locates both the template and its styles.
When templates live in nested directories, each folder segment is separated by a hyphen β the same separator used between folder and file. The last segment before __ is always the file:
The HTML tree is not mirrored in class names. The element name describes what it is, not where it sits.
β .sale-return_request__form_footer_save_btn (DOM-coupled)
β
.sale-return_request__save-btn (flat identity)
Hyphens express logical grouping within element names. Underscores are not used for sub-elements.
β __process_bubble (false hierarchy)
β
__process-bubble (semantic group)
Element names are specific enough to understand without surrounding context.
β __step (which step?)
β
__process-step (clear intent)
Flat, scoped, descriptive:
.sale-return_request__save-btn.sale-return_request__process-step--done.user_settings-profile_form__avatar.marketplace-partner-claim__status-badgeGeneric, nested, or vague:
.btn-save (which page?)...__form_footer_btn (nested).user-settings-profile_form__β¦ (folder converted to kebab)| Aspect | BEM | rsBEM |
|---|---|---|
| Block naming | Free-form | File-route prefix |
| File location | Unknown from class | Readable from class name |
| Scope | Component-scoped | File/template-scoped |
| Reusability | Cross-project | Within project |
| Searchability | Requires convention | Built-in (grep friendly) |
{
"rules": {
"selector-class-pattern": [
"^[a-z][a-z0-9]*(?:_[a-z0-9]+)*(?:-[a-z][a-z0-9]*(?:_[a-z0-9]+)*)+__[a-z][a-z0-9]*(?:-[a-z0-9]+)*(?:--[a-z0-9]+(?:-[a-z0-9]+)*)?$",
{
"message": "Class names must follow rsBEM: [folder]-[file_name]__[element-name]--[modifier]"
}
]
}
}
Shared, reusable UI components (library or project). No file-path prefix β just standard BEM.
| Rule | Correct | Incorrect |
|---|---|---|
Sub-elements use __ |
.tooltip__arrow |
.tooltip-arrow |
Modifiers use -- |
.tooltip--top |
.tooltip.top |
| Block name is kebab-case | .slide-menu__header |
.slide-menu-header |
Examples: .modal__header, .btn--pri, .switch__slider, .tab__head--active, .admin-heading__title, .status--danger
Single-purpose, composable classes. Pattern: prefix-value. No BEM structure.
| Category | Prefix | Examples |
|---|---|---|
| Display | d- | d-flex, d-grid, d-none |
| Flex | flex- | flex-center, flex-col, flex-gap-md |
| Padding | padding- | padding-sm, padding-y-md |
| Margin | margin- | margin-sm, margin-t-md |
| Text | text- | text-center, text-upper, text-nowrap |
| Font Size | fsi- | fsi-14, fsi-16, fsi-20 |
| Font Weight | fwe- | fwe-semibold, fwe-bold |
| Image | img- | img-responsive, img-circle |
| Theme Color | tc- | tc-pri-500, tc-text-dark-1 |
| Theme BG | tbc- | tbc-pri-100, tbc-grey-300 |
| Width / Height | w- / h- | w-full, h-auto |
| Position | pos- | pos-relative, pos-absolute |
| Cursor | cursor- | cursor-pointer, cursor-default |
Three layers cover everything: Template (rsBEM) for page-specific styles, Component (BEM) for shared UI, Utility for atomic classes.
rsBEM v2.0.0 β 2025. A layered CSS naming system for MVC projects.