BEM — Block Element Modifier metodologiyasi

~20 daq · CSS · Animatsiya va Ilg'or mavzular

Muammodan boshlaylik

Loyiha boshida CSS fayl 200 qator, hammasi tushunarli. Bir yildan keyin — 5000 qator va uch dasturchi:

.title { font-size: 24px; }               /* qaysi title? */
.card .title { font-size: 18px; }
.sidebar .card .title { font-size: 14px; }
.header .nav .list .item .link.active { color: blue; }   /* 5-dars: specificity (0, 6, 0) */
.active { color: red !important; }         /* kimdir urushda yutqazdi */

Muammolar:

  • Nomlar to'qnashadi: .title sahifaning o'nta joyida, har biri boshqacha
  • Specificity urushlari (5-dars): har bir yangi qoida oldingisini yengish uchun uzunroq
  • O'chirishdan qo'rqish: "bu class qayerda ishlatiladi?" — hech kim bilmaydi, shuning uchun hech narsa o'chirilmaydi
  • Ko'chirish imkonsiz: kartochkani boshqa sahifaga ko'chirsangiz — uning stillari .sidebar ichida bo'lgani uchun buziladi

Bu muammolarning ildizi — nomlash. BEM — CSS class larini nomlashning qat'iy, oddiy qoidalari.


Uch tushuncha

BEM — Block, Element, Modifier.

Block — mustaqil komponent

.card { }
.header { }
.search-form { }

O'z-o'zidan ma'noga ega, sahifaning istalgan joyiga ko'chirilishi mumkin bo'lgan qism. Nomi — vazifasi bo'yicha (2-dars: .btn-danger, .red-button emas).

Element — blokning qismi

.card__image { }
.card__title { }
.card__price { }

Blokdan tashqarida ma'nosi yo'q qism. Yozilishi: blok__element — ikkita pastki chiziq.

Modifier — variant yoki holat

.card--featured { }       /* blok varianti */
.btn--primary { }
.btn--large { }
.card__title--small { }   /* element varianti */

Ko'rinish yoki xatti-harakatning o'zgarishi. Yozilishi: blok--modifier yoki blok__element--modifier — ikkita chiziqcha.


To'liq misol

<article class="card card--featured">
  <img class="card__image" src="noutbuk.jpg" alt="Noutbuk">
  <div class="card__body">
    <h3 class="card__title">Noutbuk Pro 14</h3>
    <p class="card__price card__price--sale">12 500 000 so'm</p>
    <button class="btn btn--primary btn--small">Savatga</button>
  </div>
</article>
.card {
  border: 1px solid #e2e8f0;
  border-radius: 12px;
  overflow: hidden;
}

.card--featured {
  border-color: #f59e0b;
  box-shadow: 0 0 0 3px rgb(245 158 11 / 0.2);
}

.card__image {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

.card__body {
  padding: 16px;
}

.card__title {
  font-size: 1.125rem;
}

.card__price--sale {
  color: #dc2626;
}

.btn { padding: 10px 20px; border-radius: 8px; }
.btn--primary { background: #2563eb; color: white; }
.btn--small { padding: 6px 12px; font-size: 0.875rem; }

Bir qarashda: HTML da class nomining o'zidan element qaysi komponentga tegishli ekani va qanday holatda ekani ko'rinadi. CSS da esa barcha selektorlar — bitta class.


Asosiy qoidalar

1. Faqat class — ichma-ich selektorlarsiz

/* ❌ */
.card h3 { }
.card .title { }

/* ✅ */
.card__title { }

Hamma selektorning specificity si (0, 1, 0) — 5-darsdagi "past va tekis specificity" o'z-o'zidan ta'minlanadi. Tartib va modifier lar har doim kutilganday ishlaydi.

2. Element — doim blokka bog'lanadi, ichma-ich emas

<div class="card">
  <div class="card__body">
    <h3 class="card__title">...</h3>    <!-- ✅ card__body__title EMAS -->
  </div>
</div>

card__body__title — xato. HTML qanchalik chuqur bo'lmasin, element nomi — blok__element. HTML tuzilmasi o'zgarsa (yana bitta div qo'shilsa) — class nomlari o'zgarmaydi.

3. Modifier — asosiy class bilan birga

<button class="btn btn--primary">       <!-- ✅ -->
<button class="btn--primary">           <!-- ❌ asosiy stillar yo'q -->

Modifier faqat farqni saqlaydi; asosiy stillar .btn da.

4. Ichki blok — o'z nomi bilan

Kartochka ichidagi tugma — kartochkaning elementi emas, mustaqil .btn bloki. Lekin kartochka ichida joylashuvi kerak bo'lsa — aralash (mix):

<button class="btn btn--primary card__action">Savatga</button>
  • .btn — tugma qanday ko'rinadi (o'zining blok stillari)
  • .card__action — kartochka ichida qayerda turadi (margin, joylashuv)

Tugmaning o'zi kartochkadan mustaqil qoladi.


Holatlar

Vaqtinchalik holatlar (ochiq, faol, yuklanmoqda) uchun ikki yondashuv:

.menu__item--active { }          /* BEM modifier */
.menu__item.is-active { }        /* "is-" yoki "has-" prefiksli holat class i (SMACSS uslubi) */
.menu__item[aria-current="page"] { }   /* ARIA atributi — eng yaxshisi, agar mavjud bo'lsa */

ARIA atributlari (aria-expanded, aria-current, aria-selected) — ham stil uchun, ham ekran o'quvchilar uchun: bitta manba, ikki foyda.


BEM va zamonaviy vositalar

BEM 2010-yillarda Yandex da yaratilgan. Bugun xuddi shu muammolarni hal qiladigan boshqa yondashuvlar ham bor:

Yondashuv Qanday hal qiladi
BEM Nomlash qoidalari — qo'shimcha vosita kerak emas
CSS Modules Build vositasi class nomlarini avtomatik noyob qiladi (.title → .Card_title_x7f2)
Tailwind CSS Utility class lar to'g'ridan-to'g'ri HTML da: class="p-4 rounded-lg border"
Scoped styles (Vue, Svelte) Komponent stillari faqat shu komponentga tegishli
@scope (yangi CSS) Stillarni DOM qismiga cheklash

Freymvork va build vositalarisiz oddiy CSS yozganda (bu DevDocs saytining ko'p qismi kabi) — BEM eng sodda va ishonchli tanlov. Va boshqa yondashuvlardan foydalanganda ham BEM ning g'oyalari — komponentlar, past specificity, ma'noli nomlar — o'z kuchini saqlaydi.


Nima uchun shunday?

Nima uchun BEM nomlari bunchalik uzun va "xunuk" — card__price--sale o'rniga .sale qisqaroq emasmi?

Chunki qisqa nomlar global — va CSS da hamma class lar global. .sale bugun sizning kartochkangizda, ertaga boshqa dasturchi uni bannerda boshqa ma'noda ishlatadi va ikkalasi bir-birini buzadi. Uzun nom — bu nomlar fazosi (namespace): card__price--sale faqat bitta narsani anglatadi va boshqa hech narsa bilan to'qnashmaydi. Bundan tashqari, uzunlik o'zi ma'lumot beradi: HTML ni ochib, CSS faylga qaramasdan, har bir element qaysi komponentga tegishli va qanday holatda ekanini bilasiz. Yozishda bir necha harf ko'p — lekin bir yildan keyin "bu class ni o'chirsam nima buziladi?" degan savolga darhol javob bera olasiz. Katta loyihada bu soatlab tejalgan vaqt.


Xulosa

Eslab qoling:

  • Block — mustaqil komponent: .card
  • Element — blok qismi, ikkita pastki chiziq: .card__title
  • Modifier — variant/holat, ikkita chiziqcha: .card--featured, .btn--primary
  • Faqat bitta class li selektorlar — specificity doim (0, 1, 0)
  • Element nomi — blok__element, HTML chuqurligidan qat'i nazar (card__body__title emas)
  • Modifier — asosiy class bilan birga: class="btn btn--primary"
  • Ichki blok — o'z nomi + joylashuv uchun aralash: class="btn card__action"
  • Holatlar — modifier, is- class yoki ARIA atributlari

Kurs yakuni

Tabriklaymiz — siz CSS kursini tugatdingiz! Endi siz:

  • Kaskad, specificity va meros qanday ishlashini tushunasiz va "stil nega ishlamayapti?" savoliga DevTools da javob topasiz
  • Box model, birliklar va tipografiya bilan o'qilishi oson, toza sahifalar yasaysiz
  • Flexbox va Grid bilan har qanday layoutni qurasiz — header dan dashboard gacha
  • position, z-index va stacking context bilan ustma-ust elementlarni boshqarasiz
  • Mobile First va fluid qiymatlar bilan har qanday ekranga moslashadigan sayt yasaysiz
  • Silliq va tez animatsiyalar yozasiz, foydalanuvchi sozlamalarini hurmat qilgan holda
  • Zamonaviy selektorlar, funksiyalar va BEM bilan katta loyihada ham tartibli CSS yozasiz

Keyingi qadamlar

  • Amaliyot: sevimli saytingizdan bitta sahifani noldan takrorlab ko'ring — eng yaxshi mashq
  • Flexbox Froggy va Grid Garden — o'yin shaklidagi mashqlar
  • JavaScript kursi — sahifalarga hayot qo'shish
  • React kursi — komponentlar bilan katta interfeyslar
  • MDN Web Docs — har bir CSS xususiyati bo'yicha eng ishonchli ma'lumotnoma