Ситуация была следующей.
Компания занималась редизайном сайта и заявила, что он должен быть максимально гибким. Во-первых, чтобы иметь возможность легко обновлять дизайн, а во-вторых, сделать еще несколько подразделов на основе готового функционала (этакая 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 ряда).
Подводя итог всему, хочу обозначить плюсы и минусы такого подхода.
В общем то же самое, что и с комментариями. Если вы будете писать подробные и понятные комментарии там, где они действительно нужны, если будете помнить об их обновлении каждый раз после изменения логики, то это даст вам огромное преимущество в поддержке кода.
Я бы сказал, что чем больше будет проект, тем легче будет его писать.
Здесь то же самое. Если, узнав новую информацию от дизайнера, вы не поленитесь обновить все переменные, которые с ней связаны, если постараетесь сделать логику в коде похожей на ту, что в голове у заказчика, то через некоторое время , проект не будет нуждаться в дизайнере — сделать будет быстрее, чем рисовать.
Если вы забываете обновлять комментарии, или когда вы слышите о новых требованиях от клиента, вы ленитесь и создаете другую переменную вместо обновления существующей, такой подход сделает ваш код слишком сложным.
Еще раз хочу напомнить вам, чторазработчик — это человек, который переводит мысли заказчика на машинный язык.
Пишите понятный код, надеюсь поддержка теперь будет вам в удовольствие!