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

(Часть 1)

Приходит первый дизайн (пришлось много менять из-за NDA, но было что-то похожее).

У нас есть кое-что интересное здесь.
1) Есть разделы разделенные по принципу:

· Заголовок
· Содержание

Заголовок всегда один и тот же.
Итак, мы переносим заголовок и текст содержимого в типографику (Компоненты/Типографика или любое другое имя, которое вам нравится, если оно семантически объясняет, что это такое).

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

Оказывается, вам также нужна сущность, которая устанавливает те же правила для разделов, такие как общие отступы и общая минимальная высота. Я назвал этот тип объектов «контейнерами». В частности, для BasicSection.

Итак, у нас уже есть Typography с заголовком и Containers с BasicSection.

Отлично, давайте создадим такие разделы.

Я думаю, это немного запутанно в стилях, не так ли?
Поясню.

Мы помним из предыдущей статьи, что у нас есть ритм в дизайне. Поэтому за основу всех отступов на сайте мы взяли 10px.

Почему 10px?
Потому что все отступы кратны 10.
Отступ сбоку страницы — 90px, отступ между кнопками, метками, формой — 10px или 20px и т.д.

Тогда все отступы будут считаться от 10px ($offset-basic). Сам $offset-basic нигде не должен использоваться, потому что он является лишь ориентиром и не имеет отношения к семантике сайта.

Давайте двигаться дальше.
Высота раздела, по нашему мнению, равна высоте экрана (100вх). Вроде логично, но когда добавляю шапку на сайт оказывается полоса прокрутки есть. Это потому, что у нас есть блок высоты заголовка 100vh + 150px (например). Чтобы не потерять контекст, который мы только что обнаружили, я предлагаю прописать эту логику в переменной высоты секции.

Результат:

Почему это важно?
Я часто видел записи в компоненте заголовка, высота: 150px, и в разделе высоты, высота: 95vh.
Вроде точно, но куда делся 5vh? Почему 150px = 5vh? И другие вопросы.

Где? Например, откройте сайт Forbes (https://www.forbes.com).
Похожая логика магических чисел: 3%, 31,8%.

Ну да, я понимаю, что оставшийся блок скорее всего занимает 97% и 68,2%, или не один оставшийся блок, а два оставшихся блока.
Хм.
Ладно, ладно, я не понимаю.

Думаю, с формулой высоты мы закончили, идем дальше.

Далее появился этот замечательный раздел (белый) для которого есть и мобильный дизайн и дизайн для планшета. Что нам с этим делать?

Запросы СМИ!
Здесь изменены отступы в каждом разделе. В мобильной версии фона почти нет, в планшетной версии фона немного, а в десктопной он заполняет, насколько я понимаю, все свободное место.

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

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

Надеюсь, вас не удивит переменная ширина экранов…

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

Переходим к следующим разделам.

Хорошо виден отступ между элементами и отступ от шапки.
Итак, для метки нужно добавить отступ с правой стороны равный одному $offset-basic, а для шапки снизу нужно чтобы добавить отступ, равный двум $offset-basic.

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

Результат:

Я добавлю медиа-запросы, потому что у нас разная раскладка для разных устройств…

Честно говоря, это уже не очень читабельно.
Да, лучше было бы разнести его по разным файлам.
Например, прописать глобальные переменные в main.scss и использовать их в медиа-запросах внутри компонентов.

Чтобы поместить медиа-запросы в mixins.scss как что-то вроде @include mobile, @include table.

Так.

Получаем следующее:

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

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

Давайте внимательно посмотрим.

Первая (№1) версия — простое копирование из Figma или откуда-то еще.

Второй (№2) вариант — это стандартная унификация переменных.
Когда у нас есть цвета как $red, $black или $alpha, $beta, то отступы просто перемножаются (в лучшем случае иногда просто создаются новые переменные и в проекте сразу 1000 переменных).

Третья (№3) версия вроде читабельна, но, честно говоря, тоже не очень. В имени переменной ($[property]-[element]-[media-query]) есть задумка, но выглядит слишком избыточно.

Наконец, «серебряная пуля», которую я предлагаю.
Вариант кодирования, который мы искали!
Мы помещаем переменные, которые мы изменяем из каждого компонента, в один глобальный компонент — тег html.

Как?
Добавляем css-переменные.

Теперь наши занятия выглядят так.
Все. Все разделы, все заголовки, кнопки, ярлыки — все есть в проекте.

Потому что они будут созданы таким же образом.

Но как выглядят медиа-запросы?

Вот так.
Код стал разделяться на файлы. Компоненты теперь содержат только информацию о типе отступа (его семантическом значении), а файл variable.scss содержит информацию о том, как отличаются отступы в зависимости от устройства.

В продолжение статьи я сделал шаблон на основе приложения create-react-app, чтобы вы могли самостоятельно следить за развитием событий, «тыкаясь» в код и выясняя, устраивает вас он или нет (https:// github.com/DrBoria/cra-scss).

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

Следующая задача — редактирование дизайна — оказалась куда сложнее.
Ну, не то чтобы «правки». Полностью изменился дизайн.

Некоторые разделы можно только переписать с нуля, некоторые похожи, но требуют полной модификации.

  • До

  • После

Главная страница практически не изменилась — изменились только отступы между разделами (от меню до шапки) и цвета.

Но услуги совсем другие. Единственное, что похоже, это структура карт. И даже не очень.

  • До

  • После

И вы считаете это проблемой? Замена заняла максимум 20 минут.

  • До

  • После

1. Изменяем два столбца на сложную систему столбцов, как в областях шаблона сетки.

2. Так как у нас теперь есть два типа карточек — изображения и текст — я вынес их в отдельный компонент.

3. Для отступов между карточками добавляем grid-gap, равный отступу между элементами.

4. Хорошо, теперь мы можем пойти сварить кофе. Нам даже не пришлось переписывать структуру на jsx (я для красоты вынес карточки в отдельный компонент, но там все равно было меньше 20 строк…)

Я обещал ранее, что будет три дизайна.

Теперь у нас белая версия…

Как видим, логика совсем другая.
Сверху (черный) у нас, скажем так, оверлей. На нижнем (белом) у нас есть текст и фотографии.

Сами фото идут в разном порядке, разной структуры.
По сути, это та же страница, но на другую тему.

Размещаем фотографии с сеткой (думаю, нет особого смысла показывать, как это делается).

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

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

Далее, чтобы понять, какая тема сейчас включена, я добавил переменную css –theme с названием темы («темная» и «светлая» соответственно)

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

В отличие от data-атрибутного подхода, этот метод позволяет переопределить тему не только в корневом компоненте, но и во вложенных.
Само переопределение осуществляется с помощью ThemeProvider.

Получив доступ к текущей теме непосредственно в компоненте jsx, я добавил логику наложения (базовые пластины под текстом в темной теме) и размещение карточек (2 или 3 ряда).

Подводя итог всему, хочу обозначить плюсы и минусы такого подхода.

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

Здесь то же самое. Если, узнав новую информацию от дизайнера, вы не поленитесь обновить все переменные, которые с ней связаны, если постараетесь сделать логику в коде похожей на ту, что в голове у заказчика, то через некоторое время , проект не будет нуждаться в дизайнере — сделать будет быстрее, чем рисовать.

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

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

Пишите понятный код, надеюсь поддержка теперь будет вам в удовольствие!