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

Раскладка

Примитивы потока

Три способа расставить элементы: стопкой, рядом, сеткой. У каждого три шага зазора, названные намерением, а не числом.

Компонент
В работе
7
В очереди
5
Упало
1
Разметка
<div class="inst-stack">
  <div class="inst-cluster">
    <button class="inst-btn inst-btn--sm" type="button">Фильтры</button>
    <button class="inst-btn inst-btn--sm" type="button">Период</button>
    <span class="inst-cluster-spacer"></span>
    <button class="inst-btn inst-btn--sm inst-btn--primary" type="button">Запустить</button>
  </div>
  <div class="inst-grid inst-grid--tight">
    <div class="inst-metric"><div class="inst-metric-label">В работе</div><div class="inst-metric-value">7</div></div>
    <div class="inst-metric"><div class="inst-metric-label">В очереди</div><div class="inst-metric-value">5</div></div>
    <div class="inst-metric"><div class="inst-metric-label">Упало</div><div class="inst-metric-value">1</div></div>
  </div>
</div>

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

<div class="inst-stack">
  <div>…</div>
  <div>…</div>
</div>
Что Обязательно Почему
Зазор ставит контейнер, а не элемент да Отступ у элемента складывается с внутренним отступом контейнера сверху и снизу, но не по бокам: блок отъезжает от рамки по вертикали вдвое дальше, чем по горизонтали
Шаг зазора — модификатором да --tight и --loose названы намерением. Число в разметке ломается на первой же смене плотности
Один inst-cluster-spacer на ряд да Второй ничего не даст: первый уже забрал остаток
<ul> вместо <div>, если это список нет, но обычно да Примитивы семантики не несут

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

Используйте Возьмите другое
Вертикальный ритм между блоками — inst-stack Ограничение ширины и боковые поляконтейнер
Горизонтальный ряд, который переносится, — inst-cluster Две колонки разной важностисплит: у него есть порог переноса
Карточки в адаптивную сетку — inst-grid Табличные данныетаблица: у сетки нет строк и заголовков колонок
Полоса действий у заголовка Действия экранаinst-page-actions, шапка экрана; действия секциисекция

Варианты

Стопка

Пример
Первый
Второй
Разметка
<div class="inst-stack inst-stack--tight">
  <div class="inst-card"><div class="inst-card-title">Первый</div></div>
  <div class="inst-card"><div class="inst-card-title">Второй</div></div>
</div>
Класс Зазор Когда
inst-stack --pad-panel Умолчание: блоки экрана, секции, панели
inst-stack--tight --gap-row Строки внутри блока: пары ключ-значение, список задач
inst-stack--loose --space-7 Крупные смысловые разделы длинного экрана

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

Это работает во всех колонках кита — стопке, форме, филдсете, поле, секции. В своей колонке приложения — нет: display: flex; flex-direction: column, написанный руками, растянет их заново. Это довод взять примитив, а не писать колонку.

Кластер

Пример
готово идёт
Разметка
<div class="inst-cluster inst-cluster--loose">
  <span class="inst-badge" data-tone="ok"><span class="inst-dot"></span>готово</span>
  <span class="inst-badge" data-tone="running"><span class="inst-dot"></span>идёт</span>
  <span class="inst-cluster-spacer"></span>
  <button class="inst-btn inst-btn--sm" type="button">Ещё</button>
</div>
Класс Зазор Когда
inst-cluster --gap-inline Умолчание: кнопки, бейджи, контролы в ряд
inst-cluster--tight --space-2 Элементы, читающиеся как одна группа: теги, чипы
inst-cluster--loose --pad-panel Разные по смыслу группы в одной строке

Кластер переносится всегда (flex-wrap: wrap) и выравнивает детей по центру поперечной оси. inst-cluster-spacer — пустой элемент с margin-inline-start: auto: всё после него уезжает к дальнему краю.

Сетка

Пример
Карточка
Колонки перестраиваются сами: auto-fit, без единого запроса.
Карточка
min() не даёт колонке вылезти за контейнер на узком экране.
Разметка
<div class="inst-grid inst-grid--wide">
  <div class="inst-card"><div class="inst-card-title">Карточка</div>
    <div class="inst-card-sub">Колонки перестраиваются сами: auto-fit, без единого запроса.</div></div>
  <div class="inst-card"><div class="inst-card-title">Карточка</div>
    <div class="inst-card-sub">min() не даёт колонке вылезти за контейнер на узком экране.</div></div>
</div>
Класс Минимальная колонка Когда
inst-grid --col-min, 260px Умолчание: карточки, панели
inst-grid--tight 180px Мелкие ячейки: метрики, плитки состояний
inst-grid--wide 380px Крупные блоки с текстом внутри

Число колонок не задаётся: repeat(auto-fit, minmax(min(var(--col-min), 100%), 1fr)) считает его сам. min(…, 100%) обязателен — без него колонка шириной 380px не помещается в контейнер шириной 320px и вылезает наружу вместе с горизонтальной прокруткой.

Это первый уровень адаптивности, интринсик: работает всегда, в том числе там, где контейнера-предка нет.

/* Своя плотность сетки — одна строка */
.my-board { --col-min: 320px; }

Правила

Почему здесь нет mt-3 и p-2

Утилит отступов в ките нет и не будет, и это не эстетика.

Шкала кита нарочно разрежена сверху: между соседними шагами разрыв растёт, чтобы «чуть побольше» не было доступным решением. Набор из двухсот утилит возвращает его первым классом — и вместе с ним переносит решение о вертикальном ритме из кита в разметку каждого экрана. Через полгода одинаковые на вид экраны отличаются на два пикселя в тридцати местах, и починить это можно только поштучно.

Вместо утилит — три примитива с тремя шагами зазора, названными намерением. Плотность перенастраивает все три разом, потому что зазор приходит из ролей (--pad-panel, --gap-row, --gap-inline), а не из числа в разметке. Полное рассуждение — в конституции.

Так Зазор ставит контейнер

Нужен воздух между блоками — положите их в стопку. Шаг выбирается модификатором.

Не так Отступ у элемента

Он складывается с внутренним отступом контейнера по вертикали и не складывается по горизонтали. Блок отъезжает от рамки неравномерно.

Так Три шага, названные намерением

--tight, умолчание, --loose. Плотность перенастраивает все три разом.

Не так «Чуть побольше» числом

Через полгода одинаковые на вид экраны расходятся на два пикселя в тридцати местах, и чинится это только поштучно.

Доступность

Порядок Все три примитива сохраняют порядок разметки: визуальный и клавиатурный совпадают. order и row-reverse в ките не применяются
Перенос Кластер и сетка переносятся сами — при увеличении кегля до 200% содержимое не обрезается и не даёт горизонтальной прокрутки
Распорка inst-cluster-spacer пуст и в дереве доступности отсутствует: он не сообщает ничего сверх порядка
Плотность Все три зазора приходят из ролей и перенастраиваются data-density разом. Компонент, у которого зашито число, ломается здесь первым
Семантика Примитивы — <div>. Если группа элементов — список, ставьте <ul> и класс на него

API

ИмяЗначениеЧто делает
класс
inst-stackКолонка. Зазор --pad-panel
inst-clusterРяд с переносом, выравнивание по центру. Зазор --gap-inline
inst-cluster-spacerПрижать хвост ряда к дальнему краю
inst-gridАдаптивная сетка. Зазор --pad-panel
модификатор
inst-stack--tightШаг зазора
inst-stack--looseШаг зазора
inst-cluster--tightШаг зазора
inst-cluster--looseШаг зазора
inst-grid--tightМинимальная ширина колонки
inst-grid--wideМинимальная ширина колонки
переменная
--col-min260px
токен
--pad-panelvar(--space-5)
--gap-rowvar(--space-3)
--gap-inlinevar(--space-4)
--space-24px
--space-724px

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