В начале 2013 года синтаксис «Блок, Элемент, Модификатор» (БЭМ), применяемый к
CSS, стал крайне популярной методологией организации кода, добавляющей
определенное единообразие в проекты. Если брать в целом, то я просто обожаю
БЭМ. Он действительно хорошо структурирован, и для меня это важно.
Единственное, что меня волновало все это время, да и не только меня, но и
большинство моих коллег разработчиков — это то, насколько длинными и
избыточными становились значения атрибута class
у элементов. Особенно, когда
дело доходило до модификаторов.
<button class="button button--green button--rounded button--large">
Мне действительно нравится наглядная запись вида элемент--модификатор
. Она
помогает понять, что класс предназначен только для расширения каких-либо
свойств элемента. Однако, зачастую дублирование названия элемента является
избыточным. Мы можем избежать этого, визуально отделив модификаторы,
путем добавления их к элементам непосредственно в самих таблицах стилей. И при
этом мы сохраним дефис в начале имени класса, чтобы показать, что он является
модификатором.
HTML
<button class="button -green -rounded -large">
SCSS
.button {
&.-green {...}
&.-rounded {...}
&.-large {...}
}
Такой ход обеспечивает наглядное отделение элементов и модификаторов, позволяя при этом избегать повторения в имени класса. И да, использование дефиса в качестве первого символа в селекторе валидно, а вот использование двойного дефиса — нет. Если вас действительно беспокоят селекторы по нескольким классам, то возможно, что у вас просто остались плохие воспоминания об ужасах времен IE6. Но, поверьте, вам больше действительно не стоит о нём беспокоиться.
Дополнительная специфичность, возникающая при таком подходе, казалось бы, также может являться проблемой. Тем не менее, лично я ее таковой не считаю, хотя и представляю ситуацию, в которой у вас есть несколько глобальных переопределяющих правил, которые вы хотели бы применять к любому элементу. В этом случае вам необходимо сделать что-то в таком духе:
SCSS
.button {
&.-hoverable {
&:hover {
opacity: 0.75;
}
}
}
.overrides {
&.-disabled {
opacity: 0.25;
}
}
HTML
<button class="button -hoverable overrides -disabled">Disabled</button>
Пример конечно же выдуманный, но я думаю, что вы уловили смысл. При наведении
курсора на кнопку ее прозрачность не изменяется, потому что свойства,
определенные для селектора .button.-hoverable
, перекрывается другими
свойствами, указанными для селектора .overrides.-disabled
, обладающего той
же специфичностью, но определенного в таблице позже.
Гибкость использования модификаторов в разметке — это круто, но когда я замечаю часто повторяющиеся группы свойств, я предпочитаю комбинировать их в моей таблице стилей. Директива @extend в Sass отлично подходит для этого.
SCSS
.button--save {
@extend %button;
@extend %button--large;
@extend %button--rounded;
@extend %button--green;
}
HTML
<button class="button--save">Save</button>
Весьма наглядно. В этом примере вы должны обратить свое внимание на следующее:
- я использую селектор-плейсхолдер % в Sass;
- и я все еще использую обычный синтаксис БЭМ
элемент--модификатор
.
Сначала я определяю все свои стили для селектора-плейсхолдера, и таким образом, я могу расширить их для других классов с помощью директивы @extend.
%button {
background: #45beff;
border: none;
padding: 1em 2em;
font-size: 16px;
&:hover {
opacity: 0.75;
}
}
%button--green {
background: #3efa95;
}
%button--red {
background: #ff3a6a;
}
%button--large {
font-size:20px;
}
%button--rounded {
border-radius: 10px;
}
Теперь я могу собрать все стили для элемента, добавляя модификаторы, которые я планирую использовать в разметке, а также создавать вариации, которые можно использовать повторно и расширять за счет сочетания модификаторов.
.button {
@extend %button;
&.-green {
@extend %button--green;
}
&.-large {
@extend %button--large;
}
}
.button--delete {
@extend %button;
@extend %button--large;
@extend %button--rounded;
@extend %button--red;
}
После всего, что сказано и сделано выше, паттерн БЭМ
блок__элемент--модификатор
для меня трансформировался во что-то более
похожее на блок__элемент--вариация -модификатор
(БЭВМ), дополненный
внутренними Sass-селекторами вида %модификатор
.
// Внутренний модификатор
%button--red {
background: #ff3a6a;
}
// Элемент
.button {
// Модификатор
&.-red {
@extend %button--red;
}
}
// Вариация
.button--delete {
@extend %button;
@extend %button--red;
}
Мне все это нравится, а что думаете вы? Удобно? Странно? Давайте обсудим!