SSB - Единый стандарт для кнопок

SSB - Единый стандарт для кнопок
Стандарты

31

5 мин.

Определения

Стандарт SSB определяет требования к семантике, доступности и логике работы кнопок.

Структура и семантика

Назначение и тип кнопки

  • Для действий используется нативный элемент <button>. Элементы <div> и <span> с обработчиками событий не заменяют кнопку: они не получают её поведение с клавиатуры и семантику автоматически.
  • Атрибут type указывается явно для каждой кнопки. Его значение отражает действие, а не только расположение кнопки:
    • type="submit" — отправка связанной формы;
    • type="button" — действие интерфейса без отправки или сброса формы;
    • type="reset" — возврат элементов формы к исходным значениям.
  • Отсутствующий type может привести к отправке формы: значение по умолчанию зависит от контекста и связи кнопки с формой. Кнопка может быть связана с формой через атрибут form, даже если она расположена вне <form>.
  • type="reset" применяется только тогда, когда возврат к исходным значениям является ожидаемым действием. Такой сброс не обязательно очищает поля: элементам формы восстанавливаются значения по умолчанию.

Группировка кнопок

  • Связанные кнопки объединяются семантически. Для обычной группы применяется role="group" с доступным именем; для набора связанных полей формы подходит <fieldset> с <legend>.
  • role="toolbar" используется для настоящей панели инструментов, а не как универсальная замена группе. Такая панель реализует клавиатурное перемещение между элементами стрелками и соответствующее управление фокусом.
  • Для кнопки-переключателя с постоянной подписью состояние передаётся через aria-pressed="true" или aria-pressed="false". Если подпись меняется, например с «Воспроизвести» на «Приостановить», aria-pressed обычно не добавляется.

Доступность

Доступное имя и клавиатура

  • Текст кнопки обычно служит её доступным именем. Иконка без видимой подписи получает понятное имя через aria-label или aria-labelledby.
  • Иконка, дополняющая уже понятную текстовую подпись, помечается как декоративная, например с помощью aria-hidden="true". Дублирующее имя через aria-label не добавляется без необходимости.
  • Нативная кнопка активируется клавишами Enter и Space. Пользовательские обработчики не должны нарушать стандартную клавиатурную активацию или вызывать одно действие дважды.
  • После обычного действия фокус остаётся на кнопке. Если действие открывает диалог или меняет контекст, перемещение фокуса определяется новым контекстом и его требованиями к доступности.

Фокус и состояния

  • Индикатор фокуса не удаляется без равноценной видимой замены. Для оформления клавиатурного фокуса применяется :focus-visible; его контраст и видимость проверяются на всех используемых фонах.
  • Состояния :hover, :active, :focus-visible и :disabled должны различаться визуально там, где они применимы. Состояние наведения не используется как единственный способ показать действие: оно недоступно при касании и не заменяет состояния фокуса или нажатия.
  • Атрибут disabled используется для нативного недоступного состояния. В отличие от aria-disabled="true", он блокирует активацию кнопки и исключает её из обычной последовательности фокуса.
  • aria-disabled="true" применяется только при необходимости оставить недоступную кнопку в последовательности фокуса. В этом случае блокировка действия и его обработчика должна быть реализована отдельно.

Асинхронные действия

  • При асинхронном действии повторный запуск предотвращается, если он может привести к дублированию операции. Кнопка может временно получать disabled, пока операция выполняется.
  • aria-busy="true" указывает, что соответствующий элемент обновляется, но сам по себе не гарантирует объявление текста загрузки. Изменение статуса передаётся отдельно, например через элемент role="status".
  • По завершении операции состояние aria-busy сбрасывается, кнопка возвращается в актуальное состояние, а результат или ошибка становятся доступны пользователю.

Интерактивность и визуальное оформление

Курсор и отклик

  • В проектах, где курсор используется для обозначения действия, для доступных к нажатию кнопок задаётся cursor: pointer, а для отключённых — cursor: not-allowed. Курсор является только визуальной подсказкой и не заменяет семантику или состояния кнопки.
  • Для состояния нажатия может применяться небольшой визуальный отклик, например смещение кнопки на 1px. Эффект не должен мешать восприятию текста, фокуса или других состояний.
  • Анимации переходов сокращаются или отключаются при prefers-reduced-motion: reduce, если движение не необходимо для понимания изменения состояния.

Размер области нажатия

  • Размер интерактивной области проверяется на сенсорных устройствах. Для соответствия WCAG 2.2 SC 2.5.8 целевой размер должен быть не менее 24 × 24 CSS-px либо должно выполняться одно из предусмотренных критерием исключений, например достаточный интервал между соседними целями.
  • Видимая иконка может быть меньше области нажатия; размер самой кнопки или её контейнера при этом обеспечивает доступную целевую область.

Тестирование

  • У каждой кнопки явно задан подходящий type; отдельно проверяется поведение кнопок внутри формы и кнопок, связанных с ней через атрибут form.
  • Кнопка работает с клавиатуры, мыши и сенсорного ввода; обычная активация не перемещает фокус неожиданно.
  • Доступные имена и состояния кнопок понятны при проверке со скринридером. Иконки без текста не остаются без имени.
  • Состояния :hover, :active, :focus-visible, disabled и загрузки различимы и не зависят только от цвета или курсора.
  • Проверяются повторное нажатие во время асинхронного действия, объявление статуса, а также доступность сообщения об ошибке или результате.
  • Группы элементов используют подходящую семантику. Для role="toolbar" дополнительно проверяются навигация стрелками, управление фокусом и поведение клавиш Tab.
  • Область нажатия проверяется на соответствие WCAG 2.2 SC 2.5.8 с учётом применимых исключений.

Примеры

Явно заданные типы кнопок:

<form action="/subscribe" method="post">
  <button type="submit">Подписаться</button>
  <button type="reset">Вернуть исходные значения</button>
</form>

<button type="button">Открыть настройки</button>

Кнопка только с иконкой и группа кнопок:

<button type="button" aria-label="Удалить">
  <svg aria-hidden="true" viewBox="0 0 24 24">...</svg>
</button>

<div role="group" aria-label="Форматирование">
  <button type="button" aria-pressed="false">Жирный</button>
  <button type="button" aria-pressed="false">Курсив</button>
  <button type="button" aria-pressed="false">Подчёркнутый</button>
</div>

Состояния кнопки и клавиатурный фокус:

button:enabled {
  cursor: pointer;
  transition: transform 120ms ease;
}

button:disabled {
  cursor: not-allowed;
}

button:hover:enabled {
  background-color: #e0e0e0;
}

button:active:enabled {
  background-color: #d0d0d0;
  transform: translateY(1px);
}

button:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  button {
    transition: none;
  }
}

Цвет индикатора фокуса и фона выбирается с учётом контраста в интерфейсе. Псевдокласс :focus-visible зависит от эвристик браузера и может отображаться не только при вводе с клавиатуры.

Асинхронная операция с отдельным статусом:

<div aria-busy="true">
  <button type="submit" disabled>Сохранение...</button>
</div>

<p role="status">Изменения сохраняются</p>

aria-busy обозначает обновляемую область, а role="status" сообщает об изменении статуса без принудительного перемещения фокуса. После завершения операции область перестаёт быть занятой, кнопка обновляется, а статус сообщает о результате.

Похожие статьи

  • Анатомия React компонента

    Моё видение того, как должен выглядеть React компонент

    421

    7 мин.

  • SST-A - Единый стандарт для табов

    Стандарт SST-A определяет требования к семантике, доступности и логике работы табов

    62

    6 мин.

  • SSF-U - Единый стандарт для фуллскрина

    Стандарт SSF-U определяет требования к семантике, доступности и логике работы фуллскрина

    248

    2 мин.

  • SSA - Единый стандарт для аккордеона

    Стандарт SSA определяет требования к семантике, доступности и логике работы аккордеона

    258

    2 мин.

  • Bad Practices для сайтов

    Разбор критических ошибок веб-дизайна. Почему слайдеры, автоплей и тяжёлые страницы снижают конверсию и позиции в Google и Yandex

    232

    1 мин.

  • SSP - Единый стандарт для пагинации

    Стандарт SSP определяет требования к семантике, доступности и логике работы пагинации

    240

    1 мин.

  • Все статьи

Свяжитесь со мной