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

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

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

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

  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 у элементов задаем в пикселях. Если такое решение необходимо, например кнопка может быть c переносом шрифта в 2 строки, будьте осторожны с внутренним контентом. Возможно следует создать дополнительный класс.

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

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

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


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

Ссылка на пример 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,
);

Заключение

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

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


  1. BlackStar1991
    06.03.2022 10:57
    +6

    Дизайн - это творчество, а ты своим СSS пробуешь загнать дизайнеров в рамки, это так не работает... Опытные дизайнеры и так знают, что можно делать, а что - нет. Другой вопрос насколько они ленивы что бы это выполнять.

    за бездумное использование !important я бы вводил смертную казнь или принудительное кастрирование... И не только потому, что из-за таких чудо frontend-ов что бы потом сайт на AMP перевести надо его переписывать, но и ещё и-за добавления проблем в приоритетах стилей. Пожалуйста не надо так! Используйте каскадность. Ваша идея реализуема только в приделах какой-то конторки которая клепает сайт (возможно дорвеи) пачками, где всё +- одинаково, что-то по типу онлайн-казино.


    1. jtape Автор
      06.03.2022 12:06

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

      за бездумное использование !important я бы вводил смертную казнь или принудительное кастрирование

      где вы увидели бездумное использование important в моих примерах?

      использование important для атомарных  классов - это адекватное ращение, так как из за специфичности селекторов без important будет проблемы

      даже сам bootstrap 5 и многие другие фреймворки используют important

      посмотрите исходный код
      https://github.com/twbs/bootstrap/blob/main/dist/css/bootstrap-utilities.css

       Ваша идея реализуема только в приделах какой-то конторки которая клепает сайт (возможно дорвеи) пачками

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


    1. SiR2104
      07.03.2022 08:36
      +1

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


  1. skeevy
    06.03.2022 12:34
    +1

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


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

    Лучше использовать пиксели в верстке, а не другие единицы измерения. Дизайн изначально создан в пикселях, поэтому не стоит вмешиваться в исходные параметры.

    Еще как стоит. В бытность мою работы на фрилансе и галере веб-студии мне приходили макеты только для десктопа, при необходимости самому допиливать мобилку. Даже если и есть мобильные макеты, вы все-равно предлагаете отказаться от rem/em/%?

    Получается, что:
    1) Вместо установки rem на боди и пропорциональному уменьшению/увеличению его на мобилке, я должен буду руками ходить все исправлять?
    2) Я не учитываю работу клиентского устройства под разного рода масштабированием

    А масштабирование - это элемент доступности, вы предлагаете делать интерфейсы недоступными, просто потому что дизайнер прав? А если он не прав?

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

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

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

    Почему стоит избегать? Опять же, тот же бутстрап позволяет атомарно пересобрать свою сетку просто импортируя к себе нужные scss файлы и дальше вот те примеры по изобретению велосипеда не нужны от слова совсем.
    Например, откопал такие участки кода в своих проектах +-3 лет давности :

    @import 'node_modules/bootstrap/scss/bootstrap-reboot.scss';
    @import 'node_modules/bootstrap/scss/bootstrap-grid.scss';
    @import 'node_modules/bootstrap/scss/utilities/_sizing';
    /* Vars:
       ========================================================================== */
    
    // Font
    $mainFont: 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif;
    $mainFontColor: #101010;
    
    //desktops
    $large_desktop: 1440px;
    $small_desktop: 1200px;
    //tablets
    $large_tablet: 992px;
    $small_tablet: 768px;
    //phones
    $large_mobile: 576px;
    $small_mobile: 460px;
    //core font
    $mainFontSize: 16px; //16px
    $mainFontWeight: 400;
    $mainLineHeight: 150%; //24x or 1.25rem
    $boxHeight: $mainLineHeight;
    
    //bootstrap sizing
    $grid-gutter-width: 40px;
    $grid-columns: 10;
    
    $grid-breakpoints: (
      xs: 0,
      sm: $large_mobile,
      md: $small_tablet,
      lg: $large_tablet,
      xl: $small_desktop,
      xxl: $large_desktop,
    );
    
    $container-max-widths: (
      sm: 540px + $grid-gutter-width,
      md: 720px + $grid-gutter-width,
      lg: 960px + $grid-gutter-width,
      xl: 1170px + $grid-gutter-width,
      xxl: 1320px + $grid-gutter-width,
    );
    
    $gutter: $grid-gutter-width / 2;

    И дальше использовались те же классы или миксины бутстрапа. При этом, 0 js, потому что в моем случае мне только сетка и нужна.


    1. alexanderniki
      07.03.2022 01:00

      Поясните, пожалуйста, момент про em/rem.

      Допустим у нас есть компонент-карточка. А еще у нас есть заранее оговоренная система размеров и отступов для карточки.

      Получается, что, если мы зададим размеры карточки и отступы внутри нее в em/rem, то, при изменении базового размера шрифта, "поплывет" вся верстка. Условно говоря, было у нас расстояние между элементами 16px, а стало внезапно 18px. Просто потому что вот так прописали в media queries для этого min-width.

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

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


      1. skeevy
        07.03.2022 11:58

        "поплывет" вся верстка

        поплывет куда? ваша задача делать интерфейс адаптивным. Он должен быть таким, каким его задумал дизайнер, но при этом быть дружелюбным к другим юзкейсам. Речь не только об отступах, а об и респонсивных шрифтах и тот же бутстрап использует у себя rfs

        браузеры весьма неплохо справляются с масштабированием значений в пикселях

        браузер не делает ничего, чтобы ваша верстка оставалась такой, какой она есть на увеличенных/уменьшенных масштабах. А некоторые, в т.ч. и я когда-то, принудительно выключали масштабирование, только потом за это и валидатор и LightHouse по рукам бьет

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

        остается только отступы межды элементами и то, в некоторых юзкейсах, например, том же масштабировании, когда перестраивается интерфейс, отступы в пикселях выглядят отвратительно :)


    1. jtape Автор
      07.03.2022 05:49

      Большое спасибо за комментарий)

      Еще как стоит. В бытность мою работы на фрилансе и галере веб-студии мне приходили макеты только для десктопа, при необходимости самому допиливать мобилку. Даже если и есть мобильные макеты, вы все-равно предлагаете отказаться от rem/em/%?

      em - очень плохо, пришли новые правки, мы например меняем размер шрифта родителя и едут шрифты внутреннего контента. Тут думаю все понятно.

      про rem можно если вы сможете дробно подлить все размеры

      Единица rem задаёт размер относительно размера шрифта элемента <html>.

      например базовый шрифт 16px

      h1 - 38px

      h2 - 20px

      h3 - 18px

      16 собственно 1 rem

      тогда

      h1 - 2.37rem

      h2 - 1.25rem

      h3 - 1.125rem

      если для вас норм писать такие значения и потом в них не путаться, то ок,

      или например придется изменить базовый шрифт в<html> для конкретной страницы, то все ваши h1 h2 h3 поедут и не будут соответствовать дизайну.

      Почему стоит избегать? Опять же, тот же бутстрап позволяет атомарно пересобрать свою сетку просто импортируя к себе нужные scss файлы и дальше вот те примеры по изобретению велосипеда не нужны от слова совсем.

      немного изменил описание для понятности

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


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

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

      "ситуацию переполнения контента" - согласен, тут от проекта к проекту все может быть по разному

      тогда можно пойти след путем

      допустим высота кнопки по дизайну 48px, а шрифт 16px задаем след стили, предполагая что кнопка может быть c переносом шрифта в 2 строки

        max-height: 64px; // высота кнопки + высота шрифта
        min-height: 48px;
        padding: 8px 16px;
        font-size: 16px;

      обычно это кейс редкий (текст кнопки в 2 строки) , но если и делать такое, то наверное следующим путем. Опять же неправильное вставание иконки или лоадера могут сломать высоту равную 48px. Поэтому я думаю если и использовать это для конкретного места, то писать дополнительный класс. Если по дизайну минимальная высота допустим 48px, а высота может быть любой то max-height вовсе не нужен, но в своей практике такое не встречал.


      1. skeevy
        07.03.2022 12:03

        если для вас норм писать такие значения и потом в них не путаться, то ок

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

        обычно это кейс редкий

        в этой кейсе лично я бы оставил только минимальную высоту и в том же rem, т.к. в идеальных условиях будет выглядеть так, как надо, а в иных случаях будут работать связки rem + rfs. Скорее всего у меня в этих случаях не вылезет текст за кнопку и в большинстве нетривиальных кейсов пропорциональность будет более-менее соблюдена


        1. jtape Автор
          07.03.2022 16:17

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

          согласен это решает проблему непонятных размеров, а если например необходимо изменить базовый шрифт страницы пишем в body, думаю стоит дописать это в статье, но что мы получим по факту? ведь по сули используем те же px в миксине, а визуально нечего не меняет. можете дать комментарий?

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


          1. skeevy
            07.03.2022 21:55

            что мы получим по факту

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

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

            Этот миксин всего лишь DX. Пиксель это та единица, которая понятна всем. Пиксель статичен. EM/REM уже относительные единицы и ими оперировать сложнее.
            Миксин позволяет выставить базовый контекст, которым может отличаться от 16 пикселей и указывая размеры, rem будет обозначен относительно контекста. Если у вас контекст, например, 10 пикселей, а шрфит - 16, то вы получаете 1.6. Поменяв контекст, вы получите 1, при этом менять типографику вам не нужно от слова совсем (на случай важных правок)

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

            ваш дизайн обязан строго соответствовать макетам. Для остальных случаев нужен rfs, чтобы не ломать поток. У вас, например, макеты для 320-380, 768, 1360+ пикселей, при этом есть особые виды пользаков и клиентов, которые любят проверять адаптив, изменяя размер окна бразуреа. Я, когда работаю на своем маке самом свежем, часто пользуюсь сплит-скрин режимов до 4х окон и есть сайты, которые уже на полэкрана выглядят просто ужасно, потому что там все прибито гвоздями по пикселям, и расползаются и кнопки, и заголовки, и изображения теряют соотношения сторон, потому что верстальщику/фронтеру было лень добавить немного для того, чтобы во внештатных брейкпоинтах все выглядело более-менее чинно. И меня, будучи верстальщиком, некоторые заказчики этой историей так же выбешивали, и вот до чего я дошел, по сути, и по сей день использую в своих проектах. Если у вас шрифт будет чуть меньше того, что задумал дизайнер на внештатном разрешении - это не страшно, страшно когда он остается такой же и скорее всего он будет ломать поток.

            Есть, например, вот такая статья, которая "поясняет за rem/em" и другие стороны доступности и адаптивности, есть куча других докладов на smashing magazine (тык, тык), css tricks (тык, тык) и т.д., и тот же Вадим Макеев что-то про шрифты и относительные единицы говорил. И даже в приведенных ссылках ведутся дебаты по поводу надо или нет, но лично мои реалии таковы, что лучше перестраховаться


            1. jtape Автор
              09.03.2022 09:01

              Большое спасибо) исправил свои недочеты в статье про использование px и высоту элементов, дополнил и дописал уточнения.

              Действительно, для шрифтов лучше rem или rfs по необходимости.


  1. NarkoMant
    07.03.2022 06:32
    +1

    Большое спасибо за статью, все по делу!


  1. skeevy
    07.03.2022 21:54

    del