БЕМ-методологія організації CSS-коду

Писати CSS-код легко. Масшабувати та підтримувати його — ні

Це правда. І це неодноразово підтверджувалось у багатьох проектах. Будь то конструктор сайтів з темами, що настроюються (проект Getsocio — 28 тисяч рядків CSS) коду або сайт-візитка з порівняно невеликою кількістю стилів. Будь-які складні редагування у зв'язку зі змінами дизайну або з появою нових сторінок призводять до тривалого рефакторингу, в самому запущеному випадку — до дублювання стилів. При цьому постійно є ризик щось зламати в самому несподіваному місці.

У всіх проектах рано чи пізно розробники втрачають контроль над кодом CSS. Найчастіше вони навіть цього не помічають. Ознаками можуть бути небажання перевертати старий віджет, який зустрічається в кількох місцях на сайті, несподівано багато часу, необхідне на внесення правок у стилі, почуття провини перед колегами, яким у майбутньому доведеться підтримувати написаний код, докори совісті та поганий сон.

Чому так відбувається? На початковому етапі, коли розробники отримують макети, вони створюють структуру ассетів, в яку досить добре вписується весь дизайн. Проблема народжується саме в цей момент, тому що поточний дизайн це вершина айсберга в порівнянні з майбутнім дизайном. Можна уявити варіанти рішень, що приходять на думку на даному етапі. У нас лише дві сторінки – можна помістити всі стилі в один файл. Або ще. У нас десять сторінок і всі вони не схожі, тому не варто морочитися виділенням компонентів усередині сторінок і винесенням їх в окремі файли, простіше створити файл стилів на кожну сторінку. Ідеї ​​виглядають цілком здоровими з огляду на поточні аспекти дизайну. Досвідчені розробники навіть можуть зробити деякі припущення про те, як зміниться дизайн унайближчому майбутньому, але мало хто готовий до того, на що перетвориться проект через, скажімо, п'ять років.

БЕМ (Блок Елемент Модифікатор) – методологія, яка надає рішення щодо створення архітектури проекту. Це комплексне рішення, яке диктує не лише структуру CSS, а й структуру шаблонів та скриптів. Багатий інструментарій для автоматичного створення коду, створений розробниками Yandex, також допомагає організувати процес розробки. Нам зараз цікава та частина, яка стосується стилів. Благо, методологія досить гнучка і її розробники заохочують користувачів робити експерименти і брати тільки ті її частини, які допоможуть у розробці їх проектів.

Тепер можна повернутися до наших проблем та подивитися яке рішення нам пропонує БЕМ. Перша проблема – це глобальний простір імен. Нехай ми маємо навігаційне меню.

Якщо раптом на сторінці з'явиться інший компонент, що містить елемент списку (item), або якийсь елемент пов'язаний з редагуванням (edit), то нові стилі вплинуть на існуючі.

У цьому прикладі проблема вирішується виділенням двох компонентів. toolbar та user-profile - імена цих компонентів у глобальному просторі імен. Далі ми визначаємо стилі внутрішніх елементів у межах цих компонентів.

Але таке рішення дуже погано масштабується. Якщо уявити складніші компоненти ( page , company-preview , user-post ), ми отримаємо ту саму проблему, але вже у межах одного компонента. Уточнення селекторів, наприклад, .page > .edit - дуже погана ідея, оскільки створює пов'язаність між HTML шаблонами та поданням. Змінюючи шаблон, нам потрібно буде поміняти та стилі теж. До того ж додаючи клас до селектора ми змінюємо його специфічність, а це у свою чергу ускладнює перевизначенняCSS правила для елемента. У інших місцях з'являються класи збільшення специфічності, починається гонка селекторів і біль для верстальщика.

БЕМ пропонує відмовитися від каскадності, цим однозначно визначаючи елемент.

Вкладені елементи, що належать блоку, використовуватимуть це ім'я блоку інструменту як префікс. __ служить роздільником між блоком та елементом, а _ - роздільником між БЕМ-сутністю (в даному випадку елементом) та модифікатором. Тут toolbar__item_edit та toolbar__item_edit – це модифікатори елемента toolbar__item .

Непомітно для себе ми одним махом вирішили низку проблем. Елементи тепер інкапсульовані усередині блоків та ізольовані від інших елементів. Для опису стилів блоку та його елементів можна виділити окремий файл або навіть каталог файлової системи. Таким чином, тільки глянувши на структуру проекту, можна сказати, що знаходиться в глобальному просторі. Стає легше відстежувати ієрархічні зв'язки у межах блоку. CSS код стає самодокументованим. Спрощується пошук селекторів за проектом, а також модифікація стилів та видалення коду, що не використовується.

Залишилося поговорити про самодисципліну. Щоб не звести нанівець отримані переваги, слід дотримуватися деяких правил і рекомендацій. Можна пам'ятати наступний чекліст.

  • Позиціонування блоку задається батьком
  • Для опису сутностей використовуються класи, але з id
  • Не можна створювати елементи елементів ( block__elem1__elem2 )
  • В іменах модифікаторів та елементів завжди є ім'я блоку
  • З попереднього пункту випливає, що не можна створювати глобальні модифікатори
  • Блоки можуть не містити вкладених елементів (link)
  • Блоки можуть містити в собі весь вмістсторінки або великі її частини (page, page-section)

Щоб не втратити можливість переносимості блоку між різними частинами сторінки бажано щоб позиціонування та розміри блоку (margin, top, left, width) задавалися батьком.

Припустимо, що наш toolbar знаходиться всередині блоку header і повинен займати його праву половину. Рішення може виглядати так.

CSS код блоку toolbar при цьому залишається незмінним.

Ще одне непусте питання. У якому разі створювати блок, у якому елемент? Якщо фрагмент коду залежить від інших компонент сторінки, необхідно створювати блок, якщо поза контексту батька не має сенсу, то створюється елемент.

Розберемо ще один приклад. Припустимо, до нас прийшов такий дизайн тулбара.

css-коду

Розібравшись із вимогами, ми з'ясували, що перший елемент тулбару — це текстова інформація про поточну сторінку. Наступні елементи — це кнопки, деякі з них можуть перебувати у включеному стані. Останні два елементи тулбара завжди повинні знаходитися праворуч, тобто між ними та іншими елементами стоятиме роздільник. Спробуймо написати розмітку для цього блоку.

Тут для того, щоб не дублювати загальні стилі для кожного елемента блоку toolbar ми виділяємо елемент toolbar__item і використовуємо мікс з іншими елементами: toolbar__button, toolbar__spacer та toolbar__text. Деякі елементи є вкладеними, але при цьому внутрішня структура блоку все ще залишається плоскою, тобто не порушується правило про те, що не можна створювати елементи елементів. І ще одне - всі елементи, що вимагають стилізації, мають класи, в тому числі і img. Посилання на реалізацію із стилями.

На закінчення можна сказати, що дотримання принципів БЕМ дозволяєотримати цей підтримуваний і масштабований CSS, що збільшить швидкість розробки і спростить розуміння коду новими розробниками. При цьому використовується лише угода про назву елементів без будь-якого додаткового інструментарію. Для того щоб застосувати ідеї БЕМ у своєму проекті нам достатньо того стеку технологій, який там вже напевно є.