К содержанию

Навигация

Фокус

Кольцо фокуса показывает, где находится человек, который работает с клавиатуры. Framework задаёт одно кольцо на всю систему, поэтому оно одинаково видно в любом компоненте и меняется в одном месте.

Одно кольцо на всю систему

Клавиатурный фокус — единственное, по чему человек без мыши понимает, где он находится. Поэтому кольцо в Framework одно: компонент его не изобретает, а берёт четыре переменные:

Переменная Значение Почему
--sf-focus--width 2 px Нижняя граница площади индикатора по WCAG 2.2; кольцо в 1 px её не набирает
--sf-focus--style solid Полупрозрачное кольцо даёт контраст 1,4:1 вместо нужных 3:1
--sf-focus--offset 1 px Зазор показывает поверхность за контролом, и кольцу есть на чём читаться
--sf-focus--color роль --sf-focus (Служебные роли) Проект меняет её один раз, и это действует везде

Ширина и зазор кольца заданы в пикселях, через --sf-px, а не в rem. Кольцо остаётся сплошной линией 2 px с зазором 1 px при любом корневом кегле и не растёт вместе с ним.

Пример показывает, из чего собрано кольцо. Глобальное правило ядра уже рисует его на любом элементе с фокусом (Особые случаи), поэтому своё правило контролу проекта нужно, только если кольцо должно отличаться:

CSS
.project-control:focus-visible {
    outline: var(--sf-focus--width) var(--sf-focus--style) var(--sf-focus--color);
    outline-offset: var(--sf-focus--offset);
}

Значения подобраны по измерениям. Например, кольцо вплотную к переключателю на синей дорожке даёт контраст 1,0:1, а зазор в один пиксель это исправляет.

Только с клавиатуры

Кольцо появляется через :focus-visible, то есть при работе с клавиатуры. При щелчке мышью его нет: место назначения и так видно.

  • Нельзя подменять :focus-visible на :focus: кольцо начнёт появляться на каждом щелчке.

Кольцо — контур, а не тень

Кольцо рисуется свойством outline. Тень для этого не подходит: она делит свойство с высотой элемента, рисуется поверх соседей и пропадает в режиме высокой контрастности. Токен --sf-ui-focus — теневое кольцо; он сохранён для совместимости, новых мест ему не отдают.

В утилитах тот же выбор: focus-visible:outline-* рисует настоящий контур, а focus-visible:ring-* — тень (Кольцо). Для кольца фокуса берите контур. Префикс focus: срабатывает и после щелчка мышью, поэтому для кольца фокуса берите focus-visible:. В режиме высокой контрастности (forced-colors) кольцо рисуется системным цветом: цветом текста элемента или цветом выделения Highlight. Цвет контура в этом режиме подменяет сам браузер, поэтому кольцу собственного контрола проекта ничего добавлять не нужно.

Особые случаи

  • Элемент вплотную к соседям (сегмент группы кнопок, вкладка, ячейка календаря, строка списка). Внешнее кольцо закрыло бы соседа или его обрезал бы контейнер с прокруткой, поэтому кольцо поворачивается внутрь: outline-offset: calc(var(--sf-focus--width) * -1).

  • Залитый элемент. Заливка может оказаться соседней ступенью той же палитры, что и кольцо. Например, в тёмной теме контраст кольца к заливке основной кнопки — 1,31:1. Поэтому залитая кнопка рисует внутри вторую линию цветом своей подписи: он контрастен заливке по построению. Линия складывается с тенью высоты кнопки, а не заменяет её.

  • Собственный контрол проекта. Глобальное правило ядра :focus-visible { outline: … var(--sf-focus--*) } стоит в слое sf.base и рисует кольцо на любом элементе, который получил фокус с клавиатуры, в том числе на элементе проекта с tabindex="0" или role="button". Своё правило :focus-visible контролу проекта нужно, только если кольцо должно отличаться, например поворачиваться внутрь. То же кольцо рисует и класс .focus-visible.

  • Кто владеет кольцом. Глобальное правило красит элемент, который держит фокус. Если компонент рисует кольцо на видимой обёртке (у поля это рамка поля, у флажка — коробка, у переключателя — дорожка), он обязан снять кольцо с нативного элемента внутри. Иначе колец будет два:

    CSS
    .project-field:has(input:focus-visible) .project-field-box {
        outline: var(--sf-focus--width) var(--sf-focus--style) var(--sf-focus--color);
        outline-offset: var(--sf-focus--offset);
    }
    
    .project-field input:focus-visible {
        outline: none;
    }
    

Правило:

  • Нельзя убирать кольцо без равноценной замены: outline: none в одиночку делает элемент невидимым для клавиатуры.
  • Нельзя рисовать кольцо тенью: оно закроет соседа и пропадёт в режиме высокой контрастности.
  • Нельзя заводить свой цвет кольца: проект меняет роль --sf-focus один раз, и это действует везде.

Смотрите также

Поиск по документации

Введите минимум 2 символа

    Настройки

    Тема
    Размер шрифта
    Ширина страницы