rsBEM Examples

Real-world examples for all three layers of the rsBEM naming system.

Layer 1: Template (rsBEM)

1. Sale โ€” Return Request

view/sale/return_request.tpl
scss/sale/return_request.scss

HTML

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

SCSS

.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;
        }
    }
}

2. Catalog โ€” Product Form

view/catalog/product_form.tpl
scss/catalog/product_form.scss

HTML

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

3. Common โ€” Dashboard

view/common/dashboard.tpl
scss/common/dashboard.scss

HTML

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

4. Multi-Word Folder โ€” User Settings

view/user_settings/profile_form.tpl
scss/user_settings/profile_form.scss

When a folder name contains multiple words (snake_case), it is preserved as-is. The hyphen separates folder from file:

HTML

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

SCSS

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

5. Nested Folder โ€” Marketplace Integration

view/marketplace/partner/claim.tpl
scss/marketplace/partner/claim.scss

When templates live in nested directories, each folder is separated by a hyphen. The last segment before __ is the file:

marketplace/partner/ โ†’ marketplace-partner

HTML

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

SCSS

.marketplace-partner-claim {
    &__container {
        padding: 20px;
    }

    &__status-badge {
        padding: 4px 12px;
        border-radius: 4px;

        &--open    { background: #fff3cd; }
        &--closed  { background: #d4edda; }
    }
}

6. Naming Decision Guide

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

Layer 2: Component (Standard BEM)

7. Component โ€” Modal

Shared UI component. No file-path prefix โ€” standard BEM only.

SCSS

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

8. Component โ€” Tooltip

SCSS

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

9. Component โ€” Tabs

Tab variants use modifiers on the block, not separate naming patterns.

SCSS

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

Layer 3: Utility

10. Utility โ€” Layout Composition

Utility classes compose directly in HTML. No BEM structure โ€” just prefix-value.

HTML

<!-- 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>

Prefix Reference

// 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

11. Component โ€” Admin Heading

Project-specific BEM component shared across all admin pages. Still follows standard BEM (Layer 2).

HTML

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

12. Component โ€” Status & Validation

HTML

<!-- 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>

Mixed: All Layers Together

13. Real-World โ€” All Layers in One Template

view/sale/return_request.tpl

A real template typically uses classes from multiple layers:

HTML

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