Укрощаем фокус: как легально убрать синюю рамку и не разозлить 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-канале. Подписывайтесь, чтобы не пропустить!