Перейти к содержимому
Плотность
Тема

Основания

Ритм и форма

Шаг 4px, шкала нарочно разрежена сверху — чтобы «чуть побольше» просто не было в наборе. Компонент берёт отступ не из шкалы, а из яруса ролей: именно он даёт плотности одну точку, через которую она перенастраивает всё сразу.

Компонент
worldgen-01
Генерация биомов, 3 прохода
готово
Разметка
<div class="inst-card inst-stack inst-stack--tight">
  <div class="inst-card-title">worldgen-01</div>
  <div class="inst-card-sub">Генерация биомов, 3 прохода</div>
  <div class="inst-cluster">
    <button class="inst-btn inst-btn--sm" type="button">Повторить</button>
    <span class="inst-badge" data-tone="ok"><span class="inst-dot"></span>готово</span>
  </div>
</div>

Использование

Отступ берётся по назначению: --pad-panel, не --space-5. Роль перенастраивается плотностью, ступень шкалы — нет.

.my-panel {
  padding: var(--pad-panel);
  gap: var(--gap-row);
  border-radius: var(--radius-lg);
}
Что Обязательно Почему
Роль, а не ступень да --pad-panel меняется вместе с плотностью, --space-5 — нет. Компонент с зашитой ступенью ломается первым
Зазор ставит контейнер да Отступ у элемента складывается с внутренним отступом родителя по вертикали и не складывается по горизонтали
Радиус из словаря да Пять ступеней, названных размером контрола. Своё число разъезжается с соседями на стыке
Хайрлайн через --hairline да На дробном DPR это 0.5px, и линия остаётся линией, а не полосой

Когда использовать

Используйте Возьмите другое
Роль: --pad-panel, --gap-row, --row-pad-y --space-* в компоненте — плотность перенастраивает ярус ролей, а не шкалу. Список ролей целиком — токены
Зазор между соседями — примитив потока .inst-stack / .inst-cluster / .inst-grid Утилита отступа (mt-3, p-2) — их в ките нет и не будет, см. поток
Шаг зазора именем: обычный, --tight, --loose Свой зазор числом — «чуть побольше» не должно быть доступным решением. Три шага описаны в потоке
Радиус по вложенности: контейнер lg, контрол внутри sm Один радиус на всё — внутренний элемент с радиусом контейнера выпирает. Пример — карточка
--hairline для линии, которая не должна кричать 1px числом — на 2x-дисплее это вдвое толще нужного, см. хайрлайн

Шкала

Компонент обращается к ней только через ярус ролей. Прямое использование --space-* допустимо в приложении и в примитивах потока.

Токен Значение
--space-1 2px
--space-2 4px
--space-3 6px
--space-4 8px
--space-5 12px
--space-6 16px
--space-7 24px
--space-8 32px
--space-9 48px
--space-10 64px

Разрежение сверху — не экономия, а ограничение: между 32 и 48 нет ступени, и это правильно. Шаг, которого нет, нельзя выбрать по ошибке.

Отступы по назначению

Ярус ролей. Значения ниже — для плотности по умолчанию; в compact и comfortable они другие, см. плотность.

Токен По умолчанию Где
--pad-panel --space-5 Внутренний отступ панели
--pad-card --space-6 Внутренний отступ карточки
--pad-cell-x --space-4 Горизонтальный отступ ячейки таблицы
--row-pad-y --space-3 Вертикальный отступ строки: задача, ячейка, пункт меню
--gap-row --space-3 Зазор между строками в стопке
--gap-inline --space-4 Зазор между соседями в ряду
--control-pad-sm --space-4 Горизонтальный отступ мелкого контрола
--control-pad-md --space-5 Он же у среднего
--control-pad-lg --space-6 Он же у крупного

Зазор ставится между соседями. margin-block на каждом элементе складывается с внутренним отступом контейнера сверху и снизу, но не по бокам — и подсветка отступает от рамки по вертикали вдвое дальше, чем по горизонтали. Правильная форма — X + X { margin-block-start }.

Размеры глифов и жёлобов

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

Токен По умолчанию Что это
--size-dot 6px Точка состояния
--size-check 15px Чекбокс и радио
--size-switch-w / --size-switch-h 30 / 18px Дорожка свитча
--size-thumb 14px Бегунок
--size-track 4px Дорожка слайдера
--size-meter 6px Толщина меры
--size-spinner 13px Кольцо занятости
--size-icon 16px Иконка — см. иконки
--size-chevron 10px Шеврон, мелкая иконка
--size-marker 2px Несущая метка: полоса вкладки, край сноски, край текущего пункта навигации. Тоньше не видно, толще — спорит с текстом
--size-gutter 14px Левый жёлоб строки задачи
--size-indent 14px Шаг вложенности дерева
--label-col 92px Колонка подписей инспектора

Радиусы

Пять ступеней, и выбирает их вложенность.

Токен Значение Для чего
--radius-xs 3px Инлайн: бейджи, образцы, торцы полос
--radius-sm 5px Контролы внутри карточки или панели
--radius-md 7px Отдельно стоящие контролы: кнопка, поле, поповер
--radius-lg 11px Карточки, панели, модалка
--radius-full 999px Дорожки, бегунки, аватар

Правило вложенных радиусов

Внутреннему углу нужен радиус меньше внешнего, иначе внутренний элемент выглядит выпирающим из контейнера. Оптически внутренний радиус равен внешнему минус толщина промежутка, и шкала уже подобрана так, чтобы соседняя ступень вниз давала верный результат при отступе из яруса ролей.

<!-- панель lg → контрол внутри sm; отдельно стоящий контрол — md -->
<div class="inst-panel">
  <div class="inst-panel-body">
    <div class="inst-card"></div>
  </div>
</div>

Скругление на односторонней рамке — всегда баг. border-left вместе с border-radius даёт обрубок дуги: сноска и край текущего пункта навигации несут прямой угол намеренно.

Хайрлайн

Браузер никогда не рисует рамку тоньше одного физического пикселя. На 1x-дисплее 0.5px и 1px дают одно и то же, а отрицательное поле в -0.5px при нарисованной рамке в 1px оставляет полпикселя двойной линии. Поэтому хайрлайн включается только там, где ему есть куда поместиться.

Токен Значение Когда
--hairline 1px Плотность пикселей ниже 1.5dppx
--hairline 0.5px @media (min-resolution: 1.5dppx)
--stroke 1px Линия, которая обязана остаться видимой всегда

Шов группы кнопок сделан снятой рамкой у соседа — по той же причине.

Правила

Токен Значение Что это
--aside-w 232px Боковая колонка оболочки
--container-max 76rem Потолок ширины рабочей области. В rem, потому что мера читаемости, а не геометрия
--split-side 18rem Желаемая ширина боковой части сплита
--split-main 30rem Ниже этого основная часть переносится вниз
--col-min 260px Минимальная колонка адаптивной сетки

Доступность

Цели нажатия Отступ контрола участвует в размере цели наравне с высотой. В compact мелкие контролы уходят ниже 24px по WCAG 2.5.8 — см. плотность
Геометрия в px Отступы и радиусы не растут вместе с кеглем: плотный инструментальный вид иначе расползается. Растёт текст, а высоты работают как минимум
Разделение групп Ритм — тоже носитель смысла: четыре метрики без рамок читаются как одна группа именно зазором
Хайрлайн На 1x-дисплее остаётся 1px: линия, которая должна быть видна, видна на любом экране

API

ИмяЗначениеЧто делает
класс
inst-stackВертикальный поток, зазор --gap-inline
inst-clusterГоризонтальный поток с переносом
inst-cluster-spacerРазрыв в ряду: всё после него уходит вправо
inst-gridАдаптивная сетка auto-fit по --col-min
модификатор
inst-stack--tightШаг зазора
inst-stack--looseШаг зазора
inst-cluster--tightШаг зазора
inst-cluster--looseШаг зазора
inst-grid--tightДругая минимальная колонка
inst-grid--wideДругая минимальная колонка
токен
--space-12pxШаг шкалы
--space-24pxШаг шкалы
--space-36pxШаг шкалы
--space-48pxШаг шкалы
--space-512pxШаг шкалы
--space-616pxШаг шкалы
--space-724pxШаг шкалы
--space-832pxШаг шкалы
--space-948pxШаг шкалы
--space-1064pxШаг шкалы
--pad-panelvar(--space-5)Внутренний отступ панели
--pad-cardvar(--space-6)Внутренний отступ карточки
--pad-cell-xvar(--space-4)Горизонтальный отступ ячейки
--row-pad-yvar(--space-3)Вертикальный отступ строки
--gap-rowvar(--space-3)Зазор между строками
--gap-inlinevar(--space-4)Зазор в ряду
--control-pad-smvar(--space-4)Отступ малого контрола
--control-pad-mdvar(--space-5)Отступ базового контрола
--control-pad-lgvar(--space-6)Отступ крупного контрола
--radius-xs3pxИнлайн: бейджи, образцы, торцы полос
--radius-sm5pxКонтролы внутри карточки
--radius-md7pxОтдельно стоящие контролы
--radius-lg11pxКарточки и панели
--radius-full999pxКруг и капсула
--hairline1pxВолосок. На 1x равен пикселю, выше — половине
--stroke1pxЛиния, которая обязана быть видна всегда
--aside-w232pxБоковая колонка оболочки
--container-max76remПотолок ширины рабочей области
--split-side18remЖелаемая ширина боковой части сплита
--split-main30remПорог переноса основной части
--col-min260pxМинимальная колонка адаптивной сетки
ИмяЗначениеЧто делает
класс
inst-stackВертикальный поток, зазор --gap-inline
inst-clusterГоризонтальный поток с переносом
inst-cluster-spacerРазрыв в ряду: всё после него уходит вправо
inst-gridАдаптивная сетка auto-fit по --col-min
модификатор
inst-stack--tightШаг зазора
inst-stack--looseШаг зазора
inst-cluster--tightШаг зазора
inst-cluster--looseШаг зазора
inst-grid--tightДругая минимальная колонка
inst-grid--wideДругая минимальная колонка
токен
--space-12pxШаг шкалы
--space-24pxШаг шкалы
--space-36pxШаг шкалы
--space-48pxШаг шкалы
--space-512pxШаг шкалы
--space-616pxШаг шкалы
--space-724pxШаг шкалы
--space-832pxШаг шкалы
--space-948pxШаг шкалы
--space-1064pxШаг шкалы
--pad-panelvar(--space-5)Внутренний отступ панели
--pad-cardvar(--space-6)Внутренний отступ карточки
--pad-cell-xvar(--space-4)Горизонтальный отступ ячейки
--row-pad-yvar(--space-3)Вертикальный отступ строки
--gap-rowvar(--space-3)Зазор между строками
--gap-inlinevar(--space-4)Зазор в ряду
--control-pad-smvar(--space-4)Отступ малого контрола
--control-pad-mdvar(--space-5)Отступ базового контрола
--control-pad-lgvar(--space-6)Отступ крупного контрола
--radius-xs3pxИнлайн: бейджи, образцы, торцы полос
--radius-sm5pxКонтролы внутри карточки
--radius-md7pxОтдельно стоящие контролы
--radius-lg11pxКарточки и панели
--radius-full999pxКруг и капсула
--hairline1pxВолосок. На 1x равен пикселю, выше — половине
--stroke1pxЛиния, которая обязана быть видна всегда
--aside-w232pxБоковая колонка оболочки
--container-max76remПотолок ширины рабочей области
--split-side18remЖелаемая ширина боковой части сплита
--split-main30remПорог переноса основной части
--col-min260pxМинимальная колонка адаптивной сетки

Почему кит устроен именно так — конституция · Открытый код под MIT, github.com/keshon/instrument