От автора: люди любят давать названия различным вещам, а разработчики обожают сокращения. И вот мы здесь, и перед нами все эти правила именования и методики CSS: BEM, SMACSS, PointNorth, ITCSS, OOCSS, Title CSS, Idiomatic CSS, AtomicDesign, SUIT CSS, Kickoff CSS,и т.д.
Нас часто спрашивают «Ты пользуешься OOCSS или BEM ?», но эти подходы не исключают друг друга. На самом деле в большинстве случаев мы берем концепции и идеи вышеупомянутых методик и перемешиваем их, подстраивая их под наши конкретные нужды.
Итак, чем же я пользуюсь на данный момент? И это атомный OOBEMITSCSS. Ага. Атомный OOBEMITSCSS. Впервые я услышала этот нелепый термин из твита DanEden.
Я уверена, он даже и не помнит об этой шутке. Но чем больше я об этом думала, тем больше понимала, что это была не шутка. И с тех пор это не выходило у меня из головы. OOBEMITSCSS — точно то, что мы стали применять. Звучит дико, но в этом есть смысл, если разобраться.
Атомный CSS
Начнем, пожалуй, с AtomicDesign. AtomicDesign представляет собой метод системного мышления, придуманный Brad Frost. Во время исследования данного метода и поисков того, как он относится к стилям, я наткнулась на эту статью по теме AtomicSass. Я не использую описанную в той статье структуру каталогов, но активно применяю понятия и идеи, выраженные Брэдом в AtomicDesign, в проектировании, а также переношу эти идеи в разработку (посредством Sass модулей и компонентов).
Смысл данного подхода, в основном, в дизайне и разработке с точки зрения системного мышления – создать отдельные «молекулы» или элементы, при соединении которых образуется «паутина» модулей, компонентов и в конечном итоге целых систем верстки сайта (Официально, существует 5 компонентов: атомы, молекулы, организмы, шаблоны и страницы). Увидеть о чем идет речь можно в примере ниже. Вот пример с моей стены в Pinterest:
На картинке мы видим карточку, состоящую из нескольких атомов:
Подпись к фото
Текст заголовка (тип пина)
Основной текст (заголовок)
Выносной текст (сообщение)
Выносной текст (Заголовок)
Выносное изображение (мини стена)
Иконки источника
Стандартные иконки
Статистика в числах
Основное изображение
Разделители
Все вместе они создают молекулы:
Изображение и цитата (основное изображение + иконка источника + подпись к фото)
Метаданные пина (текст типа пина + hr + основной текст + [стандартные иконки + числовая статистика] х2)
Выноска (выносное изображение + выносной текст (сообщение) + выносной текст (заголовок))
Эти молекулы соединяются в организм или нашу карточку: (Изображение и цитата) + (Метаданные пина) + разделители + (Выноска)
Домашняя страница Pinterest полна таких организмов. Они являются составной частью верстки домашней страницы сайта:
Эти элементы повторно используются и перемешиваются в других местах на сайте:
На рисунке выше изображено модальное окно просмотра пина (которое отображается при клике на кнопку «Pinit»). Мы видим все ту же числовую статистику по данному пину так же, как и на домашней странице, только без дополнительной выноски снизу. Все это размещено уже в другом контексте.
Данное окно отображается по клику на само изображение. Обратите внимание на то, как одна и та же информация о «типе» пина и иконка источника следуют по обоим шаблонам на этом сайте. Мышление по методике AtomicDesign позволяет нам создавать модульные, унифицированные системы дизайна.
BEM
Я использую BEM для разметки. BEM расшифровывается как Блок, Элемент, Модификатор. Он особенно полезен в большой команде. В такой, где я сейчас работаю – IBM. Я написала статью об этой методике, но чуть позже была опубликована статья лучше моей (Не могу поверить, это было в 2013 году!). Давайте еще раз взглянем на наш пример с карточкой:
Как нам разметить эту карточку? Сначала мы разделим разметку на ее атомные составляющие. Это означает, что мы начнем с самых базовых элементов и будем расширять разметку. Изолируем небольшой участок и изучим его разметку. (обратите внимание: Я намеренно не обращаю внимания на ссылки и взаимодействие с ними в этом примере, но по идее должна.Атомная разметка позволяет повторно использовать куски кода, где бы мы не создали компонент. Т.е. по клику на сердечко его стили всегда будут меняться, такие как цвет заливки и увеличение счетчика лайков)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<divclass="card"> <img src="..." alt="..." class="card__source-icon"> <a href="" class="card__source-link"></a> <section class="card__metadata"> <h2 class="metadata__pin-type"></h2> <hr> <p class="metadata__caption"></p> <span class="metadata__pins"></span> <span class="metadata__hearts"></span> </section> <hr> <section class="card__callout"> <img src="..." alt="..." class="callout__board-preview"> <p class="callout__msg"></p> <a href="..." class="callout__board-title"></a> </section> </div> |
У классов семантические имена, описывающие контент, а также они разбиты на молекулы. Эти молекулы в BEM будут представлять из себя блоки. В примере выше у нас нет модификаторов, но если мы захотим отделить метаданные лайков (т.е. сделать кликабельным только сердечко), к примеру (обычно я использую псевдоклассы для иконок), мы можем сделать это так:
1 2 3 4 |
<div class="metadata__hearts"> <a href="..." class="metadata__hearts--icon"></a> <p class="metadata__hearts--count"></p> </div> |
Некоторые спорят, что такой подход увеличивает длину селекторов в CSS (да увеличивает), но семантически это придает огромный смысл и реально очищает разметку, ограничивая количество используемых классов. И, продолжая тему ограничения классов, хочу сказать, используйте по возможности **один класс на элемент**. Честно говоря, я считаю BEM бесценным инструментом при работе в команде, а также он отлично подходит при работе в объектно-ориентированной манере.
OOCSS
OOCSS переводится как Объектно-ориентированный CSS. От Nicole Sullivan с GitHub:
«В принципе «объект CSS» это повторение визуального шаблона, который может быть абстрагирован в кусочек кода HTML, CSS и возможно JavaScript. Данный объект можно потом повторно использовать в любом месте на сайте».
В примерах Николь с ГитХаба используется множество классов для достижения этого формата, но на этом этапе вы можете подумать: «Стойте, разве это не противоречит BEM?». Нет. И не может. Чтобы все сделать по канону мы используем Sass. Так что это уже в меньшей степени OOCSS и в большей OOSCSS!
Мне нравится думать о том, как я пишу Sass код объектно-ориентированно. Если представить, что наша карточка это объект, который притягивает к себе различные классы, то мы все еще можем сохранить старую вложенность тегов красиво и аккуратно с помощью всемогущего амперсанда (если вы читали хоть одну из моих предыдущих статей, то вы знаете, как сильно я люблю амперсанд).
А теперь пример! Возьмем нашу секцию метаданных, это хороший пример сложностей работы со скрытыми данными:
1 2 3 4 5 6 7 |
<section class="card__metadata"> <h2 class="metadata__pin-type"></h2> <hr> <p class="metadata__caption"></p> <span class="metadata__pins"></span> <span class="metadata__hearts"></span> </section> |
Мы же хотим мыслить модульно и объектно-ориентированно. Иконки отличный пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
%icon{ content: ''; display: block; &--pins { @extend%icon; background-image: url('../img/pins.svg'); } &--heart { @extend%icon; background-image: url('../img/heart.svg'); } } |
Что здесь происходит? А) Как я сказала выше, я злоупотребляю амперсандами, убедитесь, что вы знакомы с ними. В) Мы создаем невидимый селектор (или селектор плэйсхолдер) в Sass. Это значит, что этот код не будет обработан в CSS, пока мы не @extend его. Все наши иконки имеют парочку общих свойств (в этом примере content:’’ и display:block). Затем для каждой иконки мы устанавливаем background-image во время *расширения* стилизуемой формы от родительского блока. Это можно сделать с помощью цикла @each, и для большей чистоты иконки будут представлены в виде карты. На этом этапе ничего не выводится на экран, но технически это то, что происходит за кадром.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
%icon, %icon--pins, %icon--heart { content: '; display: block; } %icon--pins { background-image: url('../img/pins.svg'); } %icon--heart { background-image: url('../img/heart.svg'); } |
Продолжаем, давайте взглянем на то, как выглядят блоки, если применить объектно-ориентированный Sass.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
%font-stack--body { // Pinterestсемейство шрифтов(!) font-family: 'Helvetica Neue','Helvetica','ヒラギノ角ゴ Pro W3','Hiragino Kaku Gothic Pro','メイリオ','Meiryo','MSPゴシック',arial,sans-serif; } %font-stack--headers { @extend%font-stack--body; font-weight: 600; //заголовки имеют тот же шрифт, что и весь другой текст, //только вес больше } %type--base-body { @extend%font-stack--body; //расширяем бодистэк } %type--base-h2 { @extend%font-stack--headers; //расширяем заголовки (которые расширяют боди//стэк и дают шрифтам больший вес) font-size: 1.5em; //font-size adjustment } |
А теперь к молекулам! И тут становится действительно интересно:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
.metadata { &__pin-type { @extend%type--base-h2; //расширяем базовые стили заголовков } &__caption { @extend%type--base-body; //расширяемосновной текст } &__hearts { &:hover { color: red; //уникальный цвет при наведении } &:after { @extend%icon--heart; // расширяем иконку лайка с помощью псевдокласса } } &__pins { &:hover { color: green; //уникальный цвет при наведении } &:after { @extend%icon--pins; // расширяем иконку лайка с помощью псевдокласса } } } |
На что похож этот CSS? Несмотря на всю вложенность, на выходе у нас всего один класс!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
.metadata__pins:after, .metadata__hearts:after { content: '; display: block; } .metadata__pins:after { background-image: url('../img/pins.svg'); } .metadata__hearts:after { background-image: url('../img/heart.svg'); } .metadata__pin-type, .metadata__caption { font-family: 'Helvetica Neue','Helvetica','ヒラギノ角ゴ Pro W3','Hiragino Kaku Gothic Pro','メイリオ','Meiryo','MSPゴシック',arial,sans-serif; } .metadata__pin-type { font-weight: 600; } .metadata__pin-type { font-size: 1.5em; } .metadata__hearts:hover { color: red; } .metadata__pins:hover { color: green; } |
Белиссимо!
ITCSS
ОК, здесь мы соберем все мысли вместе. Мы почти у финишной черты! А теперь обсудим ITCSS. Прежде всего, что такое ITCSS? Приставка IT (лол) означает то, каким образом пометить ваши стили, как свои. А также приставка IT отвечает на вопрос о том, в каком порядке мне применять мои стили?
Ниже представлен отличный график, украденный прямо из блога HarryRobertsиз статьи Specificity Graph (простите, надеюсь, вы не возражаете!).
По существу. Вот так выглядит график объявлений (возможно):
А так ваш график объявлений «должен» выглядеть
График объявлений это анализ вашего CSS кода на объявления новых селекторов. При использовании !important и повторении кода создаются эти ужасные пики. В результате вам необходимо переопределять селектор еще раз, чтобы отменить предыдущее переопределение. Теперь видите, почему это так проблематично? Не только потому, что это несемантический подход и слишком запутанно, но также это заставляет вас писать менее производительный код. Кроме того увеличивается вес файла стилей из-за всех этих переопределений. Вес вашего файла стилей можно представить, как область под графиком.
Вы спросите как? В примере выше мы видим, что сначала применяются базовые стили, и только потом применяются определенные стили в зависимости от нужд к элементам или модификаторам. В противном случае, мы расширяем стили из существующего кода, который был создан ранее в потоке стилей. Такой подход помогает организовать модульность стилей, а также импортировать первые пару стилей в качестве помощников или переменных, которые не отображаются в CSS (как селекторы плэйсхолдеры для иконок и шрифтов). Я могла бы (и написала) написать целые статьи на эту тему (а также я создала инструментарий, отмечающий ваше авторство архитектуры стилей, который заставляет планировать маршрут написания стилей, прежде чем с головой погрузиться в код).
Ну и вот ваш Атомный OOBEMITSCSS.
Автор: Una Kravets
Источник: //www.sitepoint.com/
Редакция: Команда webformyself.