Real-world examples for all three layers of the rsBEM naming system.
<div class="sale-return_request__container"> <div class="sale-return_request__header"> <h1 class="sale-return_request__page-title">Return Request #1234</h1> <span class="sale-return_request__status-badge--pending">Pending</span> </div> <div class="sale-return_request__process-bar"> <div class="sale-return_request__process-step--done"> <div class="sale-return_request__process-icon">โ</div> <span class="sale-return_request__process-label">Application</span> </div> <div class="sale-return_request__process-line--active"></div> <div class="sale-return_request__process-step--active"> <div class="sale-return_request__process-icon">2</div> <span class="sale-return_request__process-label">Review</span> </div> </div> <div class="sale-return_request__action-bar"> <button class="sale-return_request__save-btn">Save</button> <button class="sale-return_request__cancel-btn">Cancel</button> </div> </div>
.sale-return_request { &__container { max-width: 960px; margin: 0 auto; } &__status-badge { padding: 4px 12px; border-radius: 4px; &--pending { background: #fff3cd; color: #856404; } &--approved { background: #d4edda; color: #155724; } &--rejected { background: #f8d7da; color: #721c24; } } &__process-step { display: flex; align-items: center; &--done { opacity: 0.6; } &--active { font-weight: bold; } } &__page-title { font-size: 1.5rem; // Media queries nest inside their selector @media (max-width: 768px) { font-size: 1.2rem; } } }
<div class="catalog-product_form__container"> <div class="catalog-product_form__image-grid"> <div class="catalog-product_form__image-preview--main"> <img src="photo.jpg" /> <button class="catalog-product_form__image-remove">ร</button> </div> <div class="catalog-product_form__image-preview">...</div> <div class="catalog-product_form__image-preview--loading">...</div> </div> <div class="catalog-product_form__price-group"> <label class="catalog-product_form__price-label">Price</label> <input class="catalog-product_form__price-input" /> <label class="catalog-product_form__price-label">Sale Price</label> <input class="catalog-product_form__price-input--error" /> </div> </div>
<div class="common-dashboard__container"> <p class="common-dashboard__welcome-text">Welcome back!</p> <div class="common-dashboard__stat-grid"> <div class="common-dashboard__stat-card"> <div class="common-dashboard__stat-value">1,234</div> <div class="common-dashboard__stat-label">Orders</div> <div class="common-dashboard__stat-trend--up">โ 12%</div> </div> <div class="common-dashboard__stat-card"> <div class="common-dashboard__stat-value">โบ45,678</div> <div class="common-dashboard__stat-label">Revenue</div> <div class="common-dashboard__stat-trend--down">โ 3%</div> </div> </div> <table class="common-dashboard__order-table"> <tr class="common-dashboard__order-row--highlighted"> <td class="common-dashboard__order-id">#5678</td> <td class="common-dashboard__order-date">2025-01-15</td> <td class="common-dashboard__order-total">โบ1,250</td> </tr> </table> </div>
When a folder name contains multiple words (snake_case), it is preserved as-is. The hyphen separates folder from file:
<div class="user_settings-profile_form__container"> <div class="user_settings-profile_form__avatar-section"> <img class="user_settings-profile_form__avatar-image" /> <button class="user_settings-profile_form__avatar-upload">Change</button> </div> <div class="user_settings-profile_form__field-group"> <label class="user_settings-profile_form__field-label">Name</label> <input class="user_settings-profile_form__field-input" /> </div> <button class="user_settings-profile_form__save-btn">Save</button> </div>
.user_settings-profile_form { &__container { max-width: 640px; } &__avatar-image { width: 80px; height: 80px; border-radius: 50%; } &__save-btn { margin-top: 20px; } }
โ ๏ธ Common mistake: .user-settings-profile_form__โฆ โ the folder user_settings must NOT be converted to kebab-case. Preserve the original form.
When templates live in nested directories, each folder is separated by a hyphen. The last segment before __ is the file:
marketplace/partner/ โ marketplace-partner
<div class="marketplace-partner-claim__container"> <div class="marketplace-partner-claim__header"> <h1 class="marketplace-partner-claim__page-title">Claim #5678</h1> <span class="marketplace-partner-claim__status-badge--open">Open</span> </div> <div class="marketplace-partner-claim__detail-section"> <p class="marketplace-partner-claim__detail-label">Reason</p> <p class="marketplace-partner-claim__detail-value">Missing item</p> </div> </div>
.marketplace-partner-claim { &__container { padding: 20px; } &__status-badge { padding: 4px 12px; border-radius: 4px; &--open { background: #fff3cd; } &--closed { background: #d4edda; } } }
When naming an element, follow this decision flow:
// Step 1: What file is this in? // โ view/sale/return_request.tpl // โ prefix: sale-return_request // Step 2: What IS this element? // โ It's a button that saves the form // โ element: save-btn // Step 3: Does it belong to a logical group? // โ The "process" section has: bar, step, icon, label, line // โ All prefixed with "process-" // Step 4: Does it have states? // โ step can be: done, active, upcoming // โ modifier: --done, --active // Result: .sale-return_request__process-step--done
Shared UI component. No file-path prefix โ standard BEM only.
.modal { &--opened { display: block; } &__dialog { max-width: 600px; &--sm { max-width: 400px; } &--lg { max-width: 900px; } } &__header { padding: 16px 24px; } &__body { padding: 24px; } &__footer { padding: 16px 24px; } // โ Modifiers use --, NOT class stacking &__notification-list { &--error { background: #f8d7da; } &--warning { background: #fff3cd; } &--success { background: #d4edda; } } }
โ ๏ธ Common mistake: .modal__notification-list.error โ modifiers must use --, not class stacking.
.tooltip { // โ Position modifiers use --, NOT class stacking &--top { } &--right { } &--bottom { } &--left { } // โ Sub-element uses __, NOT single hyphen &__arrow { position: absolute; border: 5px solid transparent; } }
โ ๏ธ Common mistakes: .tooltip-arrow (should be __arrow), .tooltip.top (should be --top).
Tab variants use modifiers on the block, not separate naming patterns.
.tab { &__container { width: 100%; } &__heading { display: flex; border-bottom: 2px solid #e9ecef; } &__head { padding: 10px 16px; &--active { color: #0d6efd; border-bottom-color: #0d6efd; } } &__body { padding: 16px 0; } &__panel { display: none; &--active { display: block; } } // Variants as block modifiers &--pill { /* pill/segment style */ } &--scroll { /* horizontal overflow */ } }
โ ๏ธ Common mistake: Using .tabv2-*, .tabv3-*, .tabv4-* โ use .tab--pill, .tab--scroll instead.
Utility classes compose directly in HTML. No BEM structure โ just prefix-value.
<!-- Flex row with centered items and medium gap --> <div class="d-flex flex-center flex-gap-md padding-md"> <div class="w-full">Content</div> <div class="w-auto">Sidebar</div> </div> <!-- Grid layout --> <div class="d-grid grid-cols-3 flex-gap-sm padding-sm"> <div>Card 1</div> <div>Card 2</div> <div>Card 3</div> </div> <!-- Typography + spacing --> <h1 class="fsi-20 fwe-bold margin-b-sm">Title</h1> <p class="text-center tc-text-dark-2 margin-y-md">Centered text</p>
// Display d-flex, d-grid, d-table, d-block, d-none // Flex flex-center, flex-col, flex-wrap, flex-gap-sm // Grid grid-cols-2, grid-cols-3, grid-auto-fit // Padding padding-sm, padding-md, padding-lg, padding-y-sm // Margin margin-sm, margin-md, margin-lg, margin-t-sm // Text text-center, text-left, text-upper, text-nowrap // Font fsi-14, fwe-semibold, ffa-sans // Width w-full, w-auto, w-fit // Height h-full, h-auto, h-screen // Color tc-pri-500, tc-text-dark-1 // BG tbc-pri-100, tbc-grey-300 // Position pos-relative, pos-absolute // Z-index z-10, z-50, z-max // Overflow ovf-hidden, ovf-auto // Cursor cursor-pointer, cursor-default // Select sel-none, sel-all // Visible vis-hidden--md-up, vis-show--lg-down
Project-specific BEM component shared across all admin pages. Still follows standard BEM (Layer 2).
<div class="admin-heading"> <h1 class="admin-heading__title">Products</h1> <div class="admin-heading__actions"> <button class="btn btn--pri">Add Product</button> </div> </div>
<!-- Status indicators --> <span class="status status--success">Active</span> <span class="status status--danger">Suspended</span> <span class="status-dot status-dot--active"></span> <!-- Validation errors --> <div class="err-required">This field is required.</div> <div class="err-email">Invalid email address.</div>
A real template typically uses classes from multiple layers:
<!-- Layer 2: Component --> <div class="admin-heading"> <h1 class="admin-heading__title">Return Request</h1> <div class="admin-heading__actions"> <!-- Layer 2: Component --> <button class="btn btn--pri">Export</button> </div> </div> <!-- Layer 1: Template (rsBEM) --> <div class="sale-return_request__container"> <!-- Layer 3: Utility --> <div class="d-flex flex-between flex-gap-md margin-b-md"> <!-- Layer 1: Template --> <span class="sale-return_request__status-badge--pending">Pending</span> <!-- Layer 2: Component --> <span class="status status--warning">Awaiting Review</span> </div> <div class="sale-return_request__process-bar"> <div class="sale-return_request__process-step--done"> <!-- Layer 3: Utility for quick alignment --> <div class="d-flex flex-col flex-center"> <div class="sale-return_request__process-icon">โ</div> <span class="sale-return_request__process-label">Applied</span> </div> </div> </div> </div>
rsBEM v2.0.0 โ 2025. A layered CSS naming system for MVC projects.