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

Ввод

Слайдер

JS по желанию Число рядом с бегунком. Без скрипта слайдер работает целиком

Нативный input[type=range], приведённый к метрике кита. Значение выбирают положением на шкале: слайдер отвечает на «побольше или поменьше», а не на «сколько именно».

Компонент
Разметка
<input class="inst-slider" type="range" min="0" max="16" value="6" step="1"
       id="agents" aria-label="Параллельных агентов">

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

<input class="inst-slider" type="range" min="0" max="100" value="72"
       aria-label="Плотность растительности">
Что Обязательно Почему
type="range" да Всё поведение — от платформы: клавиатура, шаг, объявление значения. Класс оформляет нативные псевдоэлементы и на другом типе не делает ничего
min и max да Без границ шкала неинтерпретируема, а aria-valuemin/max платформа выведет из них сама
<label for> или aria-label да У слайдера нет собственного текста
step нет Умолчание — 1. Ставьте явно, когда шаг не единица
<output for> для числа нет Семантическая связь вместо подписи, меняющейся на каждом шаге

Слайдер тянется на 100% ширины контейнера. В ряду с другими элементами дайте ему явный flex и min-inline-size: 0, иначе он вытолкнет соседа на следующую строку.

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

Используйте Возьмите другое
Приблизительное значение из непрерывного диапазона: громкость, плотность, порог Точное число, которое вводят цифрамичисловое поле или текстовое поле: попасть бегунком в 47 из 100 нельзя
Диапазон, у которого видно оба конца и текущее положение Значение без известных граництекстовое поле: у слайдера обязаны быть min и max
Настройка, которую крутят и сразу видят результат Включение и выключение — свитч в переключателях
Строка свойства в инспекторе Показ величины без вводамера: слайдер выглядит как контрол и приглашает его тянуть

Устройство

Бегунок несёт кольцо цвета поверхности и остаётся различимым, когда наезжает на собственную дорожку. Дорожка берёт --track плюс внутренний хайрлайн: её протяжённость показывает граница, а не цвет заливки, поэтому дорожка может оставаться светлой.

Часть Токен размера Замечание
Дорожка --size-track, 4px --track плюс хайрлайн --border
Бегунок --size-thumb, 14px В плотности compact — 12px, в comfortable — 16px
Общая высота --size-icon, 16px Чтобы слайдер вставал в строку свойства по той же метрике, что значок

Нажатие увеличивает бегунок до 1.15 — отклик надо почувствовать, а не разглядывать.

Заполненной части дорожки у слайдера кита нет: она требует либо проприетарного ::-moz-range-progress без аналога в Chromium, либо градиента, пересчитываемого скриптом на каждом шаге. Положение бегунка и есть значение.

Поведение

Вывод значения

Число рядом с бегунком держит kit.js. Связать положение с текстом средствами CSS нельзя, поэтому это делает модуль: объявите <output for> — дальше он сам.

Без модуля слайдер полностью работает: значение уходит с формой, скринридер объявляет его на каждом шаге. Не обновляется только видимое число.

Пример
6
Разметка
<div class="inst-cluster">
  <input class="inst-slider" type="range" min="0" max="16" value="6" step="1"
         id="sl" aria-label="Параллельных агентов">
  <output for="sl">6</output>
</div>

Пример живой: потяните бегунок — число меняет кит.

<output for> связывает число со слайдером семантически, поэтому дублировать его в aria-label не нужно — и не следует: подпись, меняющаяся на каждом шаге, превращает объявление в шум.

JS

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

<script type="module" src="src/kit.js"></script>

Что делает кит

Пример в разделе «Вывод значения» живой: потяните бегунок, число рядом меняет кит.

Держит в <output for> текущее значение бегунка — при вводе и при загрузке страницы. Связь уже объявлена атрибутом for; синхронизировать её вручную значило бы писать одну и ту же строку в каждом приложении.

Без модуля слайдер полностью работает: значение уходит с формой, скринридер объявляет его на каждом шаге. Не обновляется только видимое число.

События

Своих нет — читайте нативный input.

sl.addEventListener('input', (e) => preview.setAgents(+e.target.value));

Методы

refresh(root) проставляет числа заново. Нужно, если разметка пришла в обход наблюдателя — например, в тесте.

Композиции

В строке свойства

Пример
Плотность
Разметка
<div class="inst-prop">
  <span class="inst-prop-label" title="Плотность растительности">Плотность</span>
  <span class="inst-prop-control">
    <input class="inst-slider" type="range" min="0" max="100" value="72"
           aria-label="Плотность растительности">
  </span>
</div>

С подписью и подсказкой

Пример
Ниже порога агент запрашивает подтверждение
Разметка
<div class="inst-field">
  <label class="inst-label" for="thr">Порог уверенности</label>
  <input class="inst-slider" type="range" min="0" max="100" value="80" step="5"
         id="thr" aria-describedby="thr-hint">
  <span class="inst-field-hint" id="thr-hint">Ниже порога агент запрашивает подтверждение</span>
</div>

Правила

Так Слайдер для приблизительного

«Побольше или поменьше» — единственный вопрос, на который он отвечает быстрее поля.

Не так Слайдер для точного числа

Попасть бегунком в 47 из 100 зависит от моторики. Там, где число задают точно, нужна пара «слайдер плюс поле».

Так Число через output

<output for> связан со слайдером семантически и не мешает объявлению значения.

Не так Значение в aria-label

Подпись, меняющаяся на каждом шаге, превращает объявление в шум.

Доступность

Клавиатура Стрелки — шаг, PageUp и PageDown — крупный шаг, Home и End — концы диапазона. Всё нативное, кит ничего не перехватывает
Роль и значение slider с aria-valuenow — от платформы. Руками ставить не нужно, а aria-valuetext пригодится, когда число само по себе непонятно: «6 агентов» вместо «6»
Имя <label for> или aria-label. Число выводится через <output>, а не подмешивается в имя
Фокус Нативное кольцо. Оно рисуется вокруг контрола целиком — бегунок 14px кольца не удержал бы
Контраст Бегунок держит 3:1 против поверхности и против дорожки: кольцо цвета поверхности разделяет их там, где они накладываются
Цель нажатия Бегунок 14px — ниже 24px по WCAG 2.5.8, но нажатие принимает дорожка по всей высоте --size-icon, а положение достижимо с клавиатуры. Там, где слайдер единственный способ задать значение, дайте рядом числовое поле
Точность Слайдер не годится для значений, которые надо задать точно: попадание в конкретное число зависит от моторики. Пара «слайдер плюс поле» решает это
Уменьшенное движение Увеличение бегунка при нажатии — переход, а не бесконечная анимация: схлопывается вместе со всеми переходами

API

ИмяЗначениеЧто делает
класс
inst-sliderЕдинственный класс. Ставится на input[type=range]
токен
--size-track4px
--size-thumb14px
--size-icon16px
--tracklight-dark(oklch(0 0 0 / 0.10), oklch(1 0 0 / 0.16))
--borderlight-dark(oklch(0 0 0 / 0.12), oklch(1 0 0 / 0.11))
--hairline1px
--accent-marklight-dark(var(--a-4), var(--a-3))
--surface-raisedlight-dark(var(--n-0), var(--n-12))
--radius-full999px
--dur-180ms
--ease-outcubic-bezier(0.22, 0.61, 0.36, 1)

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