Skip to content

Latest commit

 

History

History
740 lines (532 loc) · 27.1 KB

2.bem.md

File metadata and controls

740 lines (532 loc) · 27.1 KB

БЭМ

это система «Блок — Элемент — Модификатор».

Это один из подходов к компонентной вёрстке

Это такой подход к вёрстке, когда отдельные компоненты сайта создаются изолированно и могут использоваться в любом месте, вне зависимости от окружения и содержания.

Задача верстальщикка в контексте БЕМ, определить, какие элементы интерфейса — независимые блоки, а какие — их элементы. Что будет базовым представлением блока, а что его модификацией.

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

Правила:

Правило 1. Не использовать селектор по идентификатору

#main {
  width: 1200px;
  padding: 30px 0;
}

За счёт идентификатора вы указываете уникальное имя для элемента HTML. Это значит, что и стили элемента будут уникальны и переиспользовать их уже не получится.

Правило 2. Не использовать селектор по тегу

section {
  font-size: 22px;
  line-height: 1.5;
  font-weight: 500;
}
<section>
	<p>.....</p>
</section>
<article>
	<p>.....</p>
</article>

Правило 3. Стараться не использовать вложенные селекторы

Вложенные селекторы увеличивают связность кода и затрудняют повторное использование кода. А еще такие селекторы повышают специфичность правил, и их сложнее переопределить.

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

Правило 4. Не использовать комбинацию селекторов

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

Правило 5. Псевдоклассы

В БЭМ не приветствуется использование в селекторах псевдоклассов.

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

Правило 6. Не задавать внешнюю геометрию блокам

margin, position и float

Можно:

max-width: 100%, width: 100%, margin: 0, position: relative

Не рекомендуется:

position: absolute, fixed, sticky

Правило 7. Не стараться определить все стили в одном CSS правиле (шрифты, сетка, декор, отступы)

Не следует на один и тот же блок навешивать стили, касающиеся всего вообще. Такие блоки ещё называют «жадными».

Правило 8. Используем композицию вместо наследования.

Это правило поможет нам избавиться от «жадных» блоков, которые хотят управлять всем сразу (декором, сеткой, отступами).

Один и тот же 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>

Лучше использовать больше правил, которые отвечают за что-то одно (разделение ответственности).

Правило 9: Лучше перемельчить, чем недомельчить. Когда перестать мельчить, зависит от проекта.

У БЭМ нет точных указаний, что будет блоком, а что элементом, это зависит от проекта.

Вопрос, который поможет нам отличить одно от другого: может ли элемент существовать самостоятельно, вне своего родителя? Да — блок, нет (или нет в рамках этого сайта) — элемент.

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>

Правило 9

Блок знает всё о своих элементах, но ему всё равно, что находится во вложенных в него блоках.

Если блок хочет управлять содержимым своих внутренних/вложенных блоков, значит, что-то пошло не так.

Стараемся убирать излишнюю связанность БЭМ-блоков.

Один БЭМ-блок - не должен влиять на другой БЭМ-блок

Не используется межблочный каскад, к примеру, такой:

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

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://htmlacademy.ru/

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/

https://yoksel.github.io/html-tree/en/

https://ru.bem.info/methodology/quick-start/