روش نامگذاری BEM در CSS
روش نامگذاری BEM (Block, Element, Modifier) یک الگوی ساختاری و قابل فهم برای نوشتن CSS است که به خوانایی، قابلیت نگهداری و مقیاسپذیری کمک میکند. در این مقاله به زبان فارسی توضیح میدهیم که BEM چیست، قوانین پایه، مثالهای عملی، اشتباهات رایج و نکات پیشرفته برای پروژههای بزرگ.
مبانی BEM — Block، Element و Modifier
- Block (بلوک): یک جزء مستقل که مفهوم و عملکرد مشخصی دارد، مثل menu یا card.
- Element (المان): قسمت داخلی بلوک که وابسته به آن است و بدون بلوک معنی ندارد؛ با دو underscore جدا میشود:
block__element. - Modifier (مدیفایر): حالت یا تغییر در بلوک/المان که با دو hyphen نمایش داده میشود:
block--modifierیاblock__element--modifier.
قواعد نوشتاری پیشنهادی
- از حروف کوچک و خط تیره برای جدا کردن کلمات استفاده کنید (kebab-case).
- هر کلاس فقط یک مسئولیت داشته باشد: استایل یا هوک برای JS، نه هر دو همزمان.
- از انتخابگرهای descendant عمیق و جملهای پرهیز کنید؛ بهتر است با کلاسهای BEM کار کنید تا specificity کنترل شود.
نمونه ساده HTML و CSS با BEM
<!-- HTML -->
<div class="card card--featured">
<h3 class="card__title">عنوان کارت</h3>
<p class="card__description">توضیحات کوتاه...</p>
<button class="card__action card__action--primary">خرید</button>
</div>
در این کد، card بلاک است، card__title و card__description المانها هستند و card--featured و card__action--primary مدیفایرها.
/* CSS */.card { border: 1px solid #ddd; padding: 16px; border-radius: 6px; }
.card--featured { box-shadow: 0 4px 14px rgba(0,0,0,0.08); }
.card__title { margin: 0 0 8px; font-size: 1.1rem; }
.card__description { color: #666; font-size: 0.95rem; }
.card__action { background: none; border: 1px solid #ccc; padding: 8px 12px; }
.card__action--primary { background: #0069ff; color: #fff; border-color: #0069ff; }
در CSS بالا، هر کلاس تنها به خودش وابسته است؛ بنابراین میتوان کارتها را در جاهای مختلف بدون نگرانی از تداخل استفاده کرد.
مقایسهی مفهومی — جدول
| نوع | نمونه نام | توضیح |
|---|---|---|
| Block | menu | کامپوننت مستقل |
| Element | menu__item | قسمت داخلی وابسته به menu |
| Modifier | menu__item–active | حالت یا تغییر در item |
مثال عملی: تبدیل CSS به سبک BEM
فرض کنید استایل اولیه شما به شکل زیر است (غیر BEM):
<!-- Non-BEM HTML -->
<ul class="nav">
<li class="active">Home</li>
<li>About</li>
</ul>
مشکل: کلاس عمومی active میتواند در هرجای پروژه تداخل ایجاد کند. بهتر است با BEM:
<ul class="nav">
<li class="nav__item nav__item--active">Home</li>
<li class="nav__item">About</li>
</ul>
این نگارش، محدوده کلاس را به بلاک nav محدود میکند و از تداخل جلوگیری میشود.
نکات پیشرفته و بهترین شیوهها
- حالتهای جاوااسکریپتی: بهجای استفاده از مدیفایرهایی که وابسته به JS هستند، میتوانید از کلاسهای state مثل
is-openیاhas-errorاستفاده کنید تا واضح باشد که این کلاسها برای وضعیت هستند و نه استایل دائمی. - Namespace: در پروژههای بزرگ از پیشوند بلوکی (مثلاً
app-) برای جلوگیری از تداخل بین پکیجها استفاده کنید:app-card. - فایلبندی: هر بلوک را در فایل جداگانه نگه دارید (مثلاً
_card.scss) و در یک فایل مرکزی آنها را ایمپورت کنید. - ابزارها: از stylelint با پلاگین BEM یا قوانین محتاطانه برای جلوگیری از نامگذاری نادرست بهره ببرید.
اشتباهات رایج و راهحلها
- استفاده از انتخابگرهای بیش از حد خاص (مانند
.block .element > .sub) — راه حل: استفاده از کلاسهای صریح BEM. - ترکیب BEM با selector-based overrides — باعث سردرگمی و specificity بالا میشود. بهتر است overrides با مدیفایرها انجام شود.
- استفاده از تگ HTML به عنوان کلید کلاس — کلاسها باید معنایی مستقل داشته باشند، نه وابسته به تگ.
وقتی BEM کافی نیست
در پروژههای خیلی بزرگ یا زمانی که از CSS Modules/Styled Components استفاده میکنید، برخی مفاهیم BEM خودکار یا غیرضروری میشوند. اما اصول جداسازی و نامگذاری واضح که BEM ترویج میدهد، همچنان مفید است. میتوان از نسخههای ترکیبی استفاده کرد: نامگذاری اساسی BEM بهعلاوه scoping محلی توسط ابزارهای مدرن.
جمعبندی و توصیههای عملی
- با قواعد ساده شروع کنید: block__element–modifier.
- قواعد تیمی (style guide) بنویسید و قوانین را در lint قرار دهید.
- از BEM به عنوان قرارداد برای همکاری بین تیم CSS، HTML و JS استفاده کنید.
- در صورت نیاز، از namespace و state-classes برای وضوح بیشتر بهره ببرید.
روش نامگذاری BEM، یک الگوی امتحانشده برای نگهداری و توسعه مقیاسپذیر رابطهاست. با رعایت چند قاعده ساده میتوانید از تداخل کلاسها جلوگیری کنید، specificity را کنترل کنید و اجزای قابل استفاده مجدد بسازید.
آیا این مطلب برای شما مفید بود ؟




