Правильный CSS: OOCSS, SMACSS, BEM и SASS
Правильный CSS: OOCSS, SMACSS, BEM и SASS
Перепечатал тут статью, которая канула в Лету.
- 03 Dec 14
- Верстка
Многие девелоперы, даже имея за плечами не один успешно выполненный коммерческий проект не оставляют поиски наилучшего способа организации стилей в макете. И большинство из них остановились на синтезе OOCSS, SMACSS, BEM и SASS. В этой статье мы не только поговорим о том, что из себя представляет правильный CSS: союз OOCSS, SMACSS, BEM и SASS, но и рассмотрим наиболее эффективную структуру организации файлов в макете.
Для начала вспомним, что из себя представляет каждая из трех методологий объектно-ориентированного CSS.
OOCSS + SCSS
Принцип OOCSS заключается в раздельном существовании объекта и его модификаций. Это нужно для того, чтобы мы могли поместить клон объекта в любое место на сайте без необходимости перебивать существующие стили.
Клон объекта через новый класс расширяется дополнительными стилями (дизайном). Таким образом, в html документе к одному блоку присваивается сразу несколько классов. Нанизывание классов характерно для многих фреймворков, например Bootstrap.
Однако множественность классов идет вразрез с принципами SMACSS, который рекомендует избегать повторений. Это один из главных принципов написания «чистого кода».
На помощь приходит SASS, а именно директивы
@include и @extend. С их помощью к любому блоку можно присоединять дополнительные стили минуя html.
С помощью строки
@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 и организовать файловую структуру макета самым эффективным для вас образом. Удачных и прибыльных сайтов!