Ситуация получилась следующая.
Компания переделывала сайт и сказала, что необходимо сделать его максимально гибким, чтобы, во-первых, можно было дизайн обновлять просто, во-вторых, сделать ещё несколько подразделов на базе готового функционала (вроде как SaaS фишка для заказчиков).
(Часть 1)
![](https://habrastorage.org/getpro/habr/upload_files/5a0/deb/d8d/5a0debd8d1d50028594763f0c75dea6c.png)
Прилетает первый дизайн (пришлось сильно изменить, т.к. nda, все дела, но что-то похожее).
Что тут у нас интересное.
Есть секции, которые разбиты по принципу:
· Заголовок
· Контент
Заголовок всегда одинаковый.
Значит выносим заголовок и текст контента в типографию (Components/Typography, либо любое другое название, абы вам нравилось и семантически объясняло, что это).
Дальше куча всяких секций. На таком мелком рисунке не видно, но многие секции имеют одинаковые отступы, а у 50% ещё и высота одинаковая.
Получается нужна ещё сущность, которая задаёт одинаковые правила для секций, например, единые отступы и единую минимальную высоту. Я назвал этот тип сущностей containers. В частности, для секции BasicSection.
Получается, у нас уже есть Typography, в которой есть заголовок и Containers, где есть BasicSection.
Замечательно, создаём такие секции.
![](https://habrastorage.org/getpro/habr/upload_files/da1/b08/c53/da1b08c53e94279adbf33caaea1c4e1a.png)
![](https://habrastorage.org/getpro/habr/upload_files/bea/111/91d/bea11191dca9538405a2ebd4143b722d.png)
Наверное, немного сумбурно в стилях, да?
Сейчас поясню.
Из предыдущей статьи мы помним, что у нас есть ритм в дизайне. Поэтому мы взяли 10px, как основу для всех-всех отступов на сайте.
Почему 10px?
Потому что все отступы кратны 10ке.
Отступы сбоку страницы – 90px, отступы между кнопочками, лейблами, формой – 10px либо 20px и тд.
Далее именно от 10px ($offset-basic) будут считаться все отступы. Сам же $offset-basic использоваться нигде не должен, т. к. является исключительно точкой отсчёта и не относится к семантике сайта.
Двигаемся дальше. Высота секции, по нашему мнению, равна высоте экрана (100vh). Вроде бы всё логично, но, когда я добавляю на сайт хедер, появляется полоса прокрутки. Связанно это с тем, что у нас блок 100vh + 150px (например, столько) высота header. Для того, чтобы не терять контекст, который мы только что обнаружили, предлагаю записать эту логику в переменную высоты секции.
Итого:
![](https://habrastorage.org/getpro/habr/upload_files/7ac/11b/349/7ac11b349eb94d1dc7604312e467bae2.png)
Почему это важно.
Я часто видел записи в компоненте header, height: 150px, а в высоте секции height: 95vh.
Вроде бы точно, но куда делись 5vh? Почему 150px = 5vh? И прочие вопросы.
Где? Ну вот например откройте сайт Forbes (https://www.forbes.com).
Похожая логика магических чисел: 3%, 31.8%
![](https://habrastorage.org/getpro/habr/upload_files/dbd/1cd/71f/dbd1cd71fad1d4c15b8f81fea74a84a8.png)
![](https://habrastorage.org/getpro/habr/upload_files/aa4/279/a80/aa4279a803455cda87b7db3da889b3c3.png)
Ну да, я понимаю, что, скорее всего, оставшийся блок занимает 97% и 68.2%, или не оставшийся блок, а два оставшихся блока. Хмм. Ладно, да, я не понимаю.
Думаю, на этом с формулой высоты мы закончили, едем дальше.
![](https://habrastorage.org/getpro/habr/upload_files/586/8e5/094/5868e5094fe4d5d5ca66b38684b7120d.png)
Попалась такая замечательная секция (белая), для которой есть и мобильный дизайн, и планшетный дизайн. Что с этим то делать?
Media queries.
Здесь отступы в каждой секции изменены. В мобильной версии практически нет фона, в планшетной его немного, а в десктопной он заполняет, насколько я понимаю, всё свободное пространство.
Здесь, следуя логике первой статьи, мы идём к дизайнеру и уточняем, точно ли всё правильно поняли, чтобы не догадки строить, а точно узнать, что нужно.
Отлично, что мы делаем с полученной информацией?
Первым на ум приходит простая вставка значений в каждой media query.
![](https://habrastorage.org/getpro/habr/upload_files/3bb/bdb/d11/3bbbdbd1112fe2e5206003cbce8951f5.png)
Надеюсь, вас не сильно удивят переменные ширины экранов…
Получилось, по-моему, читаемо.
Глобальные переменные из html подставляются в компонент. В будущем их можно переиспользовать в других компонентах, секциях (с другой высотой).
Смотрим на секции дальше.
![](https://habrastorage.org/getpro/habr/upload_files/b6b/23e/8b6/b6b23e8b668b4c882441a54850f3ae99.png)
![](https://habrastorage.org/getpro/habr/upload_files/24f/55e/75f/24f55e75fa10590f488beb3ef4dd9274.png)
![](https://habrastorage.org/getpro/habr/upload_files/dfe/8c3/6e6/dfe8c36e6c4be0b6de59f27974d950d5.png)
Чётко выделяется отступ между элементами и отступ от заголовка.
Следовательно, для label нам необходимо добавить отступ справа, равный одному $offset-basic, а заголовку снизу – равный двум $offset-basic.
Единственное, по поводу отступов прошу ознакомиться с данной статьёй, чтобы понимать, почему не стоит добавлять отступы слева и сверху.
Результат:
![](https://habrastorage.org/getpro/habr/upload_files/615/9a8/df2/6159a8df272c7b831dc0e28c954b930a.png)
Я добавлю media queries, потому как у нас всё-таки вёрстка под разные устройства …
![](https://habrastorage.org/getpro/habr/upload_files/ef9/862/b8e/ef9862b8e296439fbf0da9b64bbf2cee.png)
Если честно, уже слабо читаемо.
Да, если разнести по разным файлам, будет лучше.
Например, в main.scss объявлять глобальные переменные и использовать их в media queries внутри компонентов.
![](https://habrastorage.org/getpro/habr/upload_files/571/5da/707/5715da70709c103dcefb89c6a69c27b7.png)
Media queries вынести в mixins.scss как что-то типа @include mobile, @include tablet.
Вот так
Получаем следующее:
![](https://habrastorage.org/getpro/habr/upload_files/067/a7f/8e8/067a7f8e8b1d96945de5a160d4e2df71.png)
В принципе неплохо. Ладно. Не неплохо. Терпимо. Но это будет для каждого элемента, каждого тега. Выглядит как очень странное дублирование кода…
Здесь мне очень хочется побеседовать о читаемости.
Давайте сравним 3 варианта кода, которые я часто встречаю, и тот, что был выше.
![#1 #1](https://habrastorage.org/getpro/habr/upload_files/6a2/28a/280/6a228a2806f93f7fee6d5401d0945ae0.png)
![#2 #2](https://habrastorage.org/getpro/habr/upload_files/4f8/a91/040/4f8a91040f8bf93defe950afc96c6ea2.png)
![#3 #3](https://habrastorage.org/getpro/habr/upload_files/4bd/357/3f8/4bd3573f84bd7deb7d629f277a757f4e.png)
Смотрим, вникаем.
Первый вариант (#1) – классическое копирование из фигмы или ещё откуда.
Второй вариант (#2) – классическое унифицирование переменных. Когда у нас цвета идут как $red, $black либо $alpha, $beta, а отступы просто умножаются (в лучшем случае, бывает просто новые переменные создаются и существует по 1000 переменных в проекте одновременно).
Третий способ (#3) вроде как читаем, но, честно говоря, тоже не сильно хороший. Есть какая-то идея в имени переменной ($[property]-[element]-[media-query]), но выглядит уж больно избыточно.
Ииии, «silver bullet», который я предлагаю.
Вариант записи, к которому мы так долго шли!
Выносим переменные, которые мы меняем из каждого компонента в один глобальный – html тег.
Как?
Добавляем css-variables.
![](https://habrastorage.org/getpro/habr/upload_files/41c/81f/451/41c81f451801e7d9fa30157692ca382f.png)
Теперь наши классы выглядят вот так.
Все классы. Все секции, все заголовки, кнопочи, лейбочки – всё в проекте.
Потому как они будут создаваться по подобию.
Как же выглядят media queries?
![](https://habrastorage.org/getpro/habr/upload_files/96e/318/58c/96e31858cd45d3654930dda91a546a15.png)
А вот так.
Код стал разделён по файлам. Теперь в компонентах содержится только информация о типе отступа (его семантическое значение), а в файле variables.scss – информация о том, как отличаются отступы в зависимости от устройства.
Для продолжения статьи я сделал шаблон на базе create-react-app, чтобы вы могли самостоятельно следить за развитием событий, тыкая в код и пробуя своими руками, удобно вам или нет (https://github.com/DrBoria/cra-scss).
Я добавил некоторые переменные, например, для типографии.
Для понимания размера шрифта предлагаю ознакомиться с данной статьёй.
Дальше задачка посложнее прилетела – правки по дизайну.
Ну, как сказать правки. Дизайн полностью изменился.
Некоторые секции возможно только переписать с нуля, некоторые похожи, но их нужно полностью модифицировать.
![](https://habrastorage.org/getpro/habr/upload_files/2c1/0c7/2bd/2c10c72bd4f3f0ba9816c528d0411b87.png)
Было
![](https://habrastorage.org/getpro/habr/upload_files/eac/6ee/26b/eac6ee26b95f92d3a59c0f429e4c4e05.png)
Стало
Главная практически не изменилась – только отступ между секциями (от меню до заголовка) и цвета.
Зато сервисы полностью другие. Единственное, что похоже – структура карточек. И то не сильно.
![](https://habrastorage.org/getpro/habr/upload_files/510/45a/8ed/51045a8ed354c3035a4591bbd58db0b1.png)
Было
![](https://habrastorage.org/getpro/habr/upload_files/e1d/664/d0d/e1d664d0d8c50f00cc622e1c22a615b1.png)
Стало
И думаете, это проблема? На изменение ушло минут 20 максимум.
![](https://habrastorage.org/getpro/habr/upload_files/a21/1ad/e0e/a211ade0e078808a05c97231c8d11203.png)
Было
![](https://habrastorage.org/getpro/habr/upload_files/079/2c8/e82/0792c8e8265b4a2d0a7c02b0d15bf91f.png)
(зачёркнутое вынес в отдельный компонент)
Стало
1) Меняем две колонки на сложную систему колонок, как в grid template areas.
2) Т.к. у нас теперь два типа карточек – картинки и текст. Вынес их в отдельный компонент
3) Для отступов между карточками добавляем grid-gap, равный отступу между элементами.
4) Всё, можно кофе заварить. Даже структуру в jsx не пришлось переписывать (я вынес для красоты карточки в отдельный компонент, но там всё равно меньше 20 строк было…)
Выше я обещал, что дизайна будет три.
![](https://habrastorage.org/getpro/habr/upload_files/9e4/a46/0ce/9e4a460ce3c00ca9ee14188485e9442a.png)
![](https://habrastorage.org/getpro/habr/upload_files/bce/de9/4d9/bcede94d9b8a33a0d02423be0587e5ba.png)
Подлетела белая версия…
Как мы видим – логика совершенно разная.
Слева (на чёрном) у нас есть, назовём это, overlay. Справа (на белом) у нас сразу идёт текст и фото.
Сами фото идут в разном порядке, разной структуре.
По сути это одна и та же страница, но для разной темы.
Как расставлять фото – думаю нет особого смысла показывать – гридом это делать.
Основные вопросы – как добавить разную логику в зависимости от темы? И как организовать цвета?
В данном проекте я разделил цвета на базовые и связанные с темой.
Базовые – это выделение (розовое, фиолетовое), цвет текста в выделенных элементах (всегда белый) и disabled – для элементов формы.
Все остальные цвета вошли в темы.
Дальше, чтобы понять, какая тема в данный момент включена, я добавил css переменную –theme с указанием темы (‘dark’, ‘light’ соответственно), которую ловил в компонентах, где оно было необходимо, с помощью следующей логики.
![](https://habrastorage.org/getpro/habr/upload_files/909/43f/d90/90943fd907256190f344fe5aab0cd44d.png)
В отличие от подхода с data-attribute, данный способ позволяет переопределять тему не только в root компоненте, но и во вложенных.
Собственно переопределение происходит с помощью ThemeProvider.
Получив доступ к текущей теме уже непосредственно в jsx компоненте, я добавлял логику overlay (подложки под текстом в тёмной теме) и расстановки карточек (2 или 3 ряда).
Как резюме, хочу обрисовать плюсы и минусы данного подхода.
По сути, всё так же, как с комментариями. Если вы пишете развёрнутые и понятные комментарии там, где они действительно необходимы, если вы не забываете обновлять их каждый раз после того, как изменилась логика - тогда это даст вам огромный плюс в поддержке кода.
Я бы сказал, чем больше становится проект, тем проще его будет писать.
То же самое и здесь. Если, узнав новую информацию от дизайнера вы не ленитесь обновлять все переменные, которые с этим связанны, если вы стараетесь сделать логику в коде похожую на ту, что в голове заказчика, то со временем проект не будет нуждаться в дизайнере – быстрее станет сделать, чем нарисовать.
Если же вы забываете обновлять комментарии, или услышав про новые требования от заказчика лениво создаёте очередную переменную, а не обновляете существующую, то данный подход сделает ваш код слишком запутанным.
Ещё раз хочется напомнить, что разработчик – это человек, который переводит мысли заказчика на язык машины.
Пишите понятный код, надеюсь, поддержка теперь станет для вас удовольствием!
Комментарии (9)
IgosYee
18.12.2021 14:59+1Ох, все отступы кратные 10ке. Тут недавно клиент пришел со своим дизайном, вроде ок. Но все отступы плавают 17рх, 9рх и тд, логики в них никакой нет. "Дизайнер" ставил их на глаз. На просьбу подправить или что мы будем использовать одинаковые в похожих элементах, клиент сказал "нетЪ, хочу перфект пиксель"...
mikita_du Автор
18.12.2021 15:13Тут дело такое.
У меня в одном дизайне были разные отступы в дизайне вокруг одного элемента.
Сверху 9px, справа 7px, снизу 8px.
Я на своё усмотрение сделал единое. На дизайн было похоже - все были рады)
stainlouder
19.12.2021 00:20Согласен, довольно небольшой процент дизайнеров, которые относятся к своей работе с пониманием. Как раз используют ритмику, палитры, иногда даже золотое сечение, причем со знанием дела. Многие, к сожалению, считают, что достаточно просто "природного" чутья и понимания "что с чем слепить чтобы было круто". А еще находятся заказчики, которые до абсурда отставают каждый пиксель подобных дизайн кодов.
Здорово, что можно настроить все в переменных и тогда и собственный перфекционизм спокоен и изменения не требуют большого количества времени.
skeevy
20.12.2021 02:02В первой части переизобрели бутстрап 4, во второй части в css уже видны проблемы отсутствия следования методологии какой либо
Для новичков материал суперский, но автору посоветовал бы пересмотреть подход к организации css, начиная с нейминга и раз вы используете scss - использовать миксины чаще и placeholder-классы. Даже "улучшенный" код можно ещё сократить, используя все выше, а спагетти из card-* упаковать в 3-5 строчек, используя map
notiv-nt
Конечно прекрасно, но такой контент лучше в видео формате воспринимать
Xeldos
Нет.
FFF
Такой контент лучше воспринимать в виде статьи с хорошим оформлением, чего здесь, увы, нет.