В чем заключается вопрос?


Всем привет, сегодня я хочу поделиться с вами личным опытом написания стилей или проще говоря выложить свое видение на проблему написания css для сайтов.

Казалось бы в век развития технологий, когда каждый день мы сталкиваемся с новыми и новыми фреймворками, препроцессорами, шаблонизаторами и прочими вещами проблем вообще возникать не должно. Умные разработчики придумали кучу крутых «фич» для удобства создания мощных и расширяемых сайтов. Но как эти инструменты правильно использовать в CSS? И в чем возникают трудности?

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

Суровая реальность


Ни для кого не будет секретом, что начинающим и опытным frontend разработчикам часто передают уже готовые проекты в которых нужно внести правки, переделать дизайн и так далее. В моей практике таких задач было не мало, когда ты работаешь с чужим кодом, в который нужно вникнуть и понять. И если вам в руки попал уже готовый сайт, открыв таблицу стилей будьте готовы увидеть несколько тысяч строк кода.

Вы конечно как опытный разработчик откроете его в каком-нибудь IDE, по типу Visual Studio Code и легким взмахом руки через функцию поиска и замены легко сможете найти и переписать любой класс.

Но если нужно внести приличное количество правок, интегрировав туда часть нового дизайна для каких-то секций, сколько вы потратите на это времени?

Я думаю что много. Да и все что вы сделаете будет мягко говоря «бесполезно». Представьте себе ситуацию когда переделанный вами такой сайт передают другому разработчику или через некоторое время вам говорят внести еще туда новые правки.

SASS решит наши проблемы


Переварив всю эту информацию типичный веб-разработчик скажет что вот он выход из ситуации: использовать препроцессоры CSS. Там и модульность и комфорт и все.

Конечно! Но любой инструмент в руках не опытного программиста теряет всякий смысл. Порой открываешь стили сайта и вот, заветная папка c названием «sass». Ожидая чуда чаще всего ты получаешь только разочарования.

Разбивка стилей на отдельные файлы: header.sass, main.sass, animation.sass и т.д. Как же это «гениально». И не эффективно. Открывая очередной такой файл ты сталкиваешься с той же кучей строк стилей.

Какие же есть альтернативы?


О том как разработчики называют свои классы лучше иногда умолчать, как и о цепочках вложенности стилей. Я думаю каждый кто крутиться в этой сфере хоть что-то слышал о БЭМе и понимает важность правильного именования классов. С этого и стоит начать решать все проблемы.

Я предлагаю вам особый подход, особую методологию разработки ваших стилей, но не без помощи препроцессоров. Есть несколько этапов внедрения этой методологии:

  • Первый, как Вы уже поняли это правильное именование ваших классов.
  • Второй, это избавиться от вложенности стилей. Здесь нам поможет именно БЭМ методология. Ознакомившись с основами этой замечательной документации можно приступать к следующему.
  • SASS — без этого инструмента никак. Именно он залог модульности и мощности вашего проекта.
  • Сборка проекта. Я думаю Вы много слышали о современных сборщиках (информации по сборке проекта в интернете очень много). Здесь нам поможет Gulp.

Теперь вы готовы.

А теперь по сути


В современной интерпретации frontend`а можно найти не мало javascript фреймворков. Большинство из них разделяют сайт на меньшие части, компоненты. Я предлагаю вам сделать то же самое, когда вы думаете как написать стили. Каждая кнопка, элемент меню, красивая ссылка, картинка и даже обычный текст может быть компонентом.

image

Например, на этой форме входа на сайт мы можем выделить несколько компонентов:

  1. Саму форму входа
  2. Поля ввода input`ы
  3. Кнопку отправки
  4. Чекбокс

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

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

Внутренности компонента


Как я уже сказал кнопок на сайте может быть много, с разными цветами, разными внутренними отступами, все это являет собой данные и очень умно отделить эти данные от стилей. Что я и предлагаю сделать.

Каждый компонент я предлагаю представить в виде трех сущностей: vars, maker и creater. Простым языком, это данные, создатель действий(методы управления этими данными) и создатель стилей. Теперь обо всем по порядку.

  • Данные или vars. Сюда входят: цвет текста кнопки, цвет заднего фона кнопки, padding, border-radius, размер шрифта и т.д. Все эти данные записаны в виде переменных или ассоциативного массива в отдельном файле.
  • Создатель действия или maker. Содержит в себе различные функции или миксины которые в качестве аргументов будут принимать данные и генерировать с них стили.
  • Создатель стилей или creater. Собственно здесь мы импортируем себе данные и методы и связываем их друг с другом так как нам нужно.

Ниже показано схематически взаимодействие всех трех сущностей.

image

Сложно все это вложить в голову? Рассмотрим пример создания базового компонента кнопка — «button». В качестве препроцессора будем использовать SCSS.

Как вы уже поняли в новой папке «button» создаем три файла: _vars.scss, _creater.scss, _maker.scss.

_vars.scss

$button_size:(
    sm:5px 20px,
    md:15px 20px
);
$button_color:(
   white:#ffffff
);
$button_back:(
    blue: #00e5e5
);
/* This is component config, it must be below other variables */
$button_config:(
    padding:$button_size,
    color:$button_color,
    background:$button_back
);

Как мы видим данные представлены в виде ассоциативного массива. Все отдельные стили включены в главный набор button_config. Для того чтоб создать новые стили разработчику нужно всего лишь создать новый массив, наполнив его нужными значениями и подключить его в button_config.

_creater.scss:

@import "vars";
@import "maker";

.button{
   @include InitialComponent($button_config);
}

Здесь мы импортируем данные и создателя действий. Потом через миксин InitialComponent который прописан в maker мы инициализируем все стили передавая переменную button_config. И вот магия. Все нужные классы созданы в соответствии с БЄМ неймингом.

Результатом выполнения будут стили:

.button_padding_sm {
  padding: 5px 20px; 
}

.button_padding_md {
  padding: 15px 20px;
 }

.button_color_white {
  color: #ffffff;
 }

.button_background_blue {
  background: #00e5e5;
 }

И в чем же здесь успех?


Преимущество такого подхода ощущаешь не сразу. Но по мере того как растет проект понимаешь все удобство такой методологии. Если нужно изменить цвет нескольких кнопок на разных страничках, не нужно искать классы в кучи стилей. Все что нужно — это открыть папку button и соответственно файл с данными и заменить там нужный стиль.

А если нужно создать новую кнопку?

Тогда все еще проще, записываем нужные стили в уже готовый массив или создаем новый и подключаем его там же в конфиг и классы созданы.

Все это очень удобно, особенно когда переносишь свои компоненты с проекта в проект и скорость написания стилей возрастает в несколько раз, оставляя за собой только чувство комфорта и удовлетворенности от того что в проекте полный порядок.

Такой подход был успешно опробован на множестве проектов и реализация данной методологии скоро будет в свободном доступе с документацией на русском и английском языке.

Комментарии (15)


  1. JustDont
    05.12.2019 15:37
    +1

    Выход «по сути» — это вебкомпоненты, теневой DOM, и частичное его открытие для верхних уровней через ::part и ::theme.
    Всё остальное — это попытки натягивания совы на глобус; когда модульность логики (т.е. кода и компонентов) не совпадает с модульностью стилей — это всегда означает, что за тем и другим придётся следить по отдельности, следить за синхронизацией одного с другим — тоже отдельно, а любой рефакторинг с ростом размера проекта будет превращаться в мигрень.

    Когда люди хватаются за CSS-in-JS даже несмотря на то, что это нестандарт и тормоза — это говорит только о том, что они уже наелись этого вашего CSS отдельно от всего остального. Даже если этот отдельный CSS постоянно упорядочивать.

    Статья-то конечно по делу, но беда в том, что это только первый этап — когда люди смотрят на цсс на 5000 строк и говорят "***, это срочно надо упорядочивать!". Но после упорядочивания всегда еще есть второй этап, когда люди смотрят на свой разобранный по полочкам цсс, и говорят "***, а как теперь следить, чтоб порядок этот не ломался?".


    1. bgnx
      05.12.2019 16:58

      А есть еще подход CSS-in-HTML (когда пишем стили рядом с тегами: <div style="margin: 10px, padding: 10px; color: red; ....">...</div>) который решает и проблему модульности стилей и проблему синхронизации с компонентами-версткой (удаление куска верстки заодно удалит и стили и т.д) и проблему именования классов


      1. zzzmmtt
        06.12.2019 08:51

        Это называется inline styles. И вроде бы считается не самой лучшей практикой, мягко говоря.


        1. JustDont
          06.12.2019 09:42

          Все библиотеки CSS-in-JS в конечном счете именно так стили выставляют. Но да, это мягко говоря не лучшая практика, потому что означает отказ практически от всех фич CSS разом.


          1. Metaller
            09.12.2019 07:00

            Нет, не так. Стили генерируются динамически, но они не вставляются как inline.


            1. JustDont
              09.12.2019 13:00

              Скажем так, всё остальное — это оптимизация поверх изначальной привязки стилей к элементам 1-1. Так-то да, во имя скорости и уменьшения размера DOM в каждый элемент никто уже инлайново не впихивает стиль, но формирование стилей элементов так или иначе идёт через обход их всех.


      1. vin2809
        06.12.2019 12:44

        Как бы это не называли, но оно приводит к дублированию кода или необходимости обертывания одинаковых div. А все это приводит к возрастанию размера кода.


  1. thevrbata
    05.12.2019 16:16

    А где будет выложена документация к подходу?


    1. kaowebdev Автор
      05.12.2019 16:17

      Документация будет в открытом доступе на github.


  1. sacharin
    05.12.2019 23:47

    Где содержимое файла _maker.scss?


    1. kaowebdev Автор
      05.12.2019 23:52

      Это не подробная документация программного продукта или методологии, это всего лишь размышления о том как можно организовать свой css код. Отвечая на вопрос: _maker хранит в себе как стандартные методы, которые общие для всех компонентов так и индивидуальные в зависимости от задач конкретного компонента. Содержимое файла _maker будет уместно рассмотреть в более подробном руководстве. Оно будет немного позже.


      1. zzzmmtt
        06.12.2019 08:52

        Но вы на него ссылаетесь в статье, неплохо было бы листинг хотя бы привести, иначе какая-то недосказанность получается.


  1. Against-vegetables
    06.12.2019 09:47

    Меньше всего мне хочется разгадывать ребусы из миксинов и функций в SCSS. Хочется найти селектор через ctrl+F и мгновенно поменять в нем стили.


  1. Pavenci
    09.12.2019 07:35

    Скажем так: в данный момент препроцессоры не упрощают работу с css, а усложняют. Выше привели хороший пример про нежелание разгадывать ребусы из миксинов и функций scss. Как же это жизненно, когда тебе дают проект, в котором уже тысячи строк стилей с какой-то собственной логикой, которую разработал предыдущий человек и ты должен сидеть и разгадывать где там что.

    Золотой век препроцессоров пришелся на тот период, когда еще не было нативных переменных в css, не было postcss и web компонентов. Но сейчас всё изменилось. Уже сейчас спокойно можно использовать нативные переменные css, которые в разы удобнее и + поддерживаются в js. И миксины можно использовать, просто обычным классом. И функции есть. А самый чистый подход на мой взгляд — это конечно же нативные web компоненты с инкапсулированными стилями. Но увы не весь продакшн ещё до этого уровня дорос, так как нужно отбросить допотопные версии браузеров:) Да чёрт возьми, уже и без вебпака вполне можно обходиться с помощью es модулей, без бабеля, не таща за собой мегабайты лишнего кода, но это уже совсем другая история.


    1. JustDont
      09.12.2019 13:03

      это конечно же нативные web компоненты с инкапсулированными стилями

      Это не стилизуется с верхних уровней. По крайней мере пока что, пока средств раскрытия теневого DOM еще не завезли.
      Ну про чистоту веб-компонентов можно очень серьезно дискутировать. Я бы, например, не стал называть «самым чистым» решение, с которым без выполнения JS вёрстки вообще нет.