Чуть больше Sass для (БЭ)Модификаторов

В начале 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, обладающего той же специфичностью, но определенного в таблице позже.

Сохраненные вариации: расширение с помощью Sass

Гибкость использования модификаторов в разметке — это круто, но когда я замечаю часто повторяющиеся группы свойств, я предпочитаю комбинировать их в моей таблице стилей. Директива @extend в Sass отлично подходит для этого.

SCSS

.button--save {
	@extend %button;
	@extend %button--large;
	@extend %button--rounded;
	@extend %button--green;
}	

HTML

<button class="button--save">Save</button>	

Весьма наглядно. В этом примере вы должны обратить свое внимание на следующее:

  1. я использую селектор-плейсхолдер % в Sass;
  2. и я все еще использую обычный синтаксис БЭМ элемент--модификатор.

Сначала я определяю все свои стили для селектора-плейсхолдера, и таким образом, я могу расширить их для других классов с помощью директивы @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;
}

Посмотреть пример на CodePen.

От БЭМ к БЭВМ?

После всего, что сказано и сделано выше, паттерн БЭМ блок__элемент--модификатор для меня трансформировался во что-то более похожее на блок__элемент--вариация -модификатор (БЭВМ), дополненный внутренними Sass-селекторами вида %модификатор.

// Внутренний модификатор
%button--red {
	background: #ff3a6a;
}

// Элемент
.button {
	// Модификатор
	&.-red {
		@extend %button--red;
	}
}

// Вариация
.button--delete {
	@extend %button;
	@extend %button--red;
}

Мне все это нравится, а что думаете вы? Удобно? Странно? Давайте обсудим!