Навигация
Постраничная навигация
Переход по страницам длинного списка. Каждая страница — свой адрес, поэтому это ссылки, а не кнопки.
Разметка
<nav aria-label="Страницы">
<ol class="inst-pager">
<li><a class="inst-pager-item" href="#" aria-disabled="true">Назад</a></li>
<li><a class="inst-pager-item" href="#" aria-current="page">1</a></li>
<li><a class="inst-pager-item" href="#">2</a></li>
<li><a class="inst-pager-item" href="#">3</a></li>
<li><span class="inst-pager-gap">…</span></li>
<li><a class="inst-pager-item" href="#">24</a></li>
<li><a class="inst-pager-item" href="#">Вперёд</a></li>
</ol>
</nav>
Использование
Пейджер — <ol> внутри <nav aria-label>: страницы упорядочены, и порядок
часть смысла. Кит снимает у списка маркеры и отступ сам, поэтому обёртки не
нужны.
<nav aria-label="Страницы">
<ol class="inst-pager">
<li><a class="inst-pager-item" href="?page=1" aria-current="page">1</a></li>
<li><a class="inst-pager-item" href="?page=2">2</a></li>
<li><span class="inst-pager-gap">…</span></li>
</ol>
</nav>
| Что | Обязательно | Почему |
|---|---|---|
<nav> + aria-label |
да | Отдельный ориентир: на экране уже есть боковая навигация и крошки |
<ol> с <li> |
да | Страницы упорядочены |
aria-current="page" |
да | Единственный источник текущей страницы. Класса для неё нет |
aria-disabled="true" |
да, на краю диапазона | У ссылки нет disabled — атрибут ARIA здесь единственный правдивый |
inst-pager-gap — это <span>, а не ссылка: многоточие обозначает пропуск, а
не страницу. Оно остаётся внутри <li>, чтобы список не терял структуру.
Когда использовать
| Используйте | Возьмите другое |
|---|---|
Список, разбитый на страницы с адресами: ?page=3 |
Поток, у которого нет конца — догрузка по прокрутке. Номер страницы в бесконечной ленте ничего не значит |
| Читателю важно знать, сколько всего, и вернуться на конкретную страницу | Живая лента событий — лог: в нём читают хвост, а не страницу №7 |
| Под таблицей или списком карточек | Нет ни одной страницы — пустое состояние, а не пейджер из одной кнопки |
| — | Шаги процесса — шаги мастера: там порядок обязателен, здесь — свободный переход |
Состояния
Разметка
<nav aria-label="Пример состояний">
<ol class="inst-pager">
<li><a class="inst-pager-item" href="#" aria-disabled="true">Назад</a></li>
<li><a class="inst-pager-item" href="#">7</a></li>
<li><a class="inst-pager-item" href="#" aria-current="page">8</a></li>
<li><a class="inst-pager-item" href="#">9</a></li>
</ol>
</nav>
| Состояние | Как ставится | Что происходит |
|---|---|---|
| текущая | aria-current="page" |
--surface-selected, --accent-text, рамка --accent-border внутренней тенью, --weight-medium |
| недоступна | aria-disabled="true" |
Прозрачность 0.5 и снятая мышь. У ссылки нет disabled — атрибут ARIA здесь единственный правдивый |
| наведение | :hover |
--surface-hover и полный цвет подписи |
aria-disabled не убирает ссылку из порядка обхода — она остаётся
достижимой с клавиатуры и озвучивается как недоступная. Перехват нажатия — на
слое приложения: кит снимает только мышь.
Правила
Так Страница — ссылка со своим адресом
?page=3 можно скопировать, открыть в новой вкладке и вернуться по истории
браузера.
Не так Пейджер в бесконечной ленте
Номер страницы там ничего не значит: содержимое страницы №7 меняется при каждом новом событии.
Так aria-disabled на краю диапазона
Ссылка остаётся в обходе и озвучивается как недоступная. disabled у <a> не
существует.
Не так Пейджер из одной кнопки
Если страниц нет ни одной, нужен пустое состояние, а не навигация по пустоте.
Доступность
| Клавиатура | Нативные ссылки: Tab — обход, Enter — переход. Ничего не перехватывается |
| Цель нажатия | Минимум --control-h-sm по обеим осям — квадрат, а не узкий прямоугольник. В плотности compact он опускается до 22px, ниже порога 24px по WCAG 2.5.8: держите пейджер вне compact |
| Текущая страница | Несёт aria-current, заливку и рамку: цвет не единственный носитель |
| Недоступность | aria-disabled озвучивается и сохраняет фокус, в отличие от удаления ссылки |
| Контраст | Подпись --text-secondary, многоточие --text-faint — оно декорация, а не данные |
| Печать | Пейджер не печатается: на бумаге страницы уже нет |
API
| Имя | Значение | Что делает |
|---|---|---|
| класс | ||
inst-pager | — | Список страниц. Ставится на <ol>, переносится по ширине |
inst-pager-item | — | Страница или стрелка. Квадрат не ниже --control-h-sm |
inst-pager-gap | — | Многоточие на месте пропущенного диапазона. Не ссылка |
| токен | ||
--control-h-sm | 26px | |
--radius-sm | 5px | |
--space-2 | 4px | |
--space-3 | 6px | |
--text-xs | 0.75rem | |
--weight-medium | 500 | |
--hairline | 1px | |
--surface-hover | light-dark(oklch(0 0 0 / 0.035), oklch(1 0 0 / 0.045)) | |
--surface-selected | color-mix(in oklab, var(--a-4) 14%, transparent) | |
--accent-text | light-dark(var(--a-5), var(--a-3)) | |
--accent-border | light-dark(var(--a-4), var(--a-3)) | |
--text-secondary | light-dark(var(--n-9), var(--n-5)) | |
--text-faint | light-dark(var(--n-7), var(--n-7)) | |
Почему кит устроен именно так — конституция · Открытый код под MIT, github.com/keshon/instrument