← Назад к вопросам
В чем разница между :focus и :focus-within?
2.2 Middle🔥 111 комментариев
#HTML и CSS
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
В чем разница между :focus и :focus-within?
:focus применяется к элементу, который сам имеет фокус, а :focus-within применяется к элементу, если он сам или любой его дочерний элемент имеет фокус. Это кардинальная разница в области применения.
:focus — фокус на самом элементе
:focus срабатывает только когда конкретный элемент получает фокус (через Tab, клик мышью или programmatically).
/* Стиль применяется ТА ТОЛЬКО когда input имеет фокус */
input:focus {
border-color: #007bff;
outline: 2px solid #007bff;
background-color: #f8f9fa;
}
button:focus {
outline: 3px solid #ffd700;
outline-offset: 2px;
}
<input type="text" /> <!-- При клике сюда — :focus применится к INPUT -->
<button>Click me</button> <!-- При клике сюда — :focus применится к BUTTON -->
:focus-within — фокус в элементе или его детях
:focus-within срабатывает когда родительский элемент или любой его потомок получает фокус. Это очень полезно для целого контейнера (форма, окно и т.д.).
/* Стиль применяется всей ФОРМЕ если внутри есть element с фокусом */
form:focus-within {
border: 2px solid #007bff;
box-shadow: 0 0 0 4px rgba(0, 123, 255, 0.25);
}
/* Контейнер меняет цвет если внутри элемент в фокусе */
.input-group:focus-within {
background-color: #f0f7ff;
}
/* Иконка меняет цвет при фокусе на input внутри */
.input-group:focus-within .icon {
color: #007bff;
}
<form>
<div class="input-group">
<span class="icon">@</span>
<input type="email" /> <!-- При клике сюда — :focus-within применится к FORM и .input-group -->
</div>
</form>
Практическое сравнение
<!DOCTYPE html>
<html>
<head>
<style>
/* :focus — только когда label сам в фокусе (невозможно с помощью клика) */
label:focus {
color: red;
}
/* :focus-within — когда label ИЛИ его input имеет фокус */
label:focus-within {
color: blue;
background-color: #f0f0f0;
}
/* Только input в фокусе */
input:focus {
outline: 2px solid green;
}
</style>
</head>
<body>
<!-- Эта label получит :focus-within когда input в фокусе -->
<label>
Email:
<input type="email" />
</label>
<!-- Эта label получит :focus-within когда любой input в фокусе -->
<label :focus-within>
Профиль
<div>
<input type="text" placeholder="Имя" />
<input type="text" placeholder="Фамилия" />
</div>
</label>
</body>
</html>
Примеры использования
Пример 1: Подсвечивание всей формы при заполнении
.form-card {
border: 2px solid #ccc;
padding: 20px;
border-radius: 8px;
transition: all 0.3s;
}
/* Когда любое поле в форме получает фокус */
.form-card:focus-within {
border-color: #007bff;
box-shadow: 0 0 0 4px rgba(0, 123, 255, 0.1);
background-color: #f9fbfd;
}
<form class="form-card">
<input type="text" placeholder="Имя" />
<input type="email" placeholder="Email" />
<button>Отправить</button>
</form>
Пример 2: Изменение иконки в input группе
.input-wrapper {
position: relative;
display: flex;
align-items: center;
}
.input-wrapper input {
padding-left: 40px;
}
/* Иконка по умолчанию серая */
.input-wrapper .icon {
position: absolute;
left: 12px;
color: #999;
transition: color 0.2s;
}
/* Иконка становится синей при фокусе input */
.input-wrapper:focus-within .icon {
color: #007bff;
}
.input-wrapper:focus-within input {
border-color: #007bff;
outline: none;
}
<div class="input-wrapper">
<span class="icon">🔍</span>
<input type="text" placeholder="Поиск..." />
</div>
Пример 3: Модальное окно
/* Затемнение backdrop когда модаль в фокусе */
.modal-overlay {
display: none;
}
.modal:focus-within .modal-overlay {
display: block;
background-color: rgba(0, 0, 0, 0.5);
}
/* Увеличение z-index при фокусе */
.modal:focus-within {
z-index: 1000;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
}
React компонент с обоими стилями
import styles from ./FormField.module.css;
interface FormFieldProps {
label: string;
name: string;
type?: string;
required?: boolean;
}
export function FormField({
label,
name,
type = text,
required
}: FormFieldProps) {
return (
<div className={styles.fieldWrapper}>
{/* :focus-within для контейнера */}
<label className={styles.label} htmlFor={name}>
{label}
{required && <span className={styles.required}>*</span>}
</label>
{/* :focus для самого input */}
<input
className={styles.input}
id={name}
name={name}
type={type}
required={required}
/>
{/* Сообщение ошибки показывается при :focus-within */}
<span className={styles.errorMessage}>
Это поле обязательно
</span>
</div>
);
}
/* FormField.module.css */
.fieldWrapper:focus-within {
border-bottom: 2px solid #007bff;
background-color: rgba(0, 123, 255, 0.02);
}
.input:focus {
outline: none;
border-color: #007bff;
}
.fieldWrapper:focus-within .errorMessage {
display: block;
color: #dc3545;
font-size: 12px;
margin-top: 4px;
}
Когда использовать
| Ситуация | Использовать |
|---|---|
| Подсветить одно поле при вводе | :focus на input |
| Подсветить всю форму при заполнении | :focus-within на form |
| Изменить иконку рядом с input | :focus-within на обёртке |
| Ошибка валидации только текущего поля | :focus |
| Подсвечивание группы полей | :focus-within на контейнере группы |
| Покраска кнопки в зависимости от фокуса | :focus на button |
| Модальное окно с фокусом | :focus-within на .modal |
Поддержка браузерами
- :focus — поддерживается всеми браузерами
- :focus-within — поддерживается всеми современными браузерами (IE 11 не поддерживает)
Для IE 11 используй полифил или JavaScript:
// Простой полифил
document.addEventListener(focusin, (e) => {
e.target.classList.add(has-focus);
});
document.addEventListener(focusout, (e) => {
e.target.classList.remove(has-focus);
});
/* Используй класс вместо :focus-within для IE */
form.has-focus {
border-color: #007bff;
}
Ключевые выводы
- :focus — стиль применяется к элементу, который имеет фокус
- :focus-within — стиль применяется к элементу, если он или его потомок имеет фокус
- :focus-within идеален для форм, контейнеров и групп элементов
- :focus для отдельных интерактивных элементов
- Используй оба селектора для полного контроля над UI состоянием фокуса