это система «Блок — Элемент — Модификатор».
Это один из подходов к компонентной вёрстке
Это такой подход к вёрстке, когда отдельные компоненты сайта создаются изолированно и могут использоваться в любом месте, вне зависимости от окружения и содержания.
Задача верстальщикка в контексте БЕМ, определить, какие элементы интерфейса — независимые блоки, а какие — их элементы. Что будет базовым представлением блока, а что его модификацией.
CSS определяет, как выглядит ваш компонент, а HTML применяет этот вид к элементам на странице. Чем меньше CSS «знает» про структуру HTML, тем лучше.
Функционально независимый компонент страницы, который может быть повторно использован.
Особенности:
- Название блока характеризует смысл («что это?» — «меню»: menu, «кнопка»: button), а не состояние («какой, как выглядит?» — «красный»: red, «большой»: big).
- Блок не должен влиять на свое окружение, т. е. блоку не следует задавать внешнюю геометрию (в виде отступов, границ, влияющих на размеры) и позиционирование.
Блок, он же компонент, должен быть изолированным. Это означает, что все свои отступы он должен хранить внутри себя, а не «давить» ими на другие блоки.
Из этого выводится запрет на внешние отступы у блоков. margin — запрещённое свойство для блоков в БЭМ. Внешние отступы могут быть у элементов блока, если это нужно. А у самого блока — только внутренние. padding
Блок управляет:
- только своими элементами
- и не должен хотеть управлять вложенными блоками и их элементами.
Для блока не рекомендуется использовать CSS-свойства width и max-width
- исключения width - 100%, max-width - 100%
Не рекомендуется: position: absolute, fixed, sticky
Допустимо: position: relative
Исключени margin: 0;
product, service, history, statistics, search, socials, copyright, payment, meta, features, benefits, cart, feedback, advertisement, catalog, banner, article, header, footer, card, button, page, aside, logo, warning, error, form, cover, event, avatar, slider, breadcrumbs, pagination, popup, modal, tooltip, preview, overlay, dropdown subscribing-form, site-navigation, lang-switcher
какие имена лучше не исп.: которые ничего не означают сами по себе item, object
.article{
display: flex;
font-size: 50px;
color: red;
margin: 100px; /* Запрещено */
}
Составная часть блока, которая не может использоваться в отрыве от него.
Особенности:
- Название элемента характеризует смысл («что это?» — «пункт»: item, «текст»: text), а не состояние («какой, как выглядит?» — «красный»: red, «большой»: big).
- Структура полного имени элемента соответствует схеме: имя-блока__имя-элемента. Имя элемента отделяется от имени блока двумя подчеркиваниями (__).
Это сущность, которая определяет какую часть блока занимает HTML-элемент (место расположения, ширину/высоту, расстояние до соседей и так далее)
Для элементов используются свойства, которые определяют их положение в общей сетке блока
Cтили, отвечающие за внешнюю геометрию и позиционирование, задаются через элементы родительского блока.
<section class="article">
<h2 class="article__title">Название новости</h2>
<p class="article__description">Текст новости</p>
</section>
.article {
padding: 10px;
margin: 0;
border: 1px solid #e0e2ec;
}
.article__description {
display: flex;
align-items: center;
margin-bottom: 15px;
}
Cущность, определяющая внешний вид, состояние или поведение блока либо элемента. т.е вариативность блока или элемента. Всегда только внешняя.
Особенности:
- Название модификатора характеризует внешний вид («какой размер?», «какая тема?» и т. п. — «размер»: size_s, «тема»: theme_islands), состояние («чем отличается от прочих?» — «отключен»: disabled, «фокусированный»: focused) и поведение («как ведет себя?», «как взаимодействует с пользователем?» — «направление»: directions_left-top).
- Имя модификатора отделяется от имени блока или элемента дефисами (--).
Блок — это пространство имён, а модификатор задаёт особенности реализации.
Модификатор следует всегда писать как характеристику блока или элемента.
В CSS-правилах для модификаторов мы не можем использовать внешние отступы и вообще любую внешнюю геометрию. Это допустимо делать только через миксование и для элементов!
Cвойства, которые относятся к внешнему виду: цвет текста, цвет фона, размеры шрифта, больше/меньше чем у базового блока/элемента, увеличенные/уменьшенные внутренние отступы и так далее.
Модификация — это изменение изначального состояния. Сначала нужно выяснить, какое состояние — исходное (базовое).
Нельзя использовать больше одного модификатора одного и того же типа (button--size-xl button--size-lg)
Хорошие БЭМ-модификаторы: level, theme, view, size (вроде size-xl, size-xs), direction, type-link, checked, disabled, primary, secondary, active, current, success, danger, warning, info and etc...
extra-small, small, medium, large, extra-large, extra-extra-large (расстояние, отступы)
Пример
- button--success
- button--danger
- button--warning
- button--info
.button{
color: white;
background-color: black;
}
.button--primary {
color: #acacac;
background-color: #4d88ec;
}
.button--secondary {
color: #1c1c1c;
background-color: #9d88ed;
}
.button--rounded-xl{
border-radius: 20px;
}
.article{
}
.article__text{
}
.article--size-xl{
}
.article--size-xl .article__text{
}
.article__text--highlight{
}
<div class="article article--size-xl">
<div class="article__text article__text--highlight"></div>
<div class="article__rating rating"></div>
</div>
Не правильно:
.article--size-xl .rating{
}
Правильно:
.article--size-xl .article__rating{
}
Прием, позволяющий использовать разные БЭМ-сущности на одном DOM-узле.
Один и тот же HTML-элемент может быть БЭМ-блоком и БЭМ-элементом одновременно.
Миксы позволяют:
- совмещать поведение и стили нескольких сущностей без дублирования кода;
- создавать семантически новые компоненты интерфейса на основе имеющихся.
<section class="promo">
<div class="promo__content banner">
<div class="banner__content">
<h2 class="banner__title">Большая <br>распродажа!</h2>
<img class="banner__cover" src="" width="1440" height="800" alt="">
<p class="banner__description">Скидки до 70% на коллекцию демисезонной обуви</p>
<a class="banner__button button button--primary button--size-xl" href="#">Смотреть каталог</a>
</div>
</div>
</section>
- Используйте модификатор, чтобы изменить один конкретный экземпляр блока. Установка и снятие модификатора должны влиять только на изменяемый блок и не иметь отношения к окружающим блокам.
- Используйте микс:
- чтобы позиционировать один блок в составе другого блока;
- чтобы одинаково стилизовать несколько разных блоков на странице вместо применения групповых селекторов.
- Используйте уровни переопределения, чтобы одновременно изменить все одноименные блоки проекта.
- Используйте контекст, чтобы определить стили для блока заранее, когда предварительно неизвестно, какое содержимое будет иметь вложенный блок.
Имя должно быть значащим, уникальным в рамках проекта, исчерпывающим и соответствующим нотации, которой вы придерживаетесь.
Стараемся не использовать такие название блоков:
title, content, section, inner, item and etc
Названия классов, в которых определяется внешний вид сущности:
uppercase, text--center, button--red, background--blue
.button--red{
background-color:red;
}
.button--blue{
background-color:blue;
}
нужно так:
.button--primary{
background-color:red;
}
.button--secondary{
background-color:blue;
}
.button--success{
background-color:blue;
}
Стараться подбирать более универсальные названия.
Имя сущности должно соответствовать её сути.
.card--theme-dark{
color: white;
background-color: black;
width: 350px; -
}
#main {
width: 1200px;
padding: 30px 0;
}
За счёт идентификатора вы указываете уникальное имя для элемента HTML. Это значит, что и стили элемента будут уникальны и переиспользовать их уже не получится.
section {
font-size: 22px;
line-height: 1.5;
font-weight: 500;
}
<section>
<p>.....</p>
</section>
<article>
<p>.....</p>
</article>
Вложенные селекторы увеличивают связность кода и затрудняют повторное использование кода. А еще такие селекторы повышают специфичность правил, и их сложнее переопределить.
.header .logo {
padding-top: 10px;
padding-bottom: 10px;
}
.header__logo {
padding-top: 10px;
padding-bottom: 10px;
}
<div class="header">
<div class="header__logo">
<div class="logo">
<img src="" alt="">
</div>
</div>
</div>
<div class="header">
<div class="header__logo logo">
<img class="logo__img" src="" alt="">
</div>
</div>
Как тогда применять правила каскада? - через модификаторы
(каскадирование - одновременное применение разных стилевых правил к элементам документа)
<div class="card-details">
<dl class="card-details__inner">
<dt class="card-details__item-name">Цвет</dt>
<dd class="card-details__item-value">Красный</dd>
<dd class="card-details__item-value">Синий</dd>
<dt class="card-details__item-name">Размер</dt>
<dd class="card-details__item-value">XXL</dd>
<dt class="card-details__item-name">Бренд</dt>
<dd class="card-details__item-value">Audi</dd>
</dl>
</div>
Гориз. расположение
.card-details__inner{
display: flex;
flex-direction: row;
}
<div class="card-details card-details--vertical">
<dl class="card-details__inner">
<dt class="card-details__item-name">Цвет</dt>
<dd class="card-details__item-value">Красный</dd>
<dd class="card-details__item-value">Синий</dd>
<dt class="card-details__item-name">Размер</dt>
<dd class="card-details__item-value">XXL</dd>
<dt class="card-details__item-name">Бренд</dt>
<dd class="card-details__item-value">Audi</dd>
</dl>
</div>
Верт. расположение
.card-details--vertical .card-details__inner{
flex-direction: column;
}
Исключения:
<div class="user-content">
<p></p>
<ul></ul>
<ol></ol>
</div>
.user-content h2 ..... h6{
....
}
.user-content p {
font-size: 20px;
}
.user-content ul {
font-size: 20px;
}
.user-content ol {
font-size: 20px;
}
.user-content table {
....
}
button.button
h1.h1
.page.current.active
Такие правила становятся более специфичными, а значит, их сложнее переопределить.
<button class="button button--active">Btn</button>
button.button{
background-color: red;
}
.button--active{
background-color: gray;
}
Его специфичность ниже правила с базовыми стилями кнопки.
<ul class="pages">
<li class="page active disabled">1</li>
<li class="page">2</li>
<li class="page">3</li>
</ul>
Cпецифичность селектора выше чем у обычного селектора по классу, его сложнее будет переопределить
.page.active {
background-color: red;
color: white;
}
.disabled {
background-color: gray;
color: red;
}
<ul class="pages">
<li class="page page--active page--disabled">1</li>
<li class="page">2</li>
<li class="page">3</li>
</ul>
.page--active {
background-color: red;
color: white;
}
.page--disabled {
background-color: gray;
color: red;
}
---
.page--disabled {
background-color: gray;
color: red;
}
.page--active {
background-color: red;
color: white;
}
В БЭМ не приветствуется использование в селекторах псевдоклассов.
:first-child, :last-child, :nth-child
БЭМ исходит из максимально возможной независимости от контента, его объёма, наличия либо отсутствия и количества.
<section class="items">
<div class="item">item</div>
<div class="item">item</div>
<aside>ADS</aside>
<div class="item item--last">item</div>
</section>
.item:last-child{
border-bottom: 0;
}
.item--last{
border-bottom: 0;
}
<table class="table table--striped">
<tr class="table__row">
<td class="table__cell">...</td>
<td class="table__cell">...</td>
</tr>
</table>
.table {
background-color: #777777;
}
.table--striped .table__row:nth-child(even) {
background-color: #eeeeee;
}
margin, position и float
Можно:
max-width: 100%, width: 100%, margin: 0, position: relative
Не рекомендуется:
position: absolute, fixed, sticky
Не следует на один и тот же блок навешивать стили, касающиеся всего вообще. Такие блоки ещё называют «жадными».
Это правило поможет нам избавиться от «жадных» блоков, которые хотят управлять всем сразу (декором, сеткой, отступами).
Один и тот же HTML-элемент сразу может быть несколькими БЭМ-блоками.
<section class="product product--full card">
<div class="product__description-column card__description-column offer">
<h2 class="offer__title">Дом как произведение искусства</h2>
<p class="offer__description">Расположенный в самом центре Москвы квартал класса De luxe «Театральный Дом»</p>
<button class="offer__button button button--accent" type="button">Подробнее</button>
</div>
<div class="product__img-column card__img-column">
<img class="product__img" src="img/photo.jpg" width="470" height="332" alt="">
</div>
</section>
<section class="product">
<div class="product__description-column">
</div>
<div class="product__img-column">
<img class="product__img" src="img/photo.jpg" width="470" height="332" alt="">
</div>
</section>
<section class="card">
<div class="card__description-column">
</div>
<div class="card__img-column">
</div>
</section>
<div class="offer">
<h2 class="offer__title">Дом как произведение искусства</h2>
<p class="offer__description">Расположенный в самом центре Москвы квартал класса De luxe «Театральный Дом»</p>
<button class="offer__button button button--accent" type="button">Подробнее</button>
</div>
Лучше использовать больше правил, которые отвечают за что-то одно (разделение ответственности).
У БЭМ нет точных указаний, что будет блоком, а что элементом, это зависит от проекта.
Вопрос, который поможет нам отличить одно от другого: может ли элемент существовать самостоятельно, вне своего родителя? Да — блок, нет (или нет в рамках этого сайта) — элемент.
https://land-book.com/websites/32947-wepresent-unexpected-stories-about-creativity
<div class="slider">
<h2 class="slider__heading">
<span class="slider__heading-sans">...</span>
<span class="slider__heading-serif">...</span>
</h2>
</div>
<div class="article">
<h2 class="article__heading">
<span class="article__heading-sans">...</span>
<span class="article__heading-serif">...</span>
</h2>
</div>
<div class="slider">
<h2 class="slider__heading heading">
<span class="heading__sans">...</span>
<span class="heading__serif">...</span>
</h2>
</div>
<div class="article">
<h2 class="heading">
<span class="heading__sans">...</span>
<span class="heading__serif">...</span>
</h2>
</div>
Блок знает всё о своих элементах, но ему всё равно, что находится во вложенных в него блоках.
Если блок хочет управлять содержимым своих внутренних/вложенных блоков, значит, что-то пошло не так.
Стараемся убирать излишнюю связанность БЭМ-блоков.
Один БЭМ-блок - не должен влиять на другой БЭМ-блок
Не используется межблочный каскад, к примеру, такой:
.menu .logo {
...
}
<nav class="menu">
<a class="menu__logo logo" href="index.html">
<img class="logo__img" src="img/logo.svg" width="120" height="30" alt="">
</a>
</nav>
.menu__logo {
padding-top: 20px;
padding-bottom: 35px;
}
У каждого БЭМ-блока есть свои зоны ответственности, блок не должен хотеть знать о соседних блоках и элементах, нижних или верхних уровнях абстракций дерева вложенности.
По заданным параметрам БЭМ-блок изменяет своё отображение на странице.
Кроме как через модификаторы, больше никак на внутренности блока мы не можем воздействовать.
Если составной блок всё-таки воздействует на стили вложенных блоков, это означает, что композиция составлена неверно. Нужно поделить на блоки по-другому.
Внутренностями вложенного блока мы не можем управлять напрямую, но при этом можем задать дополнительный класс-микс, который повлияет-таки на блок. Примиксовывание класса элемента к вложенному блоку — это такая «модификация» блока извне, о которой блок сам не знает.
Обычная модификация — «внутренняя», о которой блок знает, — это его «внешний интерфейс», «настройки».
Нам нужно весь дизайн декомпозировать в плоское дерево компонентов, где компоненты не зависят друг от друга, а только вкладываются друг в друга.
Зависимые и связанные компоненты — это плохой результат декомпозиции, такого быть не должно.
https://graniteselection.com/msi-quartz-countertops/alabaster-white/
https://www.kalamuna.com/sites/default/files/inline-images/states.png
https://klbtheme.com/furnob/shop/?min_price=660&max_price=4390&shop_view=grid_view
https://tailwindcss.com/docs/reusing-styles
- Простота — низкий порог вхождения в технологию;
- Гибкость — БЭМ-сущности формируются под нужды и специфику проекта. Нет чётких правил, что одни сущности отвечают только за сетки, а другие — только за темы;
- Независимость — компоненты создаются так, чтобы их можно было легко переносить из проекта в проект без каких-либо доработок;
- Командная разработка интерфейса — монолит макета делится на независимые блоки, которые разрабатываются отдельными участниками команды;
- Понятность (человекочитаемость) — вопрос больших проектов, структура проекта прозрачна, всё что относится к блоку/компоненту собрано внутри одной папки;
- Меньше конфликтов при определении стилей для элемента — имена классов уникальные и не повторяются. Перебивать вес селекторов не нужно. Как правило, достаточно сделать модификатор (возможно, придётся использовать флаг !important только для внешних библиотек, чтобы перебить правило, которое мы не имеем права переписывать);
- Помогает сформировать компонентное мышление.
- Увеличение объёма файлов со стилями;
- Дублирование css стилей;
- Нужно придумывать название классов;
- Проработать композицию.
https://developer.mozilla.org/ru/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance
https://nicothin.pro/idiomatic-pre-CSS/