На главную

Улучшаем стандартный фокус


Я очень люблю простые куски CSS-кода, которые добавляешь, и они делают сайт лучше. Вдвойне больше люблю, когда они просто работают и не требуют дальнейшего внимания.

Вот один из моих любимчиков, который позволяет придерживаться правила «не отключайте outline».

*:focus-visible {
  outline: 3px solid #000000;
  outline-offset: 0.25rem;
  border-radius: 0.13rem;
}

Этот трюк добавляет для всех интерактивных элементов закруглённый outline. Большего мне и не нужно.

Напомню, что делает :focus-visible. Селектор применяется только тогда, когда фокус был получен клавиатурой или другими средствами доступности (например, экранными читалками).

Второй вариант

Первый вариант, конечно, уже достаточно хороший, но он немного скучный. Он всегда чёрного цвета.

*:focus-visible {
  outline: 3px solid currentcolor;
  outline-offset: 0.25rem;
  border-radius: 0.13rem;
}

Теперь цвет обводки будет зависеть от color интерактивного элемента.

currentcolor отныне и во веки веков можно писать без заглавных букв — это разрешает спецификация CSS Color Module Level 4

Третий вариант

Первый вариант также не подходит для сайтов с тёмной темой, так как цвет обводки всегда чёрный.

*:focus-visible {
  outline: 3px solid -webkit-focus-ring-color;
  outline-offset: 0.25rem;
  border-radius: 0.13rem;
}

-webkit-focus-ring-color — это аналог дефолтного цвета outline в браузере. Такой цвет outline на самом деле состоит из нескольких слоёв и отлично работает на любой теме. Но, честно говоря, я не уверен, какова поддержка -webkit-focus-ring-color в разных браузерах. Поэтому перейдём к следующему варианту.

Четвёртый вариант

Продолжим решать проблему совместимости сразу для светлой и тёмной темы.

*:focus-visible {
  outline: 3px solid #000000;
  outline-offset: 0.25rem;
  border-radius: 0.13rem;
}

@media (prefers-color-scheme: dark) {
  *:focus-visible {
    outline-color: #ffffff;
  }
}

Теперь с помощью медиавыражения мы задаём белый цвет для outline, когда у пользователя включена тёмная тема.

Пятый вариант

Предыдущий (четвёртый) вариант можно сократить до light-dark(#000000, #ffffff) в современных браузерах:

*:focus-visible {
  outline: 3px solid light-dark(#000000, #ffffff);
  outline-offset: 0.25rem;
  border-radius: 0.13rem;
}

Но рекомендовано добавить:

:root {
  color-scheme: light dark;
}

Шестой вариант

Есть ещё один вариант похожий на третий с -webkit-focus-ring-color;. Можно указать всё кроме outline.

*:focus-visible {
  outline-offset: 0.25rem;
  border-radius: 0.13rem;
}

В этом случае обводка точно получается трёхслойного браузерного цвета, но есть ограничение: нельзя указать размер обводки(outline-width), а если укажем, то ничего не поменяется.

Итого

Какой же вариант выбрать? Ответ, как и всегда: «зависит от ситуации и вашего проекта». А если знаешь варианты как улучшить изначальный пример, то пиши мне в чат в телеграм-канале.