Гайд по использованию :focus-visible для улучшения UX

Укрощаем фокус: как легально убрать синюю рамку и не разозлить UX-дизайнера

Налей себе кофе, присаживайся. Сегодня поговорим о боли, которая знакома каждому, кто хоть раз верстал интерфейсы средней сложности. Представь картину: ты сдаешь проект, все пиксели на месте, анимации плавные. Но тут приходит дизайнер с круглыми глазами и кричит: «Что это за уродливая синяя рамка вокруг кнопок, когда я по ним кликаю?! Срочно убери!»

Ты, желая угодить, послушно пишешь в CSS что-то вроде outline: none;. Дизайнер счастлив, проект сдан. А через неделю прилетает баг-репорт от тестировщиков или, что еще хуже, гневный отзыв от пользователя, который управляет сайтом с клавиатуры. Он просто не видит, где сейчас находится фокус. Доступность (accessibility) разрушена, UX катится в бездну.

К счастью, в современном вебе у нас есть элегантное решение этой проблемы — псевдокласс :focus-visible. Давай разберемся, как он работает и почему это стандарт де-факто в 2026 году.

Как мы страдали раньше

Раньше выбор у нас был небогатый. Псевдокласс :focus срабатывал всегда: и когда пользователь кликал по кнопке мышкой, и когда он переходил по элементам с помощью клавиши Tab. Браузеру было все равно на способ ввода, он честно рисовал дефолтный outline.

Чтобы решить эту проблему, разработчики шли на дикие костыли:

  • Писали JS-скрипты, которые отслеживали нажатие клавиши Tab, вешали класс .user-is-tabbing на тег body и только тогда включали обводку для фокуса.
  • Использовали полифилы, которые грузили фронтенд лишними килобайтами JS-кода.
  • Просто вырезали outline под корень, наплевав на доступность.

Особенно больно это было делать при создании кастомных UI-компонентов. Кстати, если тебе интересно, как создавать сложные кастомные элементы управления без единой строчки JS, загляни в наш гайд Интерактивные элементы на чистом CSS: чекбоксы вместо JS. Там мы разбираем крутые приемы, которые отлично дополнят сегодняшнюю тему.

Как делать правильно в 2026 году

Современный стандарт предлагает четкое разделение обязанностей. У нас есть два инструмента:

  • :focus — срабатывает при любом фокусе на элементе (клик, тач, клавиатура).
  • :focus-visible — умный селектор. Он активируется только тогда, когда браузер понимает, что пользователю действительно нужно визуально подсветить элемент. Например, при навигации с клавиатуры. Если пользователь кликает по кнопке мышкой или тапает пальцем на смартфоне, рамка не появится и не будет раздражать перфекционистов.

Для создания красивого и гибкого фокуса идеально использовать CSS-переменные. Напомню, что переменные — это основа масштабируемого дизайна, и с их помощью мы можем управлять стилем фокуса глобально для всего проекта.

Давай посмотрим на красивую и современную реализацию стилизации фокуса.

Готовый сниппет кода

Вот шаблон, который ты можешь забрать в свой проект прямо сейчас. Здесь мы используем современный подход: сбрасываем стандартный фокус для кликов мыши, но делаем его заметным и эстетичным для клавиатурного ввода.

/* Глобальные настройки темы фокуса */
:root {
  --focus-ring-color: #3b82f6;
  --focus-ring-width: 3px;
  --focus-ring-offset: 2px;
}

/* 1. Сбрасываем дефолтный outline для обычного фокуса (клик мыши),
   но ТОЛЬКО если браузер поддерживает :focus-visible.
   Это гарантирует фолбек для старых систем. */
@supports selector(:focus-visible) {
  .button:focus {
    outline: none;
  }
}

/* 2. Стилизуем фокус только для тех, кому он реально нужен (клавиатура) */
.button:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
  border-radius: 4px; /* Чтобы рамка аккуратно огибала углы */
  transition: outline-offset 0.1s ease; /* Небольшая плавность для премиального UX */
}

/* 3. Опционально: если элемент имеет кастомный фон, делаем фокус контрастным */
.button-dark:focus-visible {
  --focus-ring-color: #ffffff;
}

Частая ошибка новичков

Самый распространенный факап, который я вижу на код-ревью у мидлов — это бездумное написание вот такой конструкции:

/* ТАК ДЕЛАТЬ НЕ НАДО */
button:focus {
  outline: none;
}
button:focus-visible {
  outline: 2px solid blue;
}

Казалось бы, а что тут не так? Проблема в старых браузерах, которые еще не умеют в :focus-visible (да, в 2026 году их мало, но они есть, особенно в специфичном корпоративном софте или старых Smart TV).

Если браузер не понимает селектор :focus-visible, он просто проигнорирует второе правило. Но первое правило outline: none он выполнит! В итоге пользователи старых браузеров полностью лишатся индикатора фокуса.

Поэтому всегда используй проверку через @supports selector(:focus-visible), как показано в нашем сниппете выше, либо аккуратно переопределяй стили, не ломая базовую доступность.

Внедряй этот подход в свои проекты, береги нервы дизайнеров и делай интерфейсы доступными для всех!

🔥 Больше фишек, готовых сниппетов и передовых подходов к CSS мы публикуем в нашем Telegram-канале. Подписывайтесь, чтобы не пропустить!

🚀 Прокачай свой код

Готовые CSS-сниппеты, разбор продвинутых фишек и эксклюзивные материалы — в нашем Telegram-канале.

Подписаться
error: Content is protected !!
Прокрутить вверх