В чём разница между Focus visibile и Focus within?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между :focus-visible и :focus-within
Контекст: CSS pseudo-классы для фокуса
Эти два pseudo-класса решают разные задачи управления фокусом элементов:
:focus /* Элемент имеет фокус (любым способом) */
:focus-visible /* Элемент имеет фокус И должен показать визуальный индикатор */
:focus-within /* Любой потомок элемента имеет фокус */
:focus-visible
:focus-visible выбирает элемент, который имеет фокус И браузер определил, что видимый индикатор фокуса необходим (для доступности).
Когда срабатывает:
- Клавиша Tab (клавиатурная навигация) - СРАБАТЫВАЕТ
- Клик мышью - НЕ срабатывает обычно
- Клик мышью на элемент, который требует видимого индикатора (input, button, link) - может сработать
Примеры использования:
/* Стиль для видимого фокуса (клавиатура) */
.button:focus-visible {
outline: 2px solid blue;
outline-offset: 2px;
}
/* Эквивалент для старых браузеров */
.button:focus-visible {
box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.3);
}
HTML и результат:
<button class="button">Click me</button>
<style>
.button {
padding: 10px 20px;
border: 2px solid gray;
background: white;
}
/* Фокус видимой только с клавиатуры */
.button:focus-visible {
outline: 3px solid blue;
outline-offset: 2px;
}
/* Состояние при клике мышью - БЕЗ синей обводки */
.button:active {
background: lightblue;
}
</style>
Различие между :focus и :focus-visible:
/* Срабатывает при клавиатуре И мышке */
.input:focus {
border: 2px solid blue;
box-shadow: inset 0 0 0 1px blue;
}
/* Срабатывает ТОЛЬКО при клавиатуре */
.input:focus-visible {
outline: 2px solid blue;
outline-offset: 2px;
}
Практический пример:
<input type="text" placeholder="Нажми Tab или кликни" />
<style>
input:focus {
/* Может срабатывать при обоих действиях */
border-color: blue;
}
input:focus-visible {
/* Только при Tab - для улучшенной доступности */
box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);
}
</style>
:focus-within
:focus-within выбирает элемент, если ОН или ЛЮБОЙ ЕГО ПОТОМОК имеет фокус.
Когда срабатывает:
- Фокус на самом элементе
- Фокус на любом элементе внутри
- Останавливается при выходе фокуса из элемента и его потомков
Примеры использования:
/* Стилизация формы, когда в неё кто-то вводит данные */
.form:focus-within {
border-color: blue;
box-shadow: 0 0 10px rgba(0, 0, 255, 0.3);
}
/* Стилизация контейнера поиска */
.search-container:focus-within {
box-shadow: 0 0 0 2px blue;
}
HTML пример:
<div class="form">
<label>Имя:</label>
<input type="text" name="name" />
<label>Email:</label>
<input type="email" name="email" />
<button>Отправить</button>
</div>
<style>
.form {
padding: 20px;
border: 2px solid gray;
border-radius: 8px;
}
/* Вся форма подсвечивается, когда любой input в фокусе */
.form:focus-within {
border-color: blue;
background-color: rgba(0, 0, 255, 0.05);
box-shadow: 0 0 10px rgba(0, 0, 255, 0.2);
}
.form input:focus {
outline: none;
border-color: blue;
}
</style>
Сравнение
| Свойство | Что выбирает | Срабатывает при | Примеры использования |
|---|---|---|---|
| :focus-visible | Элемент с видимым индикатором фокуса | Клавиатура (Tab) или браузер решает показать индикатор | Кольца вокруг кнопок, outline на input |
| :focus-within | Элемент ИЛИ его потомок в фокусе | Фокус на себе или потомке | Подсветка контейнера формы, обводка parent |
Практические примеры
Пример 1: Поиск с визуальной обратной связью
<div class="search-box">
<input type="text" placeholder="Поиск..." />
<button>Найти</button>
</div>
<style>
.search-box {
display: flex;
border: 2px solid #ddd;
border-radius: 8px;
padding: 4px;
transition: border-color 0.2s;
}
/* Подсвечиваем весь контейнер, когда input в фокусе */
.search-box:focus-within {
border-color: #007BFF;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
}
.search-box input {
flex: 1;
border: none;
outline: none;
padding: 8px;
}
.search-box button {
border: none;
background: white;
cursor: pointer;
padding: 4px 12px;
}
/* Кнопка подсвечивается, когда её самой даётся фокус */
.search-box button:focus-visible {
outline: 2px solid #007BFF;
outline-offset: 2px;
}
</style>
Пример 2: Форма с групповой стилизацией
<fieldset class="form-group">
<legend>Личные данные</legend>
<input type="text" placeholder="Имя" />
<input type="email" placeholder="Email" />
<input type="phone" placeholder="Телефон" />
</fieldset>
<style>
.form-group {
border: 2px solid #ddd;
padding: 16px;
border-radius: 8px;
transition: all 0.2s;
}
/* Вся группа подсвечивается, когда в неё вводят данные */
.form-group:focus-within {
border-color: #007BFF;
background-color: rgba(0, 123, 255, 0.02);
}
.form-group input {
display: block;
width: 100%;
margin-bottom: 12px;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
/* Индикатор для клавиатурной навигации */
.form-group input:focus-visible {
outline: 2px solid #007BFF;
outline-offset: 2px;
}
</style>
Пример 3: Интерактивная кнопка
<button class="btn">Нажми меня</button>
<style>
.btn {
padding: 10px 20px;
border: 2px solid #ddd;
background: white;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
/* Только при клавиатурной навигации показываем видимый фокус */
.btn:focus-visible {
outline: 3px solid #007BFF;
outline-offset: 2px;
background-color: #f0f8ff;
}
/* При клике мышью - просто подсвечиваем */
.btn:active {
background-color: #e8f4ff;
}
/* Hover эффект */
.btn:hover {
border-color: #007BFF;
}
</style>
Доступность (Accessibility)
:focus-visible - это ключевое свойство для доступности:
/* ПЛОХО - удаляет индикатор фокуса */
button:focus {
outline: none; /* Не делай так! */
}
/* ХОРОШО - используй :focus-visible */
button:focus-visible {
outline: 2px solid blue;
}
:focus-within помогает пользователям понять, какая область активна:
/* Пользователи с нарушениями зрения видят, что они в форме */
.form:focus-within {
border-color: blue;
background-color: lightyellow;
}
Поддержка браузерами
- :focus-visible - поддерживается во всех современных браузерах (но не в старых IE)
- :focus-within - поддерживается во всех современных браузерах (но не в старых IE)
Для старых браузеров можно использовать fallback:
/* Fallback для браузеров без :focus-visible */
.button:focus {
outline: 2px solid blue;
}
/* Современные браузеры переопределят это */
.button:focus-visible {
outline: 2px solid blue;
}
Заключение
- :focus-visible - стилизует элемент с видимым индикатором фокуса (обычно при клавиатуре)
- :focus-within - стилизует элемент, если он ИЛИ его потомок в фокусе
- Используй :focus-visible для улучшенной доступности и UX
- Используй :focus-within для подсветки контейнеров (формы, поиск)
- Никогда не удаляй outline без замены (для доступности)