Основы визуального дизайна: сетка, типографика, цвет, иерархия
К этому моменту трека у вас уже есть содержание: исследования объяснили, кто пользователь и что ему мешает; персоны и JTBD сформулировали задачу; информационная архитектура разложила систему по полкам; потоки собрали задачу в последовательность экранов; вайрфреймы и прототипы проверили, что последовательность работает. Всё это существовало в серых прямоугольниках. Теперь прямоугольники надо превратить в экран, который человек поймёт за долю секунды — до того, как начнёт читать.
Главная мысль статьи: визуальный дизайн — это не украшение готовой структуры, а способ её передачи. У вас есть иерархия смыслов («это главное действие, это контекст, это редкая настройка»), но у экрана нет способа сказать это словами — есть только размер, вес, цвет, расстояние и позиция. Если вы этими средствами не воспользуетесь осознанно, они всё равно сработают, только случайно: пользователь решит, что главное — самая крупная надпись, даже если это дисклеймер про cookies.
Поэтому каждое решение здесь мы будем выводить из пары «задача пользователя + ограничение». Не «сделаем крупный заголовок, потому что красиво», а «человек сканирует страницу, не читая; сканируется только то, что отличается по размеру и весу; значит, заголовок должен отличаться от текста заметно — минимум на два шага шкалы, иначе разница уйдёт в шум рендеринга». Ограничения тоже реальные: ширина экрана, длина строк в переводе на немецкий, контраст на дешёвой матрице, палец толщиной 10 мм, тёмная тема, зум 200%. И сразу честная рамка: часть материала — воспроизводимые закономерности восприятия (контраст, размер целей, длина строки, близость), часть — устойчивые конвенции (крестик закрытия справа сверху), часть — чистый вкус (радиус скругления 8 или 12). Смешивать их нельзя: за первое надо драться на ревью, за третье — нет. Раздел 9 разбирает эту границу отдельно.
1. Что вообще делает визуальный дизайн
Разложим по функциям — так проще проверять макет, а не «чувствовать».
Пять функций — пять вопросов к любому экрану:
- Приоритет. Если посмотреть на экран полсекунды, что заметно первым? Совпадает ли это с тем, зачем человек сюда пришёл?
- Группировка. Видно ли без чтения, какие элементы связаны? Подпись явно принадлежит своему полю, а не соседнему?
- Аффорданс. Понятно ли, что кликабельно, что редактируемо, а что просто текст?
- Статус. Видно ли, что система делает прямо сейчас и чем закончилось прошлое действие?
- Идентичность. Похоже ли это на ваш продукт — и не мешает ли похожесть первым четырём пунктам?
Первые четыре — инженерия восприятия, они проверяемы. Пятая — брендинг, и она обязана уступать, когда конфликтует. Фирменный светло-серый на белом, который не читается, — это не «айдентика», это баг с оправданием.
2. Как глаз читает экран: минимум теории, который реально нужен
Предвнимание: что видно до того, как вы посмотрели
Часть визуальных различий обрабатывается зрительной системой параллельно по всему полю зрения, за десятки миллисекунд, ещё до осознанного внимания. Это предвнимательные признаки: длина, толщина, размер, ориентация, оттенок, яркость, кривизна, положение, движение. Хороший обзор с интерактивными примерами — Perception in Visualization Кристофера Хили и книга Колина Уэйра «Information Visualization: Perception for Design».
Практический вывод жёсткий: пользователь находит на экране только то, что отличается по предвнимательному признаку. Если ваша главная кнопка отличается от вторичных только текстом на ней — её надо искать чтением, а чтение медленное и требует решения «читать ли». Если статус ошибки отличается только словом «ошибка» мелким шрифтом — его не увидят. И наоборот: если предвнимательно отличаются пятнадцать элементов, не отличается ни один — так рождаются дашборды, где всё кричит.
Отсюда же следует правило одного отличия: чтобы выделить элемент, достаточно одного сильного признака, а не пяти сразу. Кнопка, которая одновременно крупнее, ярче, с тенью, с иконкой, с анимацией и в рамке, — выглядит как реклама, и на неё нападает баннерная слепота (NN/g, Banner Blindness: Old and New Findings).
Гештальт: почему близость сильнее рамок
Гештальт-принципы — это описания того, как зрительная система группирует элементы: близость, сходство, замкнутость, непрерывность, общая судьба (движутся вместе — значит, вместе). Разбор с примерами есть в серии NN/g, начиная с Gestalt Principle of Proximity.
Инженеру достаточно запомнить порядок силы: близость обычно побеждает всё остальное. Если подпись «Телефон» стоит на 8 px выше своего поля и на 6 px ниже предыдущего поля — она читается как относящаяся к предыдущему, сколько бы вы ни ставили рамок и цветов. Это самый частый и самый дешёвый в починке дефект форм, и именно поэтому шкала отступов из раздела 3 — не бюрократия, а инструмент корректности.
Законы Фиттса и Хика: что из них правда
Закон Фиттса (1954, обзор применения в UX — NN/g, формулировка — Wikipedia): время попадания в цель растёт с расстоянием и падает с размером цели. Это надёжная, многократно воспроизведённая закономерность. Следствия, которые действительно работают:
- маленькие кнопки медленнее и ошибочнее — отсюда минимальные размеры целей (WCAG 2.2 требует 24×24 CSS-px, платформенные гайдлайны рекомендуют 44×44 у Apple и 48×48 у Google);
- край экрана — «бесконечно большая» цель, потому что курсор в него упирается; отсюда меню в macOS сверху и панель задач у края;
- частые действия ставят близко к точке, где уже находится внимание и курсор, а опасные — далеко от частых.
Закон Хика (время выбора растёт логарифмически с числом равновероятных вариантов) в UI цитируют куда чаще, чем он заслуживает: он выведен на простых реакциях с равновероятными альтернативами, а не на меню, где человек сканирует, а не перебирает. Хорошая критика собрана в обзоре Interaction Design Foundation. Практический вывод честнее звучит так: длинный список — это не «на 300 мс дольше», это «нужна структура, поиск и разумные умолчания». «Сократите пункты меню до семи, потому что Хик и Миллер» — плохой аргумент; про миф о 7±2 в интерфейсах см. NN/g, Short-Term Memory and Web Usability.
Сканирование, а не чтение
Люди не читают экраны — они сканируют их в поисках зацепок. Паттерны сканирования зависят от вёрстки: на плотных текстовых страницах фиксируется F-образный (NN/g, F-Shaped Pattern), на страницах с выраженной иерархией — переходы по «якорям»: крупный заголовок, выделенное число, картинка, кнопка. F-паттерн — это не рецепт («ставьте всё в форму буквы F»), а симптом: он появляется там, где дизайн не дал зацепок и глазу пришлось грести самому.
3. Сетка, пространство и ритм
Зачем сетка, если можно «на глаз»
Сетка решает три задачи: даёт предсказуемость (элементы выравниваются, глаз не спотыкается), снимает микрорешения (не надо каждый раз выбирать отступ), делает раскладку обсуждаемой («блок на 4 колонки» — это факт, «чуть поуже» — это спор). Плюс, что важно для инженера: сетка и шкала отступов — это то, что переводится в код один в один, в отличие от «ощущения воздуха».
Термины: поле (margin) — свободная зона по краям контейнера; колонка — единица ширины контента; гаттер (gutter) — промежуток между колонками. В вебе типичная схема — 12 колонок (делится на 2, 3, 4, 6), фиксированный гаттер и поля, плавающая ширина колонки. На мобильном — 4 колонки и поля 16. Классика описания раскладки под разные экраны — Responsive Web Design Итана Маркотта и раздел Layout в Material 3.
Важная поправка для инженеров: колоночная сетка — это инструмент, а не закон. Во внутренних инструментах и плотных таблицах она часто мешает; там правит шкала отступов и максимальная ширина текстовых блоков. В CSS Grid вы всё равно опишете раскладку через grid-template-columns, но не обязаны тащить туда двенадцать колонок только потому, что «так в макете».
Шкала отступов: главный рабочий инструмент
Возьмите базовую единицу 4 px и стройте отступы как её кратные: 4, 8, 12, 16, 24, 32, 48, 64. Почему 4, а не «сколько получится»: экраны имеют плотность 1x/2x/3x, кратность 4 переживает масштабирование без полупикселей, а количество допустимых значений сокращается с бесконечности до восьми. Про подход обычно говорят как о 8pt grid, с полушагом 4 для мелких деталей.
Ключевое правило пространства формулируется одной строкой:
Расстояние внутри группы должно быть заметно меньше, чем расстояние между группами. Заметно — это в 1,5–2 раза, а не на 2 px.
Это прямое следствие гештальт-близости, и это тот случай, когда «на глаз» ошибаются систематически: дизайнер видит макет целиком и знает структуру, пользователь — нет.
Разбор. Карточка товара: название, цена, рейтинг, кнопка. Отступы поставлены «чтобы дышало»: везде 16. Пользователь на тесте не может быстро сопоставить цену с товаром в списке из шести карточек — потому что цена одинаково удалена и от своего названия, и от следующей карточки. Починка бесплатная: внутри карточки 8 и 12, между карточками 32. Никаких новых элементов, никакой графики — только перераспределение того же пространства.
Плотность — это продуктовое решение
Сколько воздуха давать — вопрос не эстетики, а сценария. Лендинг читают один раз, там воздух работает на восприятие. Рабочий инструмент, в котором аналитик проводит шесть часов и сравнивает сотни строк, требует высокой плотности: каждый лишний отступ — это минус строка на экране и плюс прокрутка. Отсюда практический приём: закладывайте в дизайн-систему две-три плотности (comfortable / compact), а не спорьте о единственно верном значении. Заодно это снимает половину споров с разработкой: обе версии — токены, а не переверстка.
4. Типографика: 90 % интерфейса — это текст
Посмотрите на любой экран: почти всё, что там есть, — буквы. Значит, типографика — не «оформление», а основная несущая конструкция. Базовый учебник — Practical Typography Мэтью Баттерика, глубокая классика — «The Elements of Typographic Style» Роберта Брингхерста.
Шкала размеров вместо произвольных чисел
Нужно 5–7 размеров, не больше. Строятся они модульной шкалой: базовый размер умножается на коэффициент. Коэффициент 1,125–1,2 даёт спокойную шкалу для плотных интерфейсов, 1,25–1,333 — контрастную для промо-страниц.
# Генерация типографической шкалы и округление к шагу 4 px.
# Сложность: O(n) по времени и O(n) по памяти, n — число ступеней (обычно 7).
def type_scale(base: int = 16, ratio: float = 1.25,
steps: range = range(-1, 6), snap: int = 4) -> list[int]:
"""Модульная шкала size_n = base * ratio**n с прижатием к сетке в snap px."""
# max(snap, ...) не даёт мелким ступеням схлопнуться в ноль
return [max(snap, round(base * ratio ** n / snap) * snap) for n in steps]
print(type_scale()) # [12, 16, 20, 24, 32, 40, 48]
print(type_scale(ratio=1.2)) # [12, 16, 20, 24, 28, 32, 40]
Прижатие к шагу 4 — не педантизм: оно убирает пары размеров вроде 19 и 20 px, которые невозможно отличить, но легко перепутать в коде и в макете. Если два размера в шкале различаются меньше чем на 20 %, один из них лишний.
Пять параметров, которые решают читаемость
| Параметр | Что делает | Рабочий диапазон | Из какого ограничения |
|---|---|---|---|
| Кегль (размер) | базовая различимость | 16 px для основного текста в вебе, 14 — минимум для плотных UI, 12 — только служебное | острота зрения, зум, дешёвые матрицы |
| Интерлиньяж (line-height) | связывает строки в абзац | 1,4–1,6 для текста; 1,1–1,25 для крупных заголовков | глаз должен находить начало следующей строки |
| Мера (длина строки) | удерживает взгляд | 45–75 символов; на мобильном 35–50 | возврат каретки — самая частая точка потери строки |
| Начертание (вес) | создаёт уровни без изменения размера | 400 / 500–600 / 700; не больше трёх весов | различимость веса ниже, чем размера |
| Трекинг | плотность строки | −1…−2 % для крупных заголовков, +2…+5 % для КАПСА | оптическая компенсация размера |
Про меру строки есть неплохой разбор с данными: Readability: The Optimal Line Length у Baymard. В CSS это max-width: 65ch для текстовых блоков — одна строка, которая чинит большую часть «стены текста».
Ещё несколько вещей, которые ломают текст в проде
- Цифры в таблицах. Пропорциональные цифры делают колонку сумм неровной, и сравнивать значения глазом становится тяжело. Лечится
font-variant-numeric: tabular-nums— считайте это обязательным для любых денег и метрик. - Выравнивание. По умолчанию
text-align: left: justify без переносов даёт «реки» из пробелов, а центрирование длинного текста заставляет заново искать каждую строку — центрируйте только 1–3 строки. - КАПС. Убивает форму слова, по которой мы и опознаём слова при сканировании. Годится для коротких меток, не для предложений.
- Локализация. Немецкий и русский длиннее английского в среднем на 20–30 %. Заголовок, который ровно влезает в макете, в проде поедет. Правило: в макете проверяйте самую длинную реалистичную строку, а не «Заголовок».
Типографика как токены
:root {
/* размеры из шкалы 1.25, прижатые к 4 */
--font-size-xs: 12px; /* служебное: подписи, счётчики */
--font-size-sm: 14px; /* плотный UI: таблицы, чипы */
--font-size-md: 16px; /* основной текст — база */
--font-size-lg: 20px; /* подзаголовок раздела */
--font-size-xl: 24px; /* заголовок блока */
--font-size-2xl: 32px; /* заголовок экрана */
--line-height-tight: 1.2; /* заголовки */
--line-height-normal: 1.5; /* текст */
--font-weight-regular: 400;
--font-weight-medium: 600;
}
.prose { max-width: 65ch; line-height: var(--line-height-normal); }
.numeric { font-variant-numeric: tabular-nums; }
Именование по роли (--font-size-md), а не по значению (--font-size-16), — принципиально: значение поменяется, роль останется. Подробнее об этом — в статье про дизайн-системы, а о том, как это живёт в CSS-архитектуре, — в трек frontend.
5. Цвет: не палитра, а роли
Почему «выберем красивые цвета» не работает
Палитра из восьми оттенков, которую передали разработке, в проде превращается в тридцать: понадобился фон hover, граница disabled, цвет ошибки на тёмном, полупрозрачный оверлей. Дальше начинается импровизация. Поэтому цвет проектируют ролями, а не образцами:
оттенки 50…900"] --> R["Семантические роли"] R --> S1["surface / surface-raised
фон и подложки"] R --> S2["text / text-muted
основной и второстепенный текст"] R --> S3["border / border-strong
разделители и рамки"] R --> S4["accent / accent-hover / accent-pressed
главные действия"] R --> S5["danger / warning / success / info
статусы"] S1 & S2 & S3 & S4 & S5 --> T["Светлая и тёмная темы:
роли те же, значения разные"] T --> C["Проверка контраста
для каждой пары текст-фон"]
Роль отвечает на вопрос «зачем этот цвет», а не «какой он». Тогда тёмная тема — это не второй макет, а второй набор значений для тех же ролей, и разработчику не нужно угадывать, чем gray-400 отличается от gray-500.
:root {
--color-surface: oklch(99% 0 0);
--color-surface-raised: oklch(97% 0.005 250);
--color-text: oklch(25% 0.02 250);
--color-text-muted: oklch(50% 0.02 250); /* >= 4.5:1 к surface — проверено */
--color-border: oklch(88% 0.01 250);
--color-accent: oklch(55% 0.16 250);
}
@media (prefers-color-scheme: dark) {
:root {
--color-surface: oklch(21% 0.01 250);
--color-surface-raised: oklch(26% 0.012 250);
--color-text: oklch(95% 0.01 250);
--color-text-muted: oklch(72% 0.02 250); /* светлее, чем в светлой теме */
--color-border: oklch(35% 0.015 250);
--color-accent: oklch(72% 0.14 250); /* насыщенный синий на тёмном слепит */
}
}
Почему OKLCH, а не HSL: в HSL одинаковая «светлота» у разных оттенков воспринимается по-разному (жёлтый на 50 % кажется гораздо светлее синего на 50 %), поэтому шкалы, построенные на HSL, разъезжаются. OKLCH перцептуально равномерен: меняя только L, вы получаете предсказуемые ступени. Практический разбор — OKLCH in CSS.
Три правила цвета, за которые стоит драться
- Цвет не может быть единственным носителем смысла. Обязательное поле, отмеченное только красной рамкой; график, где ряды различаются только оттенком; ссылка, отличающаяся от текста лишь цветом, — всё это не работает при дальтонизме (около 8 % мужчин), в монохромной печати и просто при плохом освещении. Дублируйте цвет иконкой, текстом, формой или подчёркиванием.
- Контраст текста проверяется на этапе макета, а не после релиза. Минимум по WCAG — 4,5:1 для обычного текста и 3:1 для крупного; границы интерактивных элементов — 3:1. Это то место, где «дизайнеру виднее» не аргумент: цифра либо проходит, либо нет. Экспериментальная альтернатива с более точной моделью восприятия — APCA, но нормативом пока остаётся WCAG. Формулы и подробный разбор — в статье Визуальная доступность.
- Насыщенного акцента должно быть мало. Акцент работает как контраст с окружением; если яркими сделаны шапка, сайдбар, кнопки и бейджи, ни один из них не выделяется. Практическое правило: акцентного цвета на экране — единицы процентов площади.
Тени и слои. Тень в интерфейсе несёт один смысл: элемент находится выше остальных (меню, модальное окно, липкая шапка при прокрутке). Из этого следует, что теней должно быть ровно столько, сколько у вас уровней слоя — обычно 3–4, и они должны монотонно нарастать. Реалистичная тень — не одна box-shadow, а две-три с разным радиусом, потому что реальный свет так и работает; разбор с примерами — Designing Beautiful Shadows in CSS. В тёмной теме тень почти не видна — там уровни различают светлотой поверхности (surface-raised), и это надо заложить в роли заранее.
6. Иерархия: как читается экран за полсекунды
Работающий алгоритм построения иерархии — сверху вниз от смысла, а не снизу вверх от стилей:
одна главная задача"] --> B["Выпишите элементы
и присвойте им уровни 1-2-3"] B --> C{"Уровень 1 —
ровно один элемент?"} C -- "нет" --> D["Понизьте лишние:
вторичное действие — контуром или ссылкой"] D --> B C -- "да" --> E["Дайте уровню 1 одно сильное отличие:
размер ИЛИ заливку ИЛИ позицию"] E --> F["Уровень 2 — вес и размер,
без нового цвета"] F --> G["Уровень 3 — приглушённый текст,
меньший кегль"] G --> H["Проверка прищуром:
размойте экран и посмотрите"] H --> I{"Первым виден
элемент уровня 1?"} I -- "нет" --> J["Проблема не в цвете,
а в размере и пространстве"] J --> E I -- "да" --> K["Проверьте на длинном контенте,
в тёмной теме и при зуме 200%"]
Проверка прищуром (squint test) — самый дешёвый и самый честный инструмент из существующих: размойте макет (в Figma это фильтр, в браузере — filter: blur(4px)) и посмотрите, что осталось. Останутся крупные пятна разной плотности — это и есть то, что увидит пользователь в первые 300 мс. Если после размытия все пятна одинаковы, иерархии нет, сколько бы уровней вы ни задумали.
Разбор: «пользователь не нашёл кнопку»
Классическая ситуация с юзабилити-теста: человеку нужно отправить заявку, кнопка «Отправить» на экране есть, но участник её не находит и говорит «а где тут дальше?». Причин, как правило, пять, и лечатся они по-разному:
без прокрутки?"} Q1 -- "нет" --> A1["Ложное дно: край экрана выглядит как конец страницы.
Фикс: обрезать следующий блок краем, убрать полноэкранную секцию,
липкая панель действий на мобильном"] Q1 -- "да" --> Q2{"Она выделена
сильнее соседей?"} Q2 -- "нет" --> A2["Конкуренция равных: три кнопки одного веса.
Фикс: один primary, остальные — контур и текстовая ссылка"] Q2 -- "да" --> Q3{"Она похожа
на рекламу?"} Q3 -- "да" --> A3["Баннерная слепота: яркий блок у края, градиент, восклицательный знак.
Фикс: вернуть в поток контента, снять украшения"] Q3 -- "нет" --> Q4{"Она похожа
на кнопку?"} Q4 -- "нет" --> A4["Плоская метка без сигнификаторов.
Фикс: заливка или контур, курсор, состояние hover и focus"] Q4 -- "да" --> Q5{"Её искали
не там?"} Q5 -- "да" --> A5["Нарушена конвенция размещения.
Фикс: класть действие туда, где заканчивается задача,
а не туда, где осталось место в макете"]
Про ложное дно (иллюзию завершённости) есть отдельный разбор с примерами: NN/g, The Illusion of Completeness. Про плоские элементы без сигнификаторов — исследование NN/g Flat UI Elements Attract Less Attention and Cause Uncertainty: участники дольше искали кликабельные элементы и чаще сомневались, когда у тех не было ни границы, ни заливки, ни тени. Это один из немногих случаев, когда «модный стиль» имеет измеренную цену.
Обратите внимание на структуру разбора: сначала гипотеза о причине, потом починка. «Сделаем кнопку ярче» помогает только в одном из пяти случаев, а в случае баннерной слепоты — вредит.
7. Разбор: почему эта форма неудобна
Форма — идеальный полигон, потому что в ней всё видно. Возьмём типичную форму оформления заказа и разберём её по дефектам.
Дефект 1. Плейсхолдер вместо подписи. Экономит место, ломает всё остальное: подпись исчезает при вводе (человек забывает, что вводил), контраст плейсхолдера обычно ниже нормы, пустое поле выглядит уже заполненным, автозаполнение конфликтует. Данные и разбор — Baymard, Place Labels Above the Field. Фикс: подпись над полем, всегда видимая. Плейсхолдер — только для примера формата, и никогда для обязательной информации.
Дефект 2. Две колонки полей. Глаз теряет порядок: то ли читать вниз, то ли вправо; на мобильном всё равно схлопнется в одну. Baymard прямо рекомендует избегать многоколоночных форм. Исключение — короткие логически связанные пары («Город» + «Индекс», месяц + год срока карты), которые визуально объединены в одну группу.
Дефект 3. Ширина поля не соответствует данным. Поле индекса шириной во весь экран сообщает «сюда влезет много» — и человек сомневается, правильно ли понял. Ширина поля — это аффорданс длины: индекс узкий, адрес широкий. Дешёвый приём, который заметно снижает число ошибок.
Дефект 4. Отступы «поровну». Тот самый случай из раздела 3: подпись равноудалена от своего и от чужого поля. При десяти полях человек начинает перепроверять каждую пару, и заполнение растягивается.
Дефект 5. Ошибка не рядом с причиной. Сводка «Исправьте ошибки в форме» вверху, а поле с проблемой — на два экрана ниже. Фикс: сообщение под конкретным полем, плюс сводка со ссылками для длинных форм, плюс фокус в первое ошибочное поле.
Дефект 6. Валидация срабатывает в момент ввода. Человек ещё печатает ivan@, а форма уже кричит «неверный адрес». Разумное поведение: проверять при потере фокуса, а после первой ошибки — обновлять статус на лету, чтобы человек видел, что починил.
Дефект 7. Не нарисованы состояния. Что показывать, пока идёт отправка? Что, если сервер ответил 500? Что, если список пуст? Если этого нет в макете, разработчик сделает как получится, и вы увидите результат на демо. Состояния — часть дизайна, а не часть реализации; подробнее — в статье Взаимодействие и состояния.
Формулировки самих сообщений — отдельная большая тема, она в статье про текст в интерфейсе. Техническая реализация форм и валидации разобрана во frontend, а доступные формы — в accessibility.
8. Доступность как часть визуальных решений
Доступность подробно разобрана в отдельном треке accessibility и в статье трека Доступность на этапе дизайна. Здесь — только то, что решается прямо в момент выбора шрифта, цвета и отступов, и то, что потом чинится дорого:
- Контраст текста и границ — проверяется на макете плагином, а не на релизе. Приглушённый серый текст — самый частый дефект и самый простой в предотвращении.
- Не только цвет. Ошибка = цвет + иконка + текст. Ряд на графике = цвет + форма маркера или подпись.
- Размер и разнос целей. Минимум 24×24 CSS-px по WCAG 2.2, комфортно — 44–48; между соседними целями нужен зазор, иначе палец промахивается.
- Состояние фокуса. Оно должно быть нарисовано в макете так же обязательно, как hover. Если фокус не нарисован, его либо не сделают, либо сделают неразличимым — а это ломает всю клавиатурную навигацию (см. Клавиатура и фокус).
- Порядок чтения. Визуальный порядок должен совпадать с порядком в разметке. Если в макете вы поставили важный блок справа, а в вёрстке он окажется в конце DOM, скринридер и клавиатура получат другой интерфейс.
- Масштабирование. Макет в фиксированных пикселях скрывает проблему: посмотрите, что будет при увеличении текста в 2 раза. Обычно ломаются кнопки с фиксированной высотой и однострочные заголовки.
Правило простое: доступность на этапе дизайна — это не отдельный этап, а пять галочек в момент, когда вы всё равно выбираете цвет и размер. Стоимость — минуты. Стоимость починки после релиза — переработка компонентов.
9. Где заканчиваются закономерности и начинается вкус
Самая полезная профессиональная привычка — различать три категории утверждений. Иначе ревью макета превращается в конкурс мнений, где побеждает самый громкий.
Есть исследования и они воспроизводятся: контраст, размеры целей, длина строки, подписи над полями, потеря плейсхолдера, стоимость отсутствия сигнификаторов. Это требования, а не предпочтения.
Есть устойчивые конвенции. Крестик закрытия справа сверху, логотип слева и ведёт на главную, корзина справа, обязательные поля со звёздочкой, красный = опасно (в западной культуре; в Китае красный — благоприятный цвет, а в биржевых интерфейсах Восточной Азии рост часто красный, а падение зелёное). Конвенции не «правильны» сами по себе — они экономят обучение. Нарушать можно, но нужно очень хорошее объяснение и проверка тестом. Это ровно тот случай, когда «у всех так» — валидный аргумент: у всех так, потому что пользователь пришёл к вам с чужим опытом.
Вкус. Радиус скругления, точный оттенок акцента, гротеск или антиква, стиль иллюстраций, тени против границ, плотность. Здесь нет правильного ответа, есть только последовательность: любой выбор, применённый системно, лучше метаний. Золотое сечение как «закон красоты» — миф, устойчиво живущий в дизайнерских презентациях; критический разбор — колонка Кита Девлина.
Отдельный сюжет — мода, и у неё бывает измеримая цена:
Вывод не «мода — зло», а «у каждой моды есть параметр, который она ухудшает; знайте какой». Плоский стиль ухудшает распознавание кликабельного — компенсируйте состояниями и границами. Стекло ухудшает контраст — подкладывайте непрозрачный слой под текст. Так вы получаете и современный вид, и работающий интерфейс.
И ещё одна честная вещь: эстетика влияет на восприятие удобства. Эффект aesthetic-usability (Kurosu & Kashimura, CHI 1995) показывает, что более красивые интерфейсы люди оценивают как более удобные — и, что важнее для практики, прощают им мелкие проблемы. Обратная сторона: красота маскирует дефекты на тестах, поэтому измерять надо поведение (успех задачи, время, ошибки), а не оценки. Об этом — в статьях про юзабилити-тестирование и метрики.
10. Совместная работа с разработкой
Что такое нормальная передача макетов
Плохая передача — это ссылка на файл и сообщение «готово, забирайте». Хорошая передача — это передача решений и правил, а не картинок. Картинка описывает один частный случай: один размер экрана, один язык, один набор данных, одно состояние. Продукт живёт во всех остальных.
Минимальный комплект, без которого макет не считается сданным:
- Токены: размеры, цвета (роли, обе темы), типографика, радиусы, тени, длительности анимаций — с именами, а не значениями.
- Состояния каждого интерактивного элемента: default, hover, focus, active, disabled, loading, error. Плюс состояния экрана: пусто, мало данных, много данных, ошибка загрузки, нет прав.
- Поведение при изменении размера: что тянется, что фиксировано, что переносится, где брейкпоинты и почему именно там (брейкпоинт ставится там, где ломается контент, а не по списку моделей телефонов).
- Правила для контента: что при переполнении (обрезка с многоточием, перенос, скролл), максимальная длина, что если поле пустое, как выглядит очень длинное имя и очень большое число.
- Что переиспользуется: какие элементы — существующие компоненты системы, какие — новые, и почему новые.
- Приоритеты: что здесь обязательное, а что «если успеем». Без этого разработчик режет по своему усмотрению и обычно режет состояния.
Ключевой момент диаграммы — разговор до финальной отрисовки. Половина конфликтов «так нельзя сделать» рождается из того, что дизайнер узнаёт об ограничении (данные приходят пачками, у API нет нужного поля, компонент библиотеки не умеет так) после того, как отрисовал сорок экранов.
Почему «пиксель в пиксель» — плохая цель
Звучит как признак качества, а на практике это требование сделать интерфейс идентичным картинке. Проблемы:
- Макет — это модель, а не спецификация. В нём один текст, одна ширина, один язык, одно состояние. Точное воспроизведение частного случая не гарантирует ничего в остальных.
- Реальность не пиксельная. Шрифты растеризуются по-разному в разных ОС и браузерах;
line-heightдаёт полупиксели; субпиксельное сглаживание меняет видимую толщину; на 1x и 2x-экранах граница в 1 px выглядит по-разному. Требуя совпадения до пикселя, вы требуете невозможного, а значит, приучаете команду к ритуалу вместо результата. - Цена не там. Час на выравнивание отступа на 2 px — это час, не потраченный на состояние ошибки, которое пользователь увидит.
- Ломается адаптивность. «Пиксель в пиксель» тянет к фиксированным размерам, а фиксированные размеры ломаются при зуме, длинном тексте и локализации — то есть у тех самых пользователей, которым труднее всего.
- Гасит инженерное суждение. Разработчик видит проблему («при 320 px этот блок не влезает») и молчит, потому что задача — повторить макет.
Что вместо этого:
- Общий язык токенов. Если и макет, и код говорят «space-16» и «text-muted», расхождения ловятся автоматически, а не глазами. Проверять «использованы ли токены» можно линтером — это дешевле, чем сравнивать скриншоты.
- Приоритезированный список расхождений и явные допуски. Три уровня: (1) ломает смысл или иерархию — чиним всегда; (2) заметно на глаз с расстояния вытянутой руки — чиним; (3) видно только при наложении скриншотов — не чиним без причины. Договоритесь заранее: отступы — точно по шкале, шрифты — точно по токенам, всё остальное — «визуально совпадает».
- Приёмка компонента, а не экрана. Компонент принимается один раз со всеми состояниями; экран собирается из принятых компонентов, и его приёмка становится быстрой.
- Визуальные регресс-тесты для компонентов (Playwright/Chromatic и подобные) — они ловят непреднамеренные изменения, которые человек не заметит. Это как раз тот случай, где «пиксель в пиксель» уместен: против самого себя во времени, а не против макета.
Полезная формулировка для команды: цель — не совпадение с макетом, а совпадение с намерением макета. Если разработчик сделал отступ 24 вместо 20, потому что при 20 текст слипался на длинном варианте, это не дефект, а улучшение — и повод обновить макет.
Что дизайнеру полезно знать про код
Не «уметь верстать», а понимать три вещи, которые каждый день влияют на решения: что размеры бывают относительными и текст может увеличиться; что раскладка описывается правилами (flex и grid), а не координатами; что состояния — это код, и каждое нарисованное состояние стоит работы. Обратно для разработчика: понимать, что «поправь отступ» — это не каприз, если отступ ломает группировку. Подробнее про совместный процесс и карьеру — в финальной статье трека.
11. Практика: ревью макета за пятнадцать минут
Последовательность, которую можно применять к чужому и своему макету одинаково.
- Прищур. Размыть. Что видно первым? Совпадает с главной задачей экрана?
- Один primary. На экране одно действие выделено сильнее прочих? Если два — почему?
- Группы. Внутренние отступы меньше внешних? Каждая подпись явно принадлежит своему элементу?
- Шкалы. Все отступы из шкалы? Все размеры шрифта из шкалы? Все цвета — роли, а не случайные значения?
- Контраст. Прогнать текст и границы плагином. Нет исключений «тут дизайнерский серый».
- Длинный контент. Подставить самое длинное имя, самое большое число, текст на 30 % длиннее. Что поедет?
- Пустой контент. Ноль записей, нет аватара, нет прав. Нарисовано?
- Состояния. hover, focus, active, disabled, loading, error — есть для всего кликабельного?
- Мобильный. 320–360 px по ширине: что перестраивается, а что просто уменьшается до нечитаемого?
- Тёмная тема. Роли работают, тени заменены светлотой поверхностей?
- Клавиатура и переиспользование. Порядок обхода совпадает с визуальным, фокус виден? Что здесь новое и почему нельзя было взять существующий компонент?
Пункты 1–4 ловят большую часть провалов иерархии, 5–8 — большую часть багов реализации, 9–11 — большую часть переработок.
12. Типичные ошибки
- Украшать вместо структурирования. Иконки, градиенты и иллюстрации не создают иерархию; иерархию создают размер, вес и пространство. Если экран непонятен, добавление картинок его не спасёт.
- Слишком много уровней. Пять размеров шрифта, четыре веса, три акцентных цвета на одном экране — это ноль иерархии.
- Отступы «на глаз». 13, 17, 23 — верный признак, что макет соберут по-своему, а спор потом будет о числах, а не о смысле.
- Плейсхолдер вместо подписи. Дёшево выглядит, дорого обходится.
- Цвет как единственный сигнал. Ломается у части пользователей полностью.
- Дизайн на идеальных данных. Имя из шести букв, три записи в списке, число 42. В проде — имя на 40 символов, ноль записей и 1 284 903,55.
- Забытые состояния. Экран без loading/empty/error — это половина экрана.
- Тёмная тема как инверсия. Простое переворачивание светлоты даёт слепящие акценты и невидимые границы.
- Фиксированные высоты. Ломаются при зуме, длинном тексте и локализации — то есть у самых уязвимых пользователей.
- «Пиксель в пиксель» как KPI. Ритуал вместо качества; съедает время, которое стоило потратить на состояния и крайние случаи.
- Спор о вкусе в тоне спора о фактах. Быстро разрушает доверие между дизайном и разработкой. Отделяйте требования от предпочтений вслух.
13. Мини-итог
- Визуальный дизайн передаёт структуру. Средств всего пять: размер, вес, цвет, расстояние, позиция — и работают они предвнимательно, до чтения.
- Выделяйте одним сильным отличием, а не пятью сразу: пять отличий у всех элементов — это отсутствие отличий.
- Близость сильнее рамок и цветов: расстояние внутри группы должно быть заметно меньше, чем между группами.
- Шкалы (отступов, размеров, цветовых ролей) заменяют сотни микрорешений и делают макет проверяемым, а не обсуждаемым: типографика здесь несущая конструкция — 5–7 размеров, интерлиньяж 1,4–1,6, мера 45–75 символов, табличные цифры для чисел.
- Цвет проектируется ролями; контраст — требование с числом, а не мнение; цвет никогда не единственный носитель смысла.
- Иерархия проверяется прищуром за десять секунд, и это дешевле любого обсуждения.
- Отделяйте исследованные закономерности от конвенций и от вкуса — и говорите о них разным тоном.
- Нормальная передача — это токены, состояния, правила поведения контента и ранний разговор; «пиксель в пиксель» — плохая цель, правильная цель — совпадение с намерением макета.
Источники
- Adam Wathan, Steve Schoger. Refactoring UI — практическая книга по визуальным решениям для инженеров.
- Robert Bringhurst. The Elements of Typographic Style; Matthew Butterick. Practical Typography.
- Colin Ware. Information Visualization: Perception for Design; Christopher Healey. Perception in Visualization.
- Nielsen Norman Group: Flat UI Elements, Illusion of Completeness, F-Shaped Pattern, Aesthetic-Usability Effect.
- Baymard Institute: подписи над полями, многоколоночные формы, длина строки.
- W3C: SC 1.4.3 Contrast, SC 2.5.8 Target Size, Design Tokens Format.
- Material Design 3: Typography и Layout; Apple HIG: Typography; OKLCH in CSS; Designing Beautiful Shadows; Brad Frost, Atomic Design.
Что дальше
Мы разобрали визуальные решения поштучно: эта шкала, эта роль цвета, этот отступ. В продукте таких решений тысячи, и держать их в голове невозможно — нужен механизм, который превращает решения в переиспользуемые компоненты и токены, живёт вместе с кодом и не устаревает через полгода. Об этом — следующая статья: Дизайн-системы: компоненты, токены, документация, жизнь системы.