Что разберём
1Нормы контраста
Контраст — отношение яркостей двух цветов: от 1 : 1, когда цвета одинаковы, до 21 : 1 — чёрный на белом.
Нормы задаёт WCAG, стандарт доступности веба. Уровень AA — тот, на который обычно равняются продукты:
| Что | AA | AAA |
|---|---|---|
| Обычный текст | 4,5 : 1 | 7 : 1 |
| Крупный текст — от 18 pt, это 24 px, или от 14 pt жирным, около 18,5 px | 3 : 1 | 4,5 : 1 |
| Значки, рамки полей, рамка фокуса — всё, по чему видно элемент и его состояние | 3 : 1 | — |
| Не требуют контраста | Декор, текст внутри логотипа, неактивные элементы, текст на фотографии, где он не главное | |
Пороги не округляют. В пояснениях к WCAG прямо сказано, что 4,499 : 1 норму 4,5 : 1 не проходит, даже если инструмент покажет «4,5».
У рамки фокуса есть и отдельное правило уровня AAA, критерий 2.4.13. Рамка не тоньше 2 px по периметру и 3 : 1 между видом с фокусом и без.
2Замер всех пар на экране
Контраст перестаёт быть делом удачи, когда замерены все пары, включая подписи, ошибки и фокус.
Экран оплаты в двух вариантах. Числа рядом с местами — замеры: ✓ — норма выполнена, ✗ — нет. Нажмите «Контраст», чтобы спрятать или показать их.
На глаз
После замеров
Что изменилось
| Место | Норма | На глаз | После |
|---|---|---|---|
| Подпись поля, 13 px | 4,5 : 1 | 3,51 : 1 | 5,93 : 1 — вторичный текст |
| Рамка поля | 3 : 1 | 1,31 : 1 | 3,51 : 1 — своя роль «граница поля» |
| Текст ошибки | 4,5 : 1 | 2,66 : 1 | 5,58 : 1 — тёмный красный |
| Рамка фокуса | 3 : 1 | 1,75 : 1 | 5,81 : 1 — цвет действия, 2 px |
| Ссылка | 4,5 : 1 | 3,94 : 1 | 5,81 : 1 — тот же синий, что у кнопки |
Почти все поправки — не новые цвета, а роли из палитры. Бледный синий фокуса и розовый ошибки на глаз смотрелись мягче, но оказались ниже нормы.
3Не только основной текст
Основной текст проходит почти всегда. Проваливаются подписи, подсказки, ошибки, фокус и ссылки.
- Подписи и подсказки. Их делают серее основного текста — и часто перебарщивают. Мелкий кегль не даёт скидки: норма для обычного текста та же.
- Текст в поле до ввода. Подсказка вроде «0000 0000 0000 0000» — тоже текст. Её читают, чтобы понять формат.
- Ошибки и статусы. Красный для ошибки часто выбирают по «тревожности» и забывают замерить. Светлый красный на белом не проходит.
- Рамки полей и фокуса. Если поле отличается от фона только рамкой, рамка должна давать 3 : 1: без неё поле не найти. Рамка фокуса — тоже: по ней человек с клавиатурой видит, где он.
- Ссылки внутри абзаца. Синий на белом может давать 5,81 : 1, но от чёрного текста рядом он отличается лишь на 2,84 : 1. Если ссылка выделена только цветом, между ней и текстом нужно не меньше 3 : 1. Проще подчеркнуть ссылку — тогда вопрос снимается.
4Неактивное без одной прозрачности
Неактивная кнопка должна выглядеть недоступной, а не стёртой.
Самый быстрый способ сделать кнопку неактивной — прозрачность 40 %. Надпись на такой кнопке получается 1,86 : 1.
WCAG контраста от неактивных элементов не требует. Но прочитать, что написано на кнопке, человеку всё равно нужно: иначе непонятно, что станет доступно, когда он заполнит форму.
Прозрачность 40 %
Свои цвета неактивного
Почему не прозрачность
- Надпись становится нечитаемой. Прозрачная подложка смешивается с белым фоном, и контраст надписи падает с 5,81 : 1 до 1,86 : 1.
- Результат зависит от фона. На картинке или цветной плашке прозрачная кнопка смешивается с тем, что под ней, и выглядит каждый раз по-разному.
- Неактивное путают с загрузкой. Полупрозрачным часто рисуют то, что ещё не появилось.
В тёмной теме Material 2 неактивное задают как раз прозрачностью белого — 38 % для надписи. На однотонном фоне так можно, но контраст всё равно придётся измерить в каждой теме, а отдельный цвет для неактивного держать под контролем проще.
Нужна ли неактивная кнопка вообще или лучше оставить кнопку доступной и показать ошибку, разобрано в уроке «Компоненты и варианты», Middle.
5Тёмная тема на тех же ролях
Тёмная тема — не второй макет, а те же роли с другими значениями.
В палитре уже есть роли: фон, текст, вторичный текст, граница поля, действие, ошибка.
Для тёмной темы у каждой роли появляется второе значение, а экраны не перерисовывают: они и так ссылаются на роли. Переключите вариант ниже.
Светлая
Тёмная, те же акценты
Тёмная, свои акценты
Роли в двух темах
| Роль | Светлая | Тёмная |
|---|---|---|
| Фон | #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Проходит или нет
Одно и то же отношение проходит для одного места и не проходит для другого.
Подпись поля, 13 px, обычное начертание: 3,51 : 1.
Не проходитЭто обычный текст, нужно 4,5 : 1. Мелкий кегль скидки не даёт.
Заголовок экрана, 24 px: 3,62 : 1.
ПроходитТекст от 24 px — крупный, для него 3 : 1. Но запас маленький: при уменьшении кегля пара провалится.
Рамка поля ввода на белом, фон поля тоже белый: 1,31 : 1.
Не проходитПоле отличается от фона только рамкой, значит, рамке нужно 3 : 1.
Надпись внутри логотипа магазина в шапке: 2,1 : 1.
Норма не требуетТекст, который часть логотипа, в требования к контрасту не входит.
Надпись на неактивной кнопке «Оплатить»: 1,86 : 1.
Норма не требуетНеактивные элементы в требования не входят. Но надпись всё равно стоит сделать читаемой — как в разделе 4.
Ссылка внутри абзаца, без подчёркивания: к белому фону 5,81 : 1, к чёрному тексту рядом 2,84 : 1.
Не проходитК фону контраста хватает. Но от соседнего текста ссылка отличается только цветом, и тогда между ними нужно 3 : 1, а здесь 2,84 : 1. Подчеркните ссылку или возьмите цвет темнее.
Рамка фокуса 2 px цвета действия на белом: 5,81 : 1.
ПроходитДля рамки фокуса нужно 3 : 1.
Подсказка «0000 0000 0000 0000» в пустом поле: 2,53 : 1.
Не проходитПодсказка — тоже текст, и её читают, чтобы понять формат. Нужно 4,5 : 1.
Тонкая линия-разделитель между блоками: 1,31 : 1.
Норма не требуетРазделитель — декор: без него экран остаётся понятным. Если бы линия была единственной границей поля, норма 3 : 1 уже действовала бы.
8Задание
Возьмите свой экран, замерьте контраст всех текстовых и интерактивных пар, почините провалы и соберите тёмную тему на тех же ролях. Приложите таблицу замеров.
Часть 1 · Замерить, 30 минут
- Выберите экран с формой, ссылками, ошибкой и кнопками — в том числе неактивной.
- Выпишите все пары: каждый текст с его фоном, рамки полей, рамку фокуса, значки.
- Замерьте каждую и отметьте норму: обычный текст, крупный, граница или «не требует».
ЭКРАН: ______________________ Дата: __.__.____ МЕСТО | РОЛЬ ЦВЕТА | НОРМА | СВЕТЛАЯ | ТЁМНАЯ основной текст | текст / фон | 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 минут
- Каждый провал чините ролью из палитры: темнее вторичный текст, своя граница поля, тёмный оттенок ошибки.
- Неактивное состояние переведите с прозрачности на свою пару цветов.
Часть 3 · Тёмная тема, 40 минут
- Для каждой роли задайте тёмное значение. В Figma — второй режим той же коллекции переменных.
- Переключите экран на тёмный режим и заполните колонку «Тёмная».
- Провалы тёмной темы чините тёмными значениями, светлые не трогайте.
Что должно получиться
- Экран в двух темах на одних ролях.
- Таблица замеров по обеим темам.
- Список поправок: что провалилось и чем починили.
План работы: 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 ContrastНормы 4,5 : 1 и 3 : 1 и откуда они взялись (острота зрения 20/40), что пороги не округляют — 4,499 : 1 уже провал, — и кому контраст не нужен: неактивным элементам, декору, логотипам. Во второй части почти полсотни рисунков «проходит / не проходит» для полей, флажков, фокуса, значков и графиков.
- Refactoring UIГлава «Accessible doesn’t have to mean ugly» — как пройти контраст и не обесцветить интерфейс. Текст главы закрыт, открыто оглавление.
- Dark themeПочему фон тёмной темы — серый #121212, а не чёрный, как высота карточки показана светлеющей подложкой от 0 до 16 % белого и почему акценты берут из светлых тонов. Вторая версия Material, 2019 год. Неактивное и вторичный текст там задают прозрачностью белого, 38 % и 60 %, — урок советует свои цвета.
- WebAIM Contrast CheckerСамый простой замер пары по трём нормам: обычный текст, крупный текст, графика и элементы интерфейса. Ползунок Lightness подбирает ближайший проходящий оттенок, поле Alpha считает полупрозрачный цвет, а для ссылок без подчёркивания есть отдельный Link Contrast Checker.