Основания
Масштаб
Масштаб — атрибут контейнера, как и плотность. Разница между ними одна, и она вся в кегле.
Плотность двигает геометрию и не трогает кегль. Текст остаётся 14px во всех трёх режимах, меняется воздух вокруг него: сколько строк влезло на экран.
Масштаб двигает кегль вместе с геометрией. Соотношения те же, рисунок сохраняется, экран целиком становится крупнее.
Ступень названа своим базовым кеглем: data-scale="16" значит «база интерфейса
16px». Имя ступени и есть ответ на вопрос, который человек задаёт, выбирая
масштаб.
Разметка
<div class="inst-cluster" data-scale="16">
<button class="inst-btn inst-btn--sm" type="button">sm</button>
<button class="inst-btn" type="button">md</button>
<span class="inst-badge" data-tone="ok"><span class="inst-dot"></span>готово</span>
<input class="inst-input inst-input--sm" type="text" value="16">
</div>
Контракт
<html data-scale="16"> <!-- настройка человека, на корне -->
<section data-density="compact"> <!-- плотная область внутри -->
Обычное расположение именно такое: масштаб выбирает человек и ставит на корень, плотность выбирает автор экрана и ставит на область. Обе оси складываются — сочетание описано отдельной ячейкой токенов.
| Значение | База | Для чего |
|---|---|---|
| атрибута нет | 14px | Умолчание. Рабочее расстояние: ноутбук или монитор при системном масштабе |
data-scale="15" |
15px | Ступень запаса: длинная сессия, средний монитор |
data-scale="16" |
16px | Крупный монитор при системном масштабе 100%, работа стоя |
data-scale="17" |
17px | Показ на проекторе, чтение с двух метров |
data-scale="18" |
18px | Настенная панель, дежурный экран, ослабленное зрение |
Масштаб первичен
При одиночном совпадении токен забирает масштаб: блоки [data-scale] стоят в
токенах после блоков плотности, а специфичность у них одинаковая. Плотность
возвращает своё в двумерной ячейке [data-scale][data-density].
У ячейки два селектора, и второй обязателен: парный ловит только оба атрибута на одном элементе, а плотная панель внутри крупного корня — ровно потомковый случай. Без него панель взяла бы геометрию базы, оставив крупный кегль.
Доступность
Масштаб — ответ на увеличенный системный шрифт, но не замена ему. Высоты
контролов применяются как min-block-size, поэтому текст, выросший от настройки
браузера, раздвигает контрол, а не обрезается в нём.
Цели нажатия
Все пятнадцать сочетаний масштаба и плотности проходят WCAG 2.2 AA 2.5.8 —
проверяет cmd/targets по сетке 5 × 3.
Шкала
Кегль
| Токен | 14 | 15 | 16 | 17 | 18 |
|---|---|---|---|---|---|
--text-2xs |
11 | 11.5 | 12.5 | 13 | 14 |
--text-xs |
12.5 | 13 | 14 | 15 | 16 |
--text-sm |
14 | 15 | 16 | 17 | 18 |
--text-md |
16 | 17 | 18.5 | 19.5 | 21 |
--text-lg |
18 | 19.5 | 21 | 22.5 | 24 |
--text-xl |
22 | 23.5 | 26 | 28 | 30 |
--text-2xl |
28 | 30 | 33 | 35.5 | 38 |
Значения объявлены в rem и точны при корне 16px. Ось масштаба умножается
на настройку «размер шрифта по умолчанию» в браузере, а не заменяет её: человек,
поднявший корень до 20px, получит от ступени ещё одну ступень сверху.
Радиусы и высоты
| Токен | 14 | 15 | 16 | 17 | 18 |
|---|---|---|---|---|---|
--radius-2xs |
2 | 2 | 2 | 2 | 2 |
--radius-xs |
4 | 4 | 6 | 6 | 6 |
--radius-sm |
6 | 6 | 8 | 8 | 8 |
--radius-md |
8 | 10 | 10 | 10 | 10 |
--radius-lg |
12 | 12 | 14 | 14 | 16 |
--control-h-xs |
20 | 22 | 24 | 25 | 26 |
--control-h-sm |
24 | 28 | 30 | 32 | 34 |
--control-h-md |
32 | 35 | 38 | 40 | 42 |
--control-h-lg |
38 | 41 | 44 | 47 | 50 |
Лестница радиусов растёт ступенями, а не множителем: радиус обязан остаться чётным, иначе на плотности пикселей 1.5 дуга садится мимо устройственной сетки. Из-за этого соседние ступени местами делят одно значение — чётного числа между 8 и 10 не существует.
Отступы двигаются по шкале --space-*, а она разрежена нарочно, поэтому шаг у
них крупнее, чем у кегля: соседние ступени масштаба часто берут одну и ту же
ступень отступа.
Что НЕ масштабируется
| Что | Почему |
|---|---|
--hairline |
Не по принципу, а физически: браузер снапает рамку к устройственному пикселю, и ×1.07 от единицы возвращается в ту же единицу |
--tap-min |
Это норма, а не размер: 24px — пол WCAG 2.2 AA 2.5.8. Лестница идёт только вверх, поэтому фиксированный пол ничего не жмёт |
--radius-2xs |
Единственное приколоченное число: точка растёт до 8px, и радиус 4 дал бы ровно половину, то есть круг. Круг занят пометкой обратимого пункта |
--space-* |
Шкала — фундамент. Масштаб двигает роли, а не шкалу под ними: отступы переезжают на другую ступень той же лестницы |
| Цвет и контраст | Пороги не зависят от кегля. cmd/contrast масштаб поэтому и не проверяет |
Правила
Лестница начинается с 14 и не может начинаться ниже. Это не выбор, а
арифметика двух правил кита, перемноженных друг на друга: пол кегля — 11px,
минимальный шаг лестницы — 1.12, а под базой лежат две ступени, 2xs и xs.
Отсюда
минимальная база = 11 × 1.12 × 1.12 = 13.8px
и 14 — первое целое, которое в это влезает. При базе 13 второй ступени вниз достаётся 10.36px, при базе 12 — 9.57px; обе ниже пола. Опустить лестницу можно, только сдвинув пол, шаг или число ступеней под базой — каждое из трёх отдельное решение. «Мельче» остаётся работой плотности.
Значения таблицы авторские, а не вычисленные. Пропорциональный пересчёт
проваливает правило шага регулярно: при базе 16 честная доля даёт xs = 14.5,
то есть шаг 1.103 при норме 1.12. Умножение ломает и чётность радиуса, и рост
лестницы, и полосу отношения радиуса контрола к высоте.
Компонент, который ломается на ступени 18, содержит зашитый кегль или зашитую высоту — то и другое обязано быть ролью.
Что брать, а что нет
Тремя плотностями «крупнее» не выражалось. На 27″ 4K при системном масштабе 100% кит рисовался мелко, а единственная ручка, похожая на ответ, — просторная плотность — давала воздух, а не размер: строки разъезжались, буквы оставались теми же.
Проверка, отличающая ось от переименования, та же, что у атрибутных словарей: если две ручки дают один результат, это одна ручка с двумя именами. Здесь они расходятся, и это видно на числах.
| кегль | --control-h-md |
--pad-card |
|
|---|---|---|---|
18 + compact |
18px | 34px | 24px |
база + comfortable |
14px | 36px | 24px |
Высота и отступ совпали почти точно, кегль — нет. Это два разных экрана, а не один и тот же с двух сторон.
| Используйте | Возьмите другое |
|---|---|
| Ступени, чтобы сделать экран крупнее целиком | Масштаб, чтобы разредить список — воздух добавляет плотность, и она не трогает кегль |
| Атрибут на корне как настройку человека | Атрибут на отдельном компоненте — масштаб не вариант контрола. Размер выбирает --sm/--lg у кнопки |
| Сочетание с плотностью: «крупно и плотно» — рабочий режим большого монитора | Свою ступень числом в приложении — новое значение заводится ролью, список в токенах |
API
| Имя | Значение | Что делает |
|---|---|---|
| атрибут | ||
data-scale | — | 15 16 17 18 — базовый кегль интерфейса. Отсутствие атрибута — база 14px |
| Имя | Значение | Откуда |
|---|---|---|
| токен | ||
--text-2xs/xs/sm/md/lg/xl/2xl | — | одно на все ячейки |
--radius-2xs/xs/sm/md/lg | — | одно на все ячейки |
--control-h-xs/sm/md/lg | — | одно на все ячейки |
--radius-control-sm/md/lg | — | одно на все ячейки |
--size-dot | 6px | база +4: масштаб |
--size-icon | 18px | база +4: масштаб |
--size-icon-lg | 24px | база +4: масштаб |
--size-icon-sm | 14px | база +4: масштаб |
--size-chevron | 10px | база +4: масштаб |
--size-track | 4px | база +4: масштаб |
--size-meter | 6px | база +4: масштаб |
--size-tick | 3px | база +4: масштаб |
--size-marker | 2px | база +4: масштаб |
--label-col | 104px | база +4: масштаб |
--aside-w | 232px | база +4: масштаб |
--col-min | 260px | база +4: масштаб |
--container-max | 76rem | база +4: масштаб |
Почему кит устроен именно так — конституция · Открытый код под MIT, github.com/keshon/instrument