Меню
Поиск

Интерфейс и визуал · Цвет и контраст

Как проверить контраст всех пар на экране и собрать тёмную тему на тех же ролях

Основной текст проходит почти всегда, а проваливаются подписи, ошибки, рамки полей, фокус и ссылки. В уроке разберём нормы контраста для текста и элементов, замерим экран оплаты целиком, сделаем неактивную кнопку без одной прозрачности и соберём тёмную тему заменой значений тех же ролей. Для практики — экран оплаты магазина кофе со слоем замеров, светлая и две тёмные темы и тренажёр «проходит ли пара».

Пример для всего урока. Магазин кофе из урока про палитру. Палитра с ролями уже есть, и теперь по ней собирают экран оплаты и тёмную тему. Первый вариант экрана «на глаз» выглядит аккуратно. Замерим его и посмотрим, что из этого читается.

1Нормы контраста

Контраст — отношение яркостей двух цветов: от 1 : 1, когда цвета одинаковы, до 21 : 1 — чёрный на белом.

Нормы задаёт WCAG, стандарт доступности веба. Уровень AA — тот, на который обычно равняются продукты:

ЧтоAAAAA
Обычный текст4,5 : 17 : 1
Крупный текст — от 18 pt, это 24 px, или от 14 pt жирным, около 18,5 px3 : 14,5 : 1
Значки, рамки полей, рамка фокуса — всё, по чему видно элемент и его состояние3 : 1—
Не требуют контрастаДекор, текст внутри логотипа, неактивные элементы, текст на фотографии, где он не главное

Пороги не округляют. В пояснениях к WCAG прямо сказано, что 4,499 : 1 норму 4,5 : 1 не проходит, даже если инструмент покажет «4,5».

У рамки фокуса есть и отдельное правило уровня AAA, критерий 2.4.13. Рамка не тоньше 2 px по периметру и 3 : 1 между видом с фокусом и без.

Мерят пару: цвет и фон, на котором он стоит на самом деле. Один и тот же серый проходит на белом и не проходит на светло-сером фоне карточки.

2Замер всех пар на экране

Контраст перестаёт быть делом удачи, когда замерены все пары, включая подписи, ошибки и фокус.

Экран оплаты в двух вариантах. Числа рядом с местами — замеры: ✓ — норма выполнена, ✗ — нет. Нажмите «Контраст», чтобы спрятать или показать их.

Оплата · на глаз и после замеров

На глаз

←Оплата
Номер карты3,51 ✗
4276 3800 1234 5671,31 ✗
✕ Не хватает одной цифры2,66 ✗
Срок действия
12/281,75 ✗
Изменить адрес доставки3,94 ✗
Оплатить 3 480 ₽5,81 ✓

После замеров

←Оплата
Номер карты5,93 ✓
4276 3800 1234 5673,51 ✓
✕ Не хватает одной цифры5,58 ✓
Срок действия
12/285,81 ✓
Изменить адрес доставки5,81 ✓
Оплатить 3 480 ₽5,81 ✓
Слева пять провалов из шести замеров: подпись поля, рамка поля, текст ошибки, рамка фокуса и ссылка. Основной текст и кнопка проходили и так — их обычно и проверяют. Разделитель не замерен: это декор, норма к нему не относится.

Что изменилось

МестоНормаНа глазПосле
Подпись поля, 13 px4,5 : 13,51 : 15,93 : 1 — вторичный текст
Рамка поля3 : 11,31 : 13,51 : 1 — своя роль «граница поля»
Текст ошибки4,5 : 12,66 : 15,58 : 1 — тёмный красный
Рамка фокуса3 : 11,75 : 15,81 : 1 — цвет действия, 2 px
Ссылка4,5 : 13,94 : 15,81 : 1 — тот же синий, что у кнопки

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

3Не только основной текст

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

  • Подписи и подсказки. Их делают серее основного текста — и часто перебарщивают. Мелкий кегль не даёт скидки: норма для обычного текста та же.
  • Текст в поле до ввода. Подсказка вроде «0000 0000 0000 0000» — тоже текст. Её читают, чтобы понять формат.
  • Ошибки и статусы. Красный для ошибки часто выбирают по «тревожности» и забывают замерить. Светлый красный на белом не проходит.
  • Рамки полей и фокуса. Если поле отличается от фона только рамкой, рамка должна давать 3 : 1: без неё поле не найти. Рамка фокуса — тоже: по ней человек с клавиатурой видит, где он.
  • Ссылки внутри абзаца. Синий на белом может давать 5,81 : 1, но от чёрного текста рядом он отличается лишь на 2,84 : 1. Если ссылка выделена только цветом, между ней и текстом нужно не меньше 3 : 1. Проще подчеркнуть ссылку — тогда вопрос снимается.

4Неактивное без одной прозрачности

Неактивная кнопка должна выглядеть недоступной, а не стёртой.

Самый быстрый способ сделать кнопку неактивной — прозрачность 40 %. Надпись на такой кнопке получается 1,86 : 1.

WCAG контраста от неактивных элементов не требует. Но прочитать, что написано на кнопке, человеку всё равно нужно: иначе непонятно, что станет доступно, когда он заполнит форму.

Кнопка «Оплатить», пока номер карты не введён

Прозрачность 40 %

Оплатить 3 480 ₽1,86

Свои цвета неактивного

Оплатить 3 480 ₽5,04
Слева надпись почти пропала, и кнопка похожа на ту, что ещё загружается. Справа у неактивного своя пара цветов: серая подложка и вторичный текст, надпись читается, а кнопка выглядит выключенной.

Почему не прозрачность

  • Надпись становится нечитаемой. Прозрачная подложка смешивается с белым фоном, и контраст надписи падает с 5,81 : 1 до 1,86 : 1.
  • Результат зависит от фона. На картинке или цветной плашке прозрачная кнопка смешивается с тем, что под ней, и выглядит каждый раз по-разному.
  • Неактивное путают с загрузкой. Полупрозрачным часто рисуют то, что ещё не появилось.

В тёмной теме Material 2 неактивное задают как раз прозрачностью белого — 38 % для надписи. На однотонном фоне так можно, но контраст всё равно придётся измерить в каждой теме, а отдельный цвет для неактивного держать под контролем проще.

У неактивного своя пара цветов в палитре: подложка и текст. Надпись читается, а рядом с активной кнопкой видно, что эта выключена. Хорошо ещё написать, что нужно сделать: «Введите номер карты».

Нужна ли неактивная кнопка вообще или лучше оставить кнопку доступной и показать ошибку, разобрано в уроке «Компоненты и варианты», Middle.

5Тёмная тема на тех же ролях

Тёмная тема — не второй макет, а те же роли с другими значениями.

В палитре уже есть роли: фон, текст, вторичный текст, граница поля, действие, ошибка.

Для тёмной темы у каждой роли появляется второе значение, а экраны не перерисовывают: они и так ссылаются на роли. Переключите вариант ниже.

Оплата · светлая и две тёмные

Светлая

←Оплата
Номер карты5,93 ✓
4276 3800 1234 5673,51 ✓
✕ Не хватает одной цифры5,58 ✓
Изменить адрес доставки5,81 ✓
Оплатить 3 480 ₽5,81 ✓
Всё проходитЭто экран из раздела 2.

Тёмная, те же акценты

←Оплата
Номер карты7,82 ✓
4276 3800 1234 5673,96 ✓
✕ Не хватает одной цифры3,18 ✗
Изменить адрес доставки3,06 ✗
Оплатить 3 480 ₽5,81 ✓
Акценты тонутНейтральные роли получили тёмные значения, а синий и красный остались от светлой темы. Кнопка держится, потому что белый на синем не изменился, а ссылка и ошибка на тёмном фоне упали до 3 : 1.

Тёмная, свои акценты

←Оплата
Номер карты7,82 ✓
4276 3800 1234 5673,96 ✓
✕ Не хватает одной цифры6,68 ✓
Изменить адрес доставки7,30 ✓
Оплатить 3 480 ₽7,06 ✓
Всё проходитУ действия и ошибки в тёмной теме свои, более светлые значения. Текст на кнопке стал тёмным: на светлом синем белый бы не прочитался.
Разметка экрана во всех трёх вариантах одна и та же. Меняются только значения ролей.

Роли в двух темах

РольСветлаяТёмная
Фон#FFFFFF#15181C
Поверхность#F4F6F8#1E2227
Основной текст#1B1F24#E8EBEE
Вторичный текст#5B6570#A3ADB8
Граница поля#808A94#6E7883
Действие#1D5FD1#7AA7F0
Текст на действии#FFFFFF#0B1B33
Ошибка#C23030#F07C7C

Что меняется в тёмной теме

  • Акцент светлее. Насыщенный синий, который хорош на белом, на тёмном фоне теряет контраст. В Material Design 3 это заложено в саму схему. Основной цвет в светлой теме берут из тона 40 тональной палитры, в тёмной — из тона 80.
  • Фон не чисто чёрный. Material Design советует тёмно-серую поверхность #121212: на сером видны тени, а светлый текст на нём меньше режет глаз, чем на чёрном. Насыщенные цвета на тёмном фоне, по словам Material, ещё и «вибрируют», поэтому акценты берут приглушённее.
  • Текст на акценте меняется. На светлом акценте нужен тёмный текст, поэтому роль «текст на действии» в тёмной теме тоже получает своё значение.
  • Замер заново. Пары, которые прошли в светлой теме, в тёмной надо мерить отдельно: в варианте «те же акценты» провалились две из пяти. Apple в руководстве по тёмной теме просит держать не меньше 4,5 : 1, а для своих цветов в мелком тексте стремиться к 7 : 1.
Тёмная тема, собранная отдельным макетом, расходится со светлой. Через месяц в одной есть новый статус, а в другой нет. Когда обе темы — значения одних ролей, новое место на экране получает оба цвета сразу.

6Чем мерить

На глаз контраст не определить: одна и та же пара на разных экранах выглядит по-разному.

  • WebAIM Contrast Checker — два цвета на входе, на выходе отношение и отметки: обычный текст, крупный текст, графика и элементы интерфейса.
  • Who Can Use — показывает, как пару видят люди с тринадцатью разными особенностями зрения, а ещё на ярком солнце и в ночном режиме экрана.
  • Stark — плагин для Figma: контраст и имитация нарушений цветового зрения прямо в макете.
  • Figma — в палитре цвета есть кнопка Check color contrast: она мерит пару по уровням AA и AAA для обычного текста, крупного текста и графики.
  • Chrome DevTools — в палитре цвета у текста показано отношение к фону с отметками AA и AAA. А во вкладке Rendering можно имитировать нарушения цветового зрения и сниженный контраст.
Замер записывают таблицей: место, цвет, фон, отношение, норма, светлая и тёмная тема. Такую таблицу можно проверить заново после любой правки палитры.

7Проходит или нет

Одно и то же отношение проходит для одного места и не проходит для другого.

Тренажёр · проходит ли пара
  1. Подпись поля, 13 px, обычное начертание: 3,51 : 1.

  2. Заголовок экрана, 24 px: 3,62 : 1.

  3. Рамка поля ввода на белом, фон поля тоже белый: 1,31 : 1.

  4. Надпись внутри логотипа магазина в шапке: 2,1 : 1.

  5. Надпись на неактивной кнопке «Оплатить»: 1,86 : 1.

  6. Ссылка внутри абзаца, без подчёркивания: к белому фону 5,81 : 1, к чёрному тексту рядом 2,84 : 1.

  7. Рамка фокуса 2 px цвета действия на белом: 5,81 : 1.

  8. Подсказка «0000 0000 0000 0000» в пустом поле: 2,53 : 1.

  9. Тонкая линия-разделитель между блоками: 1,31 : 1.

Опирайтесь на таблицу норм из раздела 1 — уровень AA.

8Задание

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

Часть 1 · Замерить, 30 минут

  1. Выберите экран с формой, ссылками, ошибкой и кнопками — в том числе неактивной.
  2. Выпишите все пары: каждый текст с его фоном, рамки полей, рамку фокуса, значки.
  3. Замерьте каждую и отметьте норму: обычный текст, крупный, граница или «не требует».
Таблица замеров · светлая и тёмная
ЭКРАН: ______________________        Дата: __.__.____

МЕСТО              | РОЛЬ ЦВЕТА        | НОРМА | СВЕТЛАЯ     | ТЁМНАЯ
основной текст     | текст / фон       | 4,5   | ____ : 1    | ____ : 1
подпись поля       | вторичный / фон   | 4,5   | ____ : 1    | ____ : 1
подсказка в поле   | ______ / ______   | 4,5   | ____ : 1    | ____ : 1
текст ошибки       | ошибка / фон      | 4,5   | ____ : 1    | ____ : 1
ссылка             | действие / фон    | 4,5   | ____ : 1    | ____ : 1
текст на кнопке    | на действии / действие | 4,5 | ____ : 1 | ____ : 1
рамка поля         | граница / фон     | 3     | ____ : 1    | ____ : 1
рамка фокуса       | ______ / фон      | 3     | ____ : 1    | ____ : 1
значок             | ______ / ______   | 3     | ____ : 1    | ____ : 1
неактивная кнопка  | ______ / ______   | —     | ____ : 1    | ____ : 1

ПРОВАЛЫ И ЧТО ПОМЕНЯЛИ: ___________________________________
В колонке «Роль цвета» пишите роль из палитры, код цвета там не нужен: так таблица переживёт смену значений.

Часть 2 · Починить, 30 минут

  1. Каждый провал чините ролью из палитры: темнее вторичный текст, своя граница поля, тёмный оттенок ошибки.
  2. Неактивное состояние переведите с прозрачности на свою пару цветов.

Часть 3 · Тёмная тема, 40 минут

  1. Для каждой роли задайте тёмное значение. В Figma — второй режим той же коллекции переменных.
  2. Переключите экран на тёмный режим и заполните колонку «Тёмная».
  3. Провалы тёмной темы чините тёмными значениями, светлые не трогайте.
Как понять, что задание выполнено. В таблице нет пары ниже нормы ни в светлой теме, ни в тёмной.

Что должно получиться

  • Экран в двух темах на одних ролях.
  • Таблица замеров по обеим темам.
  • Список поправок: что провалилось и чем починили.

План работы: 30 минут на замеры, 30 на починку, 40 на тёмную тему. Всего — около двух часов.

Частые сложности

  • «Бренд не разрешает темнее». Фирменный цвет может остаться на кнопке с крупной надписью или в иллюстрациях. Для текста и ссылок нужен оттенок, который проходит.
  • «Серый текст выглядит элегантнее». Элегантно, пока его можно прочитать. Возьмите самый светлый серый, который проходит 4,5 : 1, — он всё равно заметно светлее основного текста.
  • «Тёмную тему делает другой дизайнер». Договоритесь о списке ролей до начала. Иначе получатся два набора цветов, которые не сходятся.
  • «В Figma нет режимов на нашем тарифе». Заведите тёмные значения второй коллекцией с теми же именами. Главное — роли одни.

9Чек-лист и ошибки

Контраст под контролем, если

  • Замерены все текстовые пары, включая подписи и ошибки
  • Текст — от 4,5 : 1, крупный текст — от 3 : 1
  • Рамки полей, фокуса и значки — от 3 : 1
  • Ссылки в тексте отличаются не только цветом
  • У неактивного своя пара цветов, надпись читается
  • Тёмная тема — те же роли с другими значениями
  • Акценты в тёмной теме светлее, текст на них перепроверен
  • Таблица замеров есть для обеих тем

Что мешает

  • Проверили только основной текст. Подписи, ошибки и фокус провалились незаметно.
  • Мягкий цвет ошибки. Розовый на белом — 2,66 : 1.
  • Бледная рамка поля. Поле сливается с фоном.
  • Неактивное прозрачностью. Надпись не прочитать.
  • Тёмная тема отдельным макетом. Темы расходятся с каждой правкой.
  • Те же акценты на тёмном фоне. Ссылки и ошибки тонут.

10Три ступени темы

На прошлой ступени собирали палитру с ролями. Здесь — проверяли её контрастом и собирали вторую тему на тех же ролях. Дальше — описать цветовую систему так, чтобы по ней работала вся команда.

СтупеньЧто нужно уметьКак проверить результат
Junior Собрать палитру из ограниченного набора; дать каждому цвету роль; отличать оттенок для поверхности от оттенка для текста; находить дубли; не передавать статус одним цветом Для каждого цвета на экране можно назвать его роль, цветов без роли не осталось
Middle — этот урок Мерить контраст текста, значков, границ и состояний; собирать тёмную тему на тех же ролях; не гасить неактивное одной прозрачностью В таблице замеров нет пары ниже нормы ни в светлой теме, ни в тёмной
Senior Описать цветовую систему: примитивы и роли, обе темы, таблица контраста, правило добавления нового цвета Новый цвет в продукт другой дизайнер добавил по вашему правилу и без вас
Ориентир по этой теме: контраст любой пары на экране известен числом, а тёмная тема не требует отдельного макета.

Что почитать дальше

  • Understanding Success Criterion 1.4.3: Contrast (Minimum) и Success Criterion 1.4.11: Non-text ContrastW3C WAI · на английском · бесплатноНормы 4,5 : 1 и 3 : 1 и откуда они взялись (острота зрения 20/40), что пороги не округляют — 4,499 : 1 уже провал, — и кому контраст не нужен: неактивным элементам, декору, логотипам. Во второй части почти полсотни рисунков «проходит / не проходит» для полей, флажков, фокуса, значков и графиков.
  • Refactoring UIАдам Уотан и Стив Шогер, 2018 · книга на английском · платнаяГлава «Accessible doesn’t have to mean ugly» — как пройти контраст и не обесцветить интерфейс. Текст главы закрыт, открыто оглавление.
  • Dark themeMaterial Design, вторая версия · на английском · бесплатноПочему фон тёмной темы — серый #121212, а не чёрный, как высота карточки показана светлеющей подложкой от 0 до 16 % белого и почему акценты берут из светлых тонов. Вторая версия Material, 2019 год. Неактивное и вторичный текст там задают прозрачностью белого, 38 % и 60 %, — урок советует свои цвета.
  • WebAIM Contrast Checkerинструмент · на английском · бесплатноСамый простой замер пары по трём нормам: обычный текст, крупный текст, графика и элементы интерфейса. Ползунок Lightness подбирает ближайший проходящий оттенок, поле Alpha считает полупрозрачный цвет, а для ссылок без подчёркивания есть отдельный Link Contrast Checker.