Паттерны верстки. Как объединить верстальщиков и дизайнеров

от автора

Данная статья поможет улучшить взаимодействие между дизайнерами и верстальщиками для минимизации ошибок и повышения продуктивности работы.

Работа богата практическими примерами. Она будет полезна специалистам разного профиля.

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

Критерии хорошего дизайна:

  1. Стандартизированные свойства элементов дизайна (цвета, шрифты, размеры, отступы и т.д.)

  1. Принцип переиспользуемости. Изменение одних элементов должно приводить к преобразованиям этих элементов в других частях макета. Нужно избегать копирования элементов.- переиспользуйте их. Речь идёт об использовании стилей и компонентов в figma: шрифтов, цветов, отступов и прочего.

  1. Порядок в слоях и понятный нейминг — прежде всего это ваш профессионализм. Необходимо подходить к процессу ответственно.

  1. Прорабатывать функционирование проекта на мобильных и touch устройствах. Помните об отсутствии hover event  на данных девайсах, не забывайте использовать это в своих макетах. (на десктопе при наведении появляется дополнительный текст, а на мобильных устройствах подобный кейс не учтен.)

  1. Для упрощения работы верстальщика дизайнеру стоит делать видео созданных анимаций.

Рекомендации по верстке:

  1. Pixel perfect — решение устаревшее. Оно преобладало для растровых макетов, в которых не было возможности уточнить размеры элементов. На этом этапе использовались расширения в браузере для наложения изображений дизайна. Подобный подход использовать не нужно.

  1. Не стоит использовать глобальные селекторы по тегам для элементов a, li, ui, h, p и тд, Создавайте классы для более точного выбора. Например, можно завязаться на класс обертку в body .main h1 {}. Глобально h1 — плохо .h1 — хорошо. Помним про принцип переиспользуемости!

  1. Не задавать высоту элементам (input button и тд) с помощью padding. Дизайнер задает конкретные параметры элемента в пикселях, поэтому изменение количества строк или внутреннего контента  повлияет на исходные размеры. Поэтому height у элементов задаем в пикселях.

  1. Лучше использовать пиксели в верстке, а не другие единицы измерения. Дизайн изначально создан в пикселях, поэтому не стоит вмешиваться в исходные параметры. Проценты тоже необходимо применять аккуратно,  если вы используете что-то помимо 25% 50% 100% то, вероятно, вы делаете что-то не так. 50% если делим поровну 2 блока внутри 1 родителя ну и 25% соответственно 4 блока.

Использование готовых ui систем и bootstrap.

В прожектах у которых все элементы кастомные с возможностью принимать любую логику и формы, используя bootstrap и прочие ui системы, вы скорее всего будете обвязывать их дополнительными обертками и костылями, при этом неся за собой неиспользуемый функционал в виде js и style кода. Поэтому в проектах с индивидуальным визуалом стоит этого избегать и кастомизировать все под свои нужды.

Разберем паттерны.

Ссылка на пример https://github.com/jtapes/styles-example

В качестве примера будет использован подход атомарных классов. При этом немного может увеличивается объем html кода. Однако данный подход решается точным и лаконичным написанием небольшого количества классов. Преимуществом данного метода в переиспользование сss стилей, а также минимизация создания классовых оберток.

Рассмотрим цветовые стандарты для — элементом, шрифтов, иконок и тд.

  1. Создавайте и переиспользуйте стили для цветов, не нужно красить пипеткой, наследуя цвет, или копировать hex коды.

  1. Малое количество оттенков одного цвета в проекте поможет избежать ненужной путаницы. Не создавайте «50 оттенков серого». Для проекта оптимально около 6 основных и 4 вариаций серого.

  1. Вынесение цветовых стилей в ui kit (dashboard) нужно для получения информации о кодах цвета и передачи без использования Figma. Например, можно отправить распечатку заказчику для brandbook.

  1. Названия стилей в figma должны совпадать с названиями переменных цветов в коде. Это поможет разработчику ориентироваться и не открывать каждый раз figma для просмотра цвета.

Примеры названий

main, primary, success, danger, warning

$color-main: #464c54;  $color-primary: #ff2e00; $color-primary-hover: #d72d00; $color-primary-active: #bd2200;  $color-success: #25b782; $color-blue: #7da9e0;  $color-withe: #f4f4f4; $color-gray-light: #ccd1d9; $color-gray: #8c9299;  $color-element: #545c66; $color-element-light: #656d78;

Создадим классы цветов и заливки для использования в html.

@mixin color($name, $color) {   .bg-#{$name}  {     background: $color !important; /* stylelint-disable-line declaration-no-important */   }   .color-#{$name} {     color: $color !important; /* stylelint-disable-line declaration-no-important */   } }

Подключим

@include color('base', $color-main); @include color('primary', $color-primary); @include color('success', $color-success); @include color('blue', $color-blue); @include color('withe', $color-withe); @include color('light', $color-gray-light); @include color('gray', $color-gray); @include color('element', $color-element); @include color('element2', $color-element-light);

для `background-color` используем bg-{{name}} .bg-primary .bg-danger

для `color` используем color-{{name}}

.color-primary .color-danger


Кратность отступов и размеров

Кратностью отступов и размеров это соблюдение дизайнером принципа деления всех таких измерений на одно целое число. Стандартом является 4px — значит, все отступы и размеры должны быть результатом произведения 4, на какое-либо целое число. 

4px, 8px, 12px, 16px, 20px и тд.  Разрешается использовать 1px и 2px.

При необходимости кратность можно поменять (например, 22px или 11px), но лучше соблюдать ее хотя бы к 2px. если базовая 4px.

В ином случае нам придется делить пиксель при центровке элементов.

Например, у кнопки размер шрифта 11px, а высота кнопки 40px.

Делаем наш шрифт по центру кнопки.

40 — 11 = 29/2 = 14.5 (отступ сверху и низу)

Браузер сможет справиться  с делением на пиксели — это не проблема. Здесь стоит вопрос эстетичности и легкости процесса верстки страницы. А при разбиении макета по пиксельной сетке в figma не придется выходить за его границы.

Не забываем выносить информацию по отступам в ui kit, тут должны быть все договоренности по дизайну.

Создаем лист, необходимый для генерации классов:

$sizes: (   0: 0,   4: 4px,   8: 8px,   12: 12px,   16: 16px,   20: 20px,   24: 24px,   28: 28px,   32: 32px,   36: 36px,   40: 40px,   44: 44px,   48: 48px, );

Используем в миксине и создаём классы:

@mixin sizes-classes($screen-name: '') {   @each $index, $size in $sizes {     .m#{$screen-name}-#{$index} {       margin: $size !important;     }     .mx#{$screen-name}-#{$index} {       margin-right: $size !important;       margin-left: $size !important;     }     .my#{$screen-name}-#{$index} {       margin-top: $size !important;       margin-bottom: $size !important;     }     .ml#{$screen-name}-#{$index} {       margin-left: $size !important;     }     .mr#{$screen-name}-#{$index} {       margin-right: $size !important;     }     .mt#{$screen-name}-#{$index} {       margin-top: $size !important;     }     .mb#{$screen-name}-#{$index} {       margin-bottom: $size !important;     }      .p#{$screen-name}-#{$index} {       padding: $size !important;     }     .px#{$screen-name}-#{$index} {       padding-right: $size !important;       padding-left: $size !important;     }     .py#{$screen-name}-#{$index} {       padding-top: $size !important;       padding-bottom: $size !important;     }     .pl#{$screen-name}-#{$index} {       padding-left: $size !important;     }     .pr#{$screen-name}-#{$index} {       padding-right: $size !important;     }     .pt#{$screen-name}-#{$index} {       padding-top: $size !important;     }     .pb#{$screen-name}-#{$index} {       padding-bottom: $size !important;     }   } } 
@include sizes-classes; @include project-classes;  @include media(lg) {   @include sizes-classes('-lg');   @include project-classes('-lg'); }  @include media(md) {   @include sizes-classes('-md');   @include project-classes('-md'); }  @include media(sm) {   @include sizes-classes('-sm');   @include project-classes('-sm'); }

Не советую создавать классы для отрицательных отступов и делать более 20 вариаций, так как мы создадим массу редко используемых классов и сильно увеличим css файл для первичной отрисовки. В примере при создании 1 размера создаются 14 классов (из миксина padding и margin) * 4 (все разрешения) — получается 56 классов, поэтому стоит сокращать количество размеров в листе.

Создание переменных:

$size-0: map-get($sizes, 0); $size-4: map-get($sizes, 4); $size-8: map-get($sizes, 8); $size-12: map-get($sizes, 12); $size-16: map-get($sizes, 16); $size-20: map-get($sizes, 20); $size-24: map-get($sizes, 24); $size-28: map-get($sizes, 28); $size-32: map-get($sizes, 32); $size-36: map-get($sizes, 36); $size-40: map-get($sizes, 40); $size-44: map-get($sizes, 44); $size-48: map-get($sizes, 48); $size-52: 52px; $size-60: 60px; $size-64: 64px; $size-80: 80px; $size-84: 84px; $size-88: 88px; $size-100: 100px;

До первого size-52 наследуем размеры от $sizes. Для остальных достаточно создать размеры, кратные нашим согласованиям.

Внутри команды необходимо запретить разработчикам использовать размеры, нужно обязательно использовать переменные по типу $size-4 $size-32 и тд, а процентные значения допускаются только в формате 100 50 25 процентов, Если все же придется отступить от такого порядка — оставляйте комментарий. Это позволит избежать недопонимания и пояснит, что это — часть дизайна.

  &__subcategories {     max-width: 600px; // Размер второй колонки в каталоге из дизайна   }

для `margin` использовать m`{-media}?`-`{size}` (x,y) — оси

.m-1 .ml-2 mt-md-1 .mx-4 .my-2

для `padding` использовать p`{-media}?`-`{size}` (x,y) — оси

.p-1 .pl-2 pt-md-1 .px-4 .py-2

для иконок можно создать классы — `icon-{size}`

Чаще всего необходимы только 3 класса:

icon-16 icon-24 icon-32

svg {   width: 100%;   height: 100%;   fill: currentColor; }  .icon-16 {   width: $size-16;   height: $size-16; }  .icon-24 {   width: $size-24;   height: $size-24; }  .icon-32 {   width: $size-32;   height: $size-32; }

Стили шрифтов

Как и в случае с цветами и отступами все шрифты необходимо занести в стили figma и вынести в up kit, не создавая при этом десятки вариаций толщины и размера, межбуквенных и межстрочных интервалов. Обычно достаточно следующего: размеры — h1, h2, h3, h4: default text, small text. Начертания — regular, medium, bold.

Верстальщику необходимо правильно подключить наши шрифты, нужно конкретно указать браузеру, откуда загружать шрифты regular, bold и т.д., В противном случае браузер сделает начертание bold самостоятельно. Это не будет соответствовать макету.

Используйте классы для задания шрифтов у элементов по типу .h1 .h2 или в крайнем случае @mixin h1. Миксины плохи тем что,  дублируют, а не переиспользуют свойства. В верстке нужный шрифт выбираем с  помощью font-weight.

Подключение

@font-face {   src: url('https://fonts.gstatic.com/s/rubik/v14/iJWKBXyIfDnIV7nBrXw.woff2') format('woff2');   font-family: 'Rubik';   font-weight: 100 500;   font-style: normal;   font-display: swap; }  @font-face {   src: url('https://fonts.gstatic.com/s/rubik/v14/iJWKBXyIfDnIV7nBrXw.woff2') format('woff2');   font-family: 'Rubik';   font-weight: 600 800;   font-style: normal;   font-display: swap; } 

Таблица размеров и типов:

100: Thin; 200: Extra Light (Ultra Light); 300: Light; 400: Normal; 500: Medium; 600: Semi Bold (Demi Bold); 700: Bold; 800: Extra Bold (Ultra Bold); 900: Black (Heavy).

Не используйте свойства шрифтов.

Если вдруг по какой-либо причине это необходимо, комментарий обязателен.

Использование миксинов для базовых классов

.h3 {   @include h3;    @include media(md) {     @include h4;   } }
@mixin font($size: 18px,  $line-height: 24px, $letter-spacing: 0.1px, $weight: 400, $bottom: false) {   margin: 0;   font-family: $font;   font-weight: $weight;   font-size: $size;   line-height: $line-height;   letter-spacing: $letter-spacing;   user-select: text;    @if $bottom {     margin-bottom: $bottom;   } }  @mixin h1 {   @include font(48px, 54px, 2px, 600, $size-32); }  @mixin h2 {   @include font(32px, 32px, 1.5px, 500, $size-24); }  @mixin h3 {   @include font(24px, 28px, 0.5px, 400, $size-16); }  @mixin h4 {   @include font(20px, 28px, 0.3px, 400, $size-8); }  @mixin text {   @include font; }  @mixin text-sm {   @include font(16px, 22px); }  @mixin text-default {   @include text;   @include media(tablet) {     @include text-sm;   } } 

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

Убрать отступы можно следующим образом: — .h1 .mb-0


Свойства элементов

Все повторяющиеся стили у элементов (тени, радиусы, бордеры) дизайнер также выносит в ui kit. Не рекомендуется делать много вариаций.

В верстке выглядит это примерно так:

$font: 'Rubik', sans-serif; $radius-block: $size-8; $radius-element: $size-8; $border-element: $size-4; $show-block: 0 0 $size-40 rgba($color-element, 0.1); $animate-time: 0.2s;

Контрольные точки

Дизайнер указывает информацию в ui kit: какие точки перестроения интерфейса у нашего приложения. Обычно размеры соответствуют размерам экранов на разных устройствах.

Создаём переменные:

$breakpoints: (   xl: 1200px,   lg: 992px,   md: 768px,   sm: 576px, );

Создаем миксин для удобства использования медиа условий:

@mixin media($Device) {   @media screen and (max-width: map-get($breakpoints, $Device) - 1px) {     @content;   } }

Сетка проекта

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

Описываем правила в стилях:

@import 'variables';  $columns-count: 12; $gutter: $size-16; $width: 100% / $columns-count;  @mixin grid($breakpoint: '') {   $prefix: if($breakpoint == '', '', '-');    @for $i from 1 through $columns-count {     .col#{$prefix}#{$breakpoint}-#{$i} {       width: $width * $i;       @if $i != 1 {         margin-left: $gutter;       }     }   }    @for $i from 1 through $columns-count {     .off#{$prefix}#{$breakpoint}-#{$i} {       margin-left: calc(#{$gutter} + #{$width * $i});     }   } }  @include grid; @each $breakpoint, $value  in $breakpoints {   @media (max-width: $value) {     @include grid($breakpoint);   } } 

Кастомные классы

Для всех кастомных классов используем префикс:

$custom: 'pr'; // префикс для кастомных классов  .#{$custom}-container {   margin: 0 auto;   padding: 0 map-get($sizes, 24);   width: 100%;   max-width: 1140px !important;    @include media(md) {     padding: 0 map-get($sizes, 16);   }    @include media(md) {     max-width: 556px !important;   } }

Классы утилиты

@mixin project-classes($screen-name: '') {   .d#{$screen-name}-n {     display: none !important;   }   .d#{$screen-name}-b {     display: block !important;   }   .d#{$screen-name}-f {     display: flex !important;   }   .fw#{$screen-name}-w {     flex-wrap: wrap !important;   }   .fw#{$screen-name}-n {     flex-wrap: nowrap !important;   }   .fd#{$screen-name}-c {     flex-direction: column !important;   }   .fd#{$screen-name}-r {     flex-direction: row !important;   }   .fb#{$screen-name}-100 {     flex-basis: 100% !important;   }   .ai#{$screen-name}-c {     align-items: center !important;   }   .ai#{$screen-name}-fs {     align-items: flex-start !important;   }   .ai#{$screen-name}-fe {     align-items: flex-end !important;   }   .as#{$screen-name}-fs {     align-self: flex-start !important;   }   .as#{$screen-name}-fe {     align-self: flex-end !important;   }   .as#{$screen-name}-c {     align-self: center !important;   }   .jc#{$screen-name}-fe {     justify-content: flex-end !important;   }   .jc#{$screen-name}-fs {     justify-content: flex-start !important;   }   .jc#{$screen-name}-c {     justify-content: center !important;   }   .jc#{$screen-name}-sb {     justify-content: space-between !important;   }    .bg#{$screen-name}-n {     background: none !important;   }    .br#{$screen-name}-n {     border: none !important;   }    .w#{$screen-name}-100 {     width: 100% !important;   }   .h#{$screen-name}-100 {     height: 100% !important;   }    .w#{$screen-name}-50 {     width: 50% !important;   }   .h#{$screen-name}-50 {     height: 50% !important;   }    .w#{$screen-name}-25 {     width: 50% !important;   }   .h#{$screen-name}-25 {     height: 50% !important;   }    .f#{$screen-name}-l {     font-weight: 300;   }   .f#{$screen-name}-r {     font-weight: 400;   }   .f#{$screen-name}-m {     font-weight: 600;   }   .f#{$screen-name}-b {     font-weight: 800;   } }

Это и есть верстка классовым подходом. Например, очень часто нам нужно выровнять блоки по горизонтали: в данном случае будет достаточно d-f, и не придётся каждый раз создавать классы-обертки.

Для `display-flex: flex`используем `d-f`

Для `align-items: center`- `ai-c`

Список можно постоянно пополнять по мере необходимости Если свойство состоит из 2 слов, используем буквы слов `text-align` = `ta`

Если свойство состоит из 1 буквы и не конфликтует с другими —  `display` = `d`

При конфликте первой и последней буквы — `border` = `br` или часть слова по логике `background` = `bg`

Старайтесь максимально использовать классовую верстку без переменных и миксинов scss.

`class=»d-f m-4 m-md-4″` — допустимо

`class=»d-f m-4 m-md-4 d-f m-4 m-md-4 d-f m-4 m-md-4 d-f m-4 m-md-4″` — Плохо. В таких случаях создается класс с описанием свойств внутри него.

`class=»d-f custom-class»` — не запрещено, но иногда удобней и предпочтительней написать свойство в классе: `display: flex`.

Возьмите за правило не писать больше 5 классов в блоке.

Не забывайте про классы w-100 h-100, w-50 h-50, w-25 h-25


Z-index

Подключение `@include z-index(наименование ключа)`

Значения z-index заданы с шагом 10 для того, чтобы оставить место для ошибок и настроек.

При добавлении нового ключа необходимо предусмотреть все конфликты с существующей картой z-index:

$z-index: (   modal: 30,   header: 20,   menu: 10,   default: 1, );

Заключение

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


ссылка на оригинал статьи https://habr.com/ru/post/654555/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *