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

Обратная связь

Спиннер

Кольцо, показывающее, что машина занята, когда долю выполненного назвать нечем. Настоящий SVG из двух окружностей, а не рамка на div.

Компонент
Разметка
<svg class="inst-spinner" viewBox="0 0 16 16" role="status" aria-label="Загрузка">
  <circle class="inst-spinner-track" cx="8" cy="8" r="6.5"/>
  <circle class="inst-spinner-arc" cx="8" cy="8" r="6.5"/>
</svg>

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

Разметка фиксирована: viewBox="0 0 16 16", две окружности радиуса 6.5 в центре 8 8. Копируется целиком.

<svg class="inst-spinner" viewBox="0 0 16 16" role="status" aria-label="Загрузка">
  <circle class="inst-spinner-track" cx="8" cy="8" r="6.5"/>
  <circle class="inst-spinner-arc" cx="8" cy="8" r="6.5"/>
</svg>
Что Почему нельзя изменить
viewBox="0 0 16 16" Толщина обводки и stroke-dasharray посчитаны под эту систему координат
r="6.5" cx="8" cy="8" Длина окружности при r=6.5 — около 40.8, и 11 30 даёт ровно четверть на дугу
role="status" Иначе появление спиннера ничего не сообщает
aria-label У role="status" должно быть имя: «Загрузка», «Идёт прогон»

Обе окружности — прямые потомки. Вложить их глубже нельзя: обводка не применится.

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

Используйте Возьмите другое
Ожидание, длительность которого неизвестна Известна доля выполненногомера: спиннер не сообщает, сколько осталось
Ожидание в маленьком месте: рядом с подписью, в ячейке Известна форма будущего содержимогоскелетон
Занятость части вида Занятость кнопкиaria-busy="true" на самой кнопке: у неё своё кольцо на месте подписи
Общий индикатор работы системы Состояние конкретного объектаточка в бейдже: она называет фазу словом

Устройство

Элемент Работа
inst-spinner <svg>. Размер, толщина обводки, вращение
inst-spinner-track Первая окружность — дорожка, --border-control
inst-spinner-arc Вторая окружность — дуга, --accent-mark. Четверть длины через stroke-dasharray: 11 30

Обе окружности одинаковы; отличает их только обводка. Дорожка нужна, чтобы кольцо было видно целиком: одна дуга без неё читается как обрывок.

Свойство Значение
размер --size-spinner — 13px, в плотном режиме 12px
толщина обводки 2
концы stroke-linecap: round
оборот 0.7с, линейно, бесконечно

--accent-mark, а не --accent-text: у тона два передних плана, и метка без подписи берёт тот, что проверен на 3:1 против дорожки.

Почему SVG

Круг из border-radius на боксе в 13px при дробном DPR растрируется с центром на полупикселе, и на вращении это видно как биение. У SVG центр задан в системе координат viewBox, поворот применяется к боксу целиком, растеризация происходит после — биения нет ни при каком DPR.

Правила

Так Спиннер со словом

Долгое ожидание сопровождается подписью: «Идёт прогон». Кольцо сообщает, что машина занята, но не чем именно.

Не так Спиннер вместо доли

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

Доступность

Роль role="status" + aria-label. Спиннер без роли — просто картинка, и для скринридера ожидание не начинается
Не единственный носитель Долгое ожидание сопровождается словами: «Идёт прогон», а не одним крутящимся кольцом
Уменьшенное движение Оборот замедляется до 2.4с, а не останавливается. Схлопнуть анимацию до 0.01ms — это не сжатие длительности, а остановка: спиннер замер бы в случайной фазе, и кит перестал бы показывать, что машина занята
Контраст Дуга --accent-mark держит 3:1 против дорожки, а не только против фона
Печать На листе не печатается: печать статична

API

ИмяЗначениеЧто делает
класс
inst-spinnerБазовый. Ставится на <svg>
inst-spinner-trackДорожка. Прямой потомок inst-spinner
inst-spinner-arcДуга. Прямой потомок inst-spinner
токен
--size-spinner13px
--border-controllight-dark(oklch(0 0 0 / 0.46), oklch(1 0 0 / 0.38))
--accent-marklight-dark(var(--a-4), var(--a-3))

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