Правильный CSS: OOCSS, SMACSS, BEM и SASS

Перепечатал тут статью, которая канула в Лету.

Правильный CSS: OOCSS, SMACSS, BEM и SASS

Перепечатал тут статью, которая канула в Лету.

Многие девелоперы, даже имея за плечами не один успешно выполненный коммерческий проект не оставляют поиски наилучшего способа организации стилей в макете. И большинство из них остановились на синтезе OOCSS, SMACSS, BEM и SASS. В этой статье мы не только поговорим о том, что из себя представляет правильный CSS: союз OOCSS, SMACSS, BEM и SASS, но и рассмотрим наиболее эффективную структуру организации файлов в макете.

Для начала вспомним, что из себя представляет каждая из трех методологий объектно-ориентированного CSS.

OOCSS + SCSS

Принцип OOCSS заключается в раздельном существовании объекта и его модификаций. Это нужно для того, чтобы мы могли поместить клон объекта в любое место на сайте без необходимости перебивать существующие стили.

Клон объекта через новый класс расширяется дополнительными стилями (дизайном). Таким образом, в html документе к одному блоку присваивается сразу несколько классов. Нанизывание классов характерно для многих фреймворков, например Bootstrap.

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

На помощь приходит SASS, а именно директивы
 @include и @extend. С их помощью к любому блоку можно присоединять дополнительные стили минуя html.

DEMO

С помощью строки

@extend .button;

мы расширяем классы blue и red стилями из класса button:.

<h2>SASS  @extend</h2>
<div class="wrapper">
<a href="#" class="blue">Linkedin</a>
<a href="#" class="red">Myspace</a>
</div>

/*SASS @extend - button записывается в CSS*/

.button
border:2px solid gray;
padding:5px 15px;
border-radius:5px;
color:white;
font-weight:bold;
.blue
@extend .button;
background:blue;
.red
@extend .button;
background:red;

При компиляции SCSS мы получаем такую запись в CSS:

.button, .blue, .red 
border:2px solid gray;
padding:5px 15px;
border-radius:5px;
color:white;
font-weight:bold;
.blue
background:blue;
.red
background:red;

Это полностью совпадает с принципами OOCSS, которые настоятельно рекомендует соблюдать его создатель Jonathan Snook. НО! Стили для класса button также записываются в CSS. И в данном случае совершенно напрасно, они нам не нужны. Так очень часто бывает в макете, когда базовый дизайн не применяется.

В таком случае лучше воспользоваться директивой Placeholder Selectors (%). Placeholder записывается в CSS ТОЛЬКО! когда его вызовут:

@extend %button;
<h2>SASS %placeholder selector</h2>
<div class="wrapper">
<a href="#" class="yellow">Linkedin</a>
<a href="#" class="pink">Myspace</a>
</div>

/*SASS %placeholder selector - %button НЕ записывается в css*/

%button
border:2px solid gray;
padding:5px 15px;
border-radius:5px;
color:gray;
font-weight:bold;
.yellow
@extend %button;
background:yellow;
.pink
@extend %button;
background:pink;

Однако в таком случае в скомпилированном CSS одни и те же стили будут повторяться в каждом классе.

.yellow 
border:2px solid gray;
padding:5px 15px;
border-radius:5px;
color:gray;
font-weight:bold;
background:yellow;
.pink
border:2px solid gray;
padding:5px 15px;
border-radius:5px;
color:gray;
font-weight:bold;
background:pink;

То же самое произойдет и в случае использования директивы @mixin. Однако при использовании mixin мы получаем определенное преимущество.

Переменные, определенные в mixin, можно изменить один раз и они изменятся во всем макете сразу. Это экономит массу времени и сил. Кроме того, используя миксин, можно в блоке менять значения переменных, если того требует дизайн (смотрите демо).

<h2>SASS  @mixin</h2>
<div class="wrapper">
<a href="#" class="gray">Linkedin</a>
<a href="#" class="green">Myspace</a>
</div>

/*SASS @mixin. Не записывается в CSS.
Предназначен для использования переменных
типа $padding-vertical:15px;*/

@mixin button $padding-vertical, $padding-horizontal, $border-radius
border:2px solid gray;
padding: $padding-vertical $padding-horizontal;
border-radius:$border-radius;
color:white;
font-weight:bold;
.gray
@include button5px, 15px, 5px;
background:gray;
.green
@include button5px, 15px, 5px;
background:green;

SASS позволяет избежать лишних классов в макете благодаря вложенности. Однако иногда вложенность играет с нами злую шутку и к блоку применяется большое наследование, типа

#header .main-line .state.state-on

И здесь пришло время обратиться к методологии BEM, разработанной компанией Yandex. Она определяет принцип создания имен классов для элементов различного уровня и их состояний.

В статье мы будем рассматривать не оригинальный BEM, а версию Nicolas Gallagher, которой все предпочитают пользоваться, потому, что она намного прозрачнее.

Вкратце, что она из себя представляет правильный CSS на BEM.

.block 
.block__element
.block--modifier

.block — стиль для родительского блока
 .block__element — стиль для вложенного дочернего блока.
 .blockmodifier — стиль состояния блока.

Возможны различные версии.

У дочернего блока может быть стиль состояния:

person__hand--left

У стиля состояния может быть дочерний блок:

person--female__hand

По отзывам девелоперов, ее протестировавших, методология BEM несколько уродлива в написании и запутанна в сфере применения.

Например, создатель csswizardry.com Harry Robertsприводит пример:

<div class="content">
<h1 class="content__headline">Lorem ipsum dolor...</h1>
</div>

Нижнее подчеркивание говорит о принадлежности h1 к дочернему элементу. Однако Harry подчеркивает, что не уверен, всегда ли класс для h1 в данном случае следует писать таким образом.

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

Как бы то ни было, BEM прекрасно решает проблему с наследованием в SASS. И хотя бы одним этим он может быть нам полезен, чтобы написать правильный CSS.

В SASS мы пишем:

.div 
color: red;

.colored
color: black;

В скомпилированном CSS получается:

.div {
color: red;
}
.div .colored {
color: black;
}

Наследование очевидно.

Sass 3.3+ BEM делает возможным следующую комбинацию:

.div 
color: red;

&__colored
color: black;

В скомпилированном CSS получается:

.div {
color: red;
}
.div__colored {
color: black;
}

Наследованию конец, генерируется только один класс!

Организация файловой структуры

А теперь поговорим об организации файловой структуры макета на SASS. Изучая опыт ведущих зарубежных девелоперов и их макеты, а также используя собственные скромные познания, мною был сделан следующий вывод об оптимальной структуре макета:

main.scss

Чаще всего это style.css, но здесь во мне говорит привычка делать макеты на html5 boilerplate. Основной файл макета, куда импортируются все остальные его части (см. ниже)

_base.scss

Включает в себя normalize.css и стили для базовых элементов сайта: html, body, a, ul, li и так далее.

_gride.scss

Если вы пользуетесь собственной сеткой или переопределяете готовые фреймворки. Соответственно сюда импортированы папки _mixins, _variables.scss и пр.

_layout.scss

Стили для объектов.

_modules.scss

Все модули с комментариями. Модули отделены от объектов, как и рекомендует SMACSS. Некоторые девелоперы рекомендуют собрать все модули в один файл и сделать навигацию по комментариям.

Мне же больше близок подход SMACSS, где предлагается рассортировать все по папкам. Я предпочитаю сохранить каждый модуль в отдельном файле и затем импортировать в _modules.scss. Так удобнее редактировать. Также считают и создатели SCSS Bootstrap.

_other.scss

Все, что не вошло в обозначенные выше папки.

_shame.scss

Фиксы

Надеюсь, что данная статья поможет вам написать правильный CSS и организовать файловую структуру макета самым эффективным для вас образом. Удачных и прибыльных сайтов!