Дневники дизайн-системы. Выпуск 2. Цвета и типографика
Предыдущие выпуски:
Типографика
Начал с выбора гарнитуры, определил следующие требования:
- гротеск;
- бесплатный для всех вариантов использования;
- качественная кириллица.
Всем трём критериям соответствует IBM Plex Sans, доступная в гугл-фонтс. Подробнее о ней можно почитать в замечательной статье на «Тайп тудэй», которая и обратила моё внимание на это семейство шрифтов.
Следом определил список стилей.
Минимально достаточным набором посчитал такой:
page name— это h1, самый крупный и самый важный заголовок, обычно он один и чаще всего это название страницы, например заглавие статьи.heading— это h2, название секции или главы.subheading— h3, подзаголовок, именует подразделы.headline— h4, вспомогательный низкоуровневый заголовок для именования незначительных элементов.large text— текстовый стиль для расстановки акцентов, например, такой можно использовать для выделения тезисов в статье или оформления важных цитат.text— стандартный стиль для простого текста.caption— уменьшенный текст: подписи, вспомогательные элементы интерфейса.code— моноширинный текст для фрагментов кода.
Некоторые стили имеют две вариации: для десктопа и для экранов мобильных устройств. На планшетах я обычно применяю десктопные стили.
В своих проектах я использую базовую сетку размером в 4px, поэтому производя расчёт кеглей и интерлиньяжа я ориентировался на этот размер.
Тут важно помнить, что задать явно межстрочный интервал, вписав базовые линии в вертикальный ритм сетки не так просто. Всё потому что в классической типографике интерлиньяж — расстояние между базовыми линиями строк, а в вебе свойство line-height задаёт высоту контейнера строки. Если line-height больше font-size — сверху и снизу появятся отступы, которые будут выбивать элементы из вертикального ритма.
Некоторые ребята конкретно заморачиваются, дотошно вгоняя всё в сетку, я же, ради экономии времени, в этом проекте постараюсь не страдать чрезмерным перфикционизмом и буду стараться соблюдать общий порядок без лишнего пиксель-перфекта.
Расчёт кеглей начал с самого маленького десктопного стиля — caption, задав ему font-size в 15 пикселей.
Добавил 2 пикселя, получил 17 для основного текста и следом продолжил прибавлять каждое следующее число фибонначи: 15+2+3+5+8+13.
Получил ряд: 15, 17, 20, 25, 33, 46 пикселей. Подобрал к нему максимально гармонично выглядящие line-height, которые при этом кратны четырём. Проверил как это всё будет выглядеть вживую и немного скорректировал линейку кеглей на глаз.
Для мобильных устройств уменьшил размеры заголовков h1 – h3, оставив прочие стили неизменными.
Получилась такая таблица стилей:
| Стиль | font-size, px (desk) | line-height, px (desk) | интерлиньяж (desk) | font-size, px (mob) | line-height, px (mob) | интерлиньяж (mob) |
|---|---|---|---|---|---|---|
| page name | 44 | 52 | 1,18 | 35 | 40 | 1,14 |
| heading | 34 | 40 | 1,17 | 28 | 32 | 1,14 |
| subheading | 26 | 32 | 1,23 | 23 | 28 | 1,21 |
| headline | 20 | 24 | 1,2 | 20 | 24 | 1,2 |
| large text | 20 | 28 | 1,4 | 20 | 28 | 1,4 |
| text | 17 | 24 | 1,41 | 17 | 24 | 1,41 |
| caption | 15 | 20 | 1,33 | 15 | 20 | 1,33 |
Обращаю внимание на межстрочный интервал заголовков, уменьшенный относительно простого стиля. Это хорошо заметно в сравнении large text и headline, имеющих одинаковые кегли. Сделано это потому что в меру разреженные текстовые блоки легко читаются, при этом если задать тот же интерлиньяж заголовку, то он визуально «развалится».
После осталось создать стили в фигме.

И написать миксины для вёрстки.
@mixin text-style__page-name {
font-size: 44px;
font-weight: 700;
line-height: 52px;
}
@mixin text-style__page-name_mobile {
font-size: 35px;
font-weight: 700;
line-height: 40px;
}
@mixin text-style__heading {
font-size: 34px;
font-weight: 700;
line-height: 40px;
}
@mixin text-style__heading_mobile {
font-size: 28px;
font-weight: 700;
line-height: 32px;
}
@mixin text-style__subheading {
font-size: 26px;
font-weight: 600;
line-height: 32px;
}
@mixin text-style__subheading_mobile {
font-size: 23px;
font-weight: 600;
line-height: 28px;
}
@mixin text-style__headline {
font-size: 20px;
font-weight: 500;
line-height: 24px;
}
@mixin text-style__large-text {
font-size: 20px;
font-weight: 400;
line-height: 28px;
}
@mixin text-style__text {
font-size: 17px;
font-weight: 400;
line-height: 24px;
}
@mixin text-style__caption {
font-size: 15px;
font-weight: 400;
line-height: 20px;
}
При этом единый для всех стилей font-family и font-style я вынес за скобки, не забыв добавить исключение для фрагментов кода:
html, body {
font-family: "IBM Plex Sans", sans-serif;
font-style: normal;
}
pre, code {
font-family: "IBM Plex Mono", monospace;
}
Палитра
Палитру поделил на три секции:
- градации серого;
- основные цвета;
- сигнальные цвета.
Начну с серой палитры, она состоит из 13 оттенков серого цвета. Замечу, что в моей системе, как и в природе, нет чистого белого и чистого чёрного: $color__white и $color__text, который служит одновременно цветом стандартного текста и чёрным, по сути являются очень светлым и тёмным серым.
Также, мои оттенки серого не нейтральны. Светлые тона имеют едва уловимую примесь жёлтого, тёмные — синего, ведь при естественном освещении светлые области обычно более тёплые, тени — холодные.
Основных цветов у меня два: $color__first и $color__second. Первый и второй — абстракция, позволяющая передавать смысл, без привязки к конкретным названиям. Синий и оранжевый сегодня завтра могут стать зелёным и жёлтым, при этом мне не придётся переписывать названия переменных.
Каждый из цветов имеет по пять градаций: стандарт, два светлых варианта и два тёмных.
Сигнальные цвета — вспомогательная часть палитры. Алармы пригодятся для предупреждений (снова абстракция: сегодня я предупреждаю красным, а завтра оранжевым). Ок-цвета для одобрений и сообщений об успехе.
Итого на момент написания поста моя палитра выглядит так.

А переменные, в соответствующем файле так:
$color__white: rgb(254,253,251); $color__gray_0: rgba(249,248,246,1); $color__gray_1: rgba(241,241,238,1); $color__gray_2: rgba(235,236,234,1); $color__gray_3: rgba(229,232,230,1); $color__gray_4: rgba(225,229,229,1); $color__gray_5: rgba(217,219,221,1); $color__gray_6: rgba(197,200,204,1); $color__gray_7: rgba(169,172,176,1); $color__gray_8: rgba(126,128,132,1); $color__gray_9: rgba(84,85,88,1); $color__gray_10: rgba(56,56,61,1); $color__text: rgba(25,27,40,1); $color__first_ultralight: rgb(159,226,255); $color__first_light: rgb(83,196,244); $color__first_standard: rgb(33,160,215); $color__first_medium: rgb(25,143,207); $color__first_dark: rgb(11,123,184); $color__second_light: rgb(253,149,94); $color__second_ultralight: rgb(255,195,157); $color__second_standard: rgb(243,109,47); $color__second_medium: rgb(243,85,22); $color__second_dark: rgb(214,61,0); $color__alarm_dark: rgb(209,13,0); $color__alarm_standard: rgb(244,32,18); $color__alarm_light: rgb(253,89,79); $color__ok_dark: rgb(29,156,34); $color__ok_standard: rgb(98,205,103); $color__ok_light: rgb(147,231,140);
Эта серия постов — описание процесса, который подразумевает эволюцию продукта. Поэтому если вы читаете пост спустя некоторое время после публикации, имейте ввиду, что это не документация, некоторые вещи в актуальной версии работы могут отличаться от описанного.Актуальную версию можно посмотреть:
Полный список записей серии смотрите по тегу #raw-alfa