CSS

CSS: псевдоклассы и псевдоэлементы

📚 20 вопросовПройти тест →
Лекция

CSS: псевдоклассы и псевдоэлементы

CSS

CSS: псевдоклассы и псевдоэлементы

Введение: интерфейс, который реагирует на пользователя

Представьте входную дверь с разными состояниями: закрыта, открывается, заблокирована.
С кнопками, ссылками и полями в интерфейсе та же логика: у каждого элемента есть состояние и визуальная реакция.
Псевдоклассы и псевдоэлементы в CSS как раз отвечают за такие моменты.
Они помогают сделать интерфейс понятным, доступным и аккуратным без лишней разметки.
💡 Совет: Всегда проектируйте hover вместе с focus-visible, а не отдельно.
Вывод: Псевдоклассы и псевдоэлементы превращают «статичную верстку» в живой UI.

Проблема -> решение

Проблема: Без состояний элементы выглядят одинаково: пользователь не понимает, что уже нажато, что доступно, где ошибка формы и где сейчас фокус.
Решение: Использовать псевдоклассы для состояния (:hover, :focus-visible, :checked) и псевдоэлементы для декоративных частей (::before, ::after, ::marker).
Вывод: Состояния и псевдоэлементы снимают большую часть базовых UX-проблем в интерфейсе.

Чем помогает и как работает

Псевдоклассы и псевдоэлементы помогают:
  • дать пользователю обратную связь при наведении, фокусе и клике;
  • подсветить ошибки и текущий статус формы;
  • добавить декоративные детали без лишних span и дополнительного HTML;
  • сделать код чище за счет селекторов состояния и структуры.
Как это работает:
  • Шаг 1: определяете, какие состояния важны для элемента (наведение, фокус, выбран, отключен).
  • Шаг 2: задаете базовый стиль элемента без состояния.
  • Шаг 3: добавляете псевдоклассы для интерактивных и структурных сценариев.
  • Шаг 4: добавляете псевдоэлементы там, где нужна декоративная часть (иконка, бейдж, маркер).
  • Шаг 5: проверяете доступность: виден ли фокус, не теряется ли смысл без декора.
  • Шаг 6: тестируете реальные сценарии: клавиатура, длинные тексты, disabled-состояния.
Вывод: Логика простая: состояние описываем псевдоклассом, визуальную добавку - псевдоэлементом.

Ключевые термины (простыми словами)

  • Pseudo-class (псевдокласс) - стиль элемента в конкретном состоянии.
  • Pseudo-element (псевдоэлемент) - виртуальная часть элемента, которой нет в HTML.
  • State (состояние) - текущий контекст элемента: наведён, в фокусе, выбран.
  • Selector specificity (специфичность) - приоритет селектора в конфликте стилей.
  • Focus ring (контур фокуса) - видимая подсветка элемента при навигации клавиатурой.
  • Structural selector (структурный селектор) - выбор элемента по позиции среди соседей.

1. Псевдокласс и псевдоэлемент: базовая разница

Назначение: Понимать, когда вы описываете состояние элемента, а когда добавляете его декоративную часть.
Простыми словами: Псевдокласс = «как элемент себя ведет», псевдоэлемент = «что у элемента визуально добавилось».
Для новичка: Если вы видите один двоеточие :, это чаще про состояние. Если двойное ::, это виртуальная часть элемента.
Аналогия: Псевдокласс - настроение человека, псевдоэлемент - его аксессуар.
Пример:
a:hover {  color: #2563eb;} .tag::before {  content: "•";  margin-right: 6px;}
🔎 Как это происходит на практике:
  • В карточке курса ссылка меняет цвет при наведении.
  • Перед названием курса добавляют точку-маркер через ::before.
  • HTML остается чистым, поведение и декор живут в CSS.
Характеристики:
  • : обычно для состояния;
  • :: обычно для визуальной части;
  • ✅ в реальных проектах используются вместе.
Когда использовать: Всегда, когда нужна обратная связь или декоративная деталь без усложнения HTML.
Вывод: Главный вопрос: это состояние элемента или отдельная визуальная часть?

2. Интерактивные состояния: :hover, :focus-visible, :active

Назначение: Показывать пользователю, что элемент доступен, выбран или нажат.
Простыми словами: Интерфейс должен отвечать на действие человека: навел, перешел клавишей Tab, нажал.
Для новичка: hover - мышь, focus-visible - клавиатура, active - момент нажатия.
Аналогия: Кнопка как физический выключатель: вы видите подсветку, фокус и клик.
Пример:
.btn:hover {  background: #2563eb;  color: #fff;} .btn:focus-visible {  outline: 3px solid #93c5fd;  outline-offset: 2px;} .btn:active {  transform: translateY(1px);}
🔎 Как это происходит на практике:
  • Дизайнер задает интерактивные состояния кнопки.
  • Разработчик реализует hover и active.
  • QA проверяет клавиатуру: при Tab фокус виден и не пропадает.
Характеристики:
  • hover не заменяет focus-visible;
  • active короткий, но важный для тактильности;
  • ✅ без фокуса страдает доступность.
Когда использовать: Для всех интерактивных элементов: ссылки, кнопки, пункты меню, вкладки.
Вывод: Качественный UI всегда учитывает мышь и клавиатуру одновременно.

3. Состояния форм: :checked, :disabled, :invalid, :required

Назначение: Показывать статус ввода и доступность действий в форме.
Простыми словами: Форма должна сразу сообщать: «выбрано», «нельзя нажать», «ошибка», «обязательное поле».
Для новичка: Когда человек заполняет форму, он должен видеть состояние без догадок.
Аналогия: Это как чек-лист с пометками: галочка, ошибка, блокировка.
Пример:
input:required {  border-color: #d1d5db;} input:invalid {  border-color: #ef4444;} input:checked + span {  color: #16a34a;} button:disabled {  opacity: 0.5;  cursor: not-allowed;}
🔎 Как это происходит на практике:
  • В форме подписки email невалиден - поле краснеет.
  • Пока чекбокс согласия не отмечен, кнопка отправки отключена.
  • После отметки чекбокса текст рядом подсвечивается.
Характеристики:
  • ✅ быстрое визуальное подтверждение;
  • ✅ меньше ошибок при вводе;
  • ✅ понятные состояния без JS для базовых кейсов.
Когда использовать: В любых формах: регистрация, фильтры, анкеты, настройки.
Вывод: Псевдоклассы форм напрямую влияют на конверсию и удобство.

4. Структурные псевдоклассы: :first-child, :last-child, :nth-child()

Назначение: Стилизовать элементы по их позиции внутри контейнера.
Простыми словами: Можно выбрать первый, последний, каждый второй или любой по формуле.
Для новичка: Это способ быстро сделать «зебру» в списке и не проставлять классы вручную.
Аналогия: Нумерация мест в поезде: можно оформить четные и нечетные по-разному.
Пример:
.card:first-child {  border-color: #2563eb;} .card:last-child {  margin-bottom: 0;} .card:nth-child(even) {  background: #f9fafb;}
🔎 Как это происходит на практике:
  • В каталоге карточек нужна визуальная ритмика.
  • Дизайнер просит выделить каждый второй элемент.
  • Разработчик добавляет :nth-child(even) без изменения HTML.
Характеристики:
  • ✅ меньше служебных классов;
  • ✅ быстрые локальные правки;
  • ✅ удобно для табличных и карточных списков.
Когда использовать: Когда стиль зависит от позиции элемента внутри списка.
Вывод: Позиционные селекторы экономят время, если использовать их осознанно.

5. Логические псевдоклассы: :is(), :not(), :has()

Назначение: Сокращать сложные селекторы и описывать условия точнее.
Простыми словами: Можно объединить несколько вариантов, исключить класс или выбрать родителя по состоянию потомка.
Для новичка: is = «любой из», not = «кроме», has = «содержит внутри».
Аналогия: Фильтр в магазине: включить нужные категории, исключить лишние, оставить товары с нужным признаком.
Пример:
.card:is(.is-new, .is-hot) {  border-color: #2563eb;} .btn:not(.is-disabled) {  cursor: pointer;} .form:has(input:invalid) {  border-color: #ef4444;}
🔎 Как это происходит на практике:
  • В компоненте много модификаторов, селекторы начинают дублироваться.
  • Команда использует :is() для группировки.
  • Через :has() родитель формы подсвечивается, если внутри есть ошибка.
Характеристики:
  • ✅ CSS становится короче;
  • ✅ условия читаются яснее;
  • ✅ легче сопровождать большой UI.
Когда использовать: В компонентах со сложными состояниями и несколькими вариациями.
Вывод: Логические псевдоклассы уменьшают дублирование и повышают читаемость CSS.

6. Контекстные состояния: :focus-within, :target, :empty

Назначение: Стилизовать блок в зависимости от контекста взаимодействия и содержания.
Простыми словами: Можно подсветить весь контейнер, когда фокус внутри, выделить раздел по якорю и обработать пустой блок.
Для новичка: Это «умные» селекторы: смотрят не только на сам элемент, но и на его окружение.
Аналогия: Подсветка комнаты, когда в ней кто-то есть, или указатель на главу, куда вы перешли по ссылке.
Пример:
.field-group:focus-within {  border-color: #2563eb;} section:target {  outline: 2px solid #93c5fd;} .note:empty {  display: none;}
🔎 Как это происходит на практике:
  • Форма выглядит как единый блок, который подсвечивается при фокусе в любом поле.
  • В FAQ якорная ссылка ведет к вопросу и подсвечивает его.
  • Пустой блок подсказки автоматически скрывается.
Характеристики:
  • ✅ лучше навигация и ориентирование;
  • ✅ меньше JS для простых реакций;
  • ✅ чище поведение компонентов.
Когда использовать: В формах, длинных документах, FAQ, карточках с опциональным контентом.
Вывод: Контекстные псевдоклассы делают интерфейс более предсказуемым и умным.

7. Декоративные псевдоэлементы: ::before и ::after

Назначение: Добавлять визуальные детали без изменения HTML-разметки.
Простыми словами: Это «добавочные слои» вокруг контента: иконка, бейдж, линия, фон-акцент.
Для новичка: Помните правило: без content псевдоэлемент не появится.
Аналогия: Наклейка на папке: меняет вид, но не меняет документы внутри.
Пример:
.badge::before {  content: "NEW";  margin-right: 8px;  color: #2563eb;  font-weight: 700;} .quote::after {  content: "";  display: block;  margin-top: 8px;  height: 2px;  background: #e5e7eb;}
🔎 Как это происходит на практике:
  • В каталоге нужно пометить новые курсы без правок шаблона HTML.
  • Через ::before добавляют бейдж.
  • Через ::after делают декоративную линию под цитатой.
Характеристики:
  • ✅ минимум изменений в разметке;
  • ✅ удобно для UI-декора;
  • ✅ легко включать и отключать темами.
Когда использовать: Для декоративных элементов, которые не несут критический смысл.
Вывод: ::before и ::after ускоряют визуальные правки и сохраняют HTML чистым.

8. Псевдоэлементы текста и списков: ::placeholder, ::selection, ::marker

Назначение: Точно стилизовать части текста, выделения и маркеры списка.
Простыми словами: Можно сделать подсказку мягче, выделение текста фирменным, маркеры списка заметнее.
Для новичка: Эти селекторы улучшают восприятие деталей, которые пользователь видит постоянно.
Аналогия: Это как тонкая настройка шрифта, подсветки и пунктов в печатной инструкции.
Пример:
input::placeholder {  color: #9ca3af;} ::selection {  background: #fde68a;  color: #111827;} li::marker {  color: #2563eb;}
🔎 Как это происходит на практике:
  • В поле поиска placeholder делают менее контрастным, чтобы не путать с введенным текстом.
  • В статье на платформе брендируют цвет выделения текста.
  • В списке преимуществ через ::marker усиливают визуальную иерархию.
Характеристики:
  • ✅ аккуратная типографика и UI-детали;
  • ✅ улучшение читаемости;
  • ✅ единый визуальный стиль.
Когда использовать: В формах, контентных страницах, документации и списках преимуществ.
Вывод: Мелкие псевдоэлементы часто заметно повышают качество интерфейса.

Must-know факты (часто спрашивают и часто путают)

  • :focus-visible не то же самое, что :focus: он лучше для доступного UX.
  • :hover не должен быть единственной обратной связью.
  • ::before и ::after требуют content, иначе не рендерятся.
  • Псевдоэлементы не подходят для критически важного текста.
  • :nth-child() считает всех детей, :nth-of-type() - только выбранный тип.
  • :visited ограничен браузером по соображениям безопасности.
  • :has() полезен, когда нужно стилить родителя по состоянию дочернего элемента.
  • Контур фокуса нельзя убирать без равноценной замены.
Вывод: Если помнить эти правила, большинство типичных ошибок с псевдоклассами не возникнет.

Сравнение подходов

Что сравниваемКогда подходитПлюсыРиск при неверном применении
Псевдокласс (:hover, :focus)Нужна реакция на состояниеПонятный интерактивПотеря доступности без focus-visible
Псевдоэлемент (::before, ::after)Нужен декор без HTMLЧистая разметкаПопытка положить в декор важный смысл
Структурные (:nth-child)Стиль зависит от позицииМеньше лишних классовХрупкость при изменении DOM
Логические (:is, :not, :has)Сложные условия селектораМеньше дублированияПереусложнение без читаемости

Часто спрашивают на собеседованиях

  1. В чем точная разница между псевдоклассом и псевдоэлементом?
  2. Почему :focus-visible предпочтительнее :focus для UI?
  3. Когда использовать :nth-child, а когда :nth-of-type?
  4. Какие ограничения есть у :visited и почему?
  5. В каких кейсах :has() реально полезен в production?
  6. Почему важный текст нельзя переносить в ::before и ::after?
  7. Что чаще всего ломают при работе с hover на мобильных?
Вывод: На собеседовании проверяют не знание списка селекторов, а понимание UX-последствий и ограничений.

Типичные ошибки

Ошибка 1: Есть hover, но нет видимого фокуса

Неправильно: Добавлять состояние только для мыши.
Правильно: Писать :focus-visible рядом с :hover.
Почему: Клавиатурная навигация без видимого фокуса становится почти непригодной.

Ошибка 2: Забыли content у ::before и ::after

Неправильно: Стилизовать псевдоэлемент без content.
Правильно: Всегда задавать content (хотя бы пустую строку).
Почему: Без content псевдоэлемент не появляется.

Ошибка 3: Важный текст вынесен в псевдоэлемент

Неправильно: Ключевой смысл страницы добавлять через ::before.
Правильно: Смысловой контент хранить в HTML, а псевдоэлемент использовать только для декора.
Почему: Декоративный слой не должен заменять реальный контент.

Ошибка 4: Путают :nth-child() и :nth-of-type()

Неправильно: Использовать :nth-child() там, где в контейнере смешанные теги.
Правильно: Выбирать селектор по реальной структуре DOM.
Почему: nth-child считает всех детей, и стили могут попадать не туда.

Ошибка 5: Удаляют outline без замены

Неправильно: outline: none; без альтернативной подсветки.
Правильно: Давать кастомный контур через :focus-visible.
Почему: Иначе пользователь теряет ориентир по клавиатуре.

Ошибка 6: Слишком сложные селекторы с :is/:has

Неправильно: Писать «умные» селекторы, которые никто не может поддерживать.
Правильно: Держать правила читаемыми и использовать логические псевдоклассы точечно.
Почему: CSS должен быть поддерживаемым для всей команды.

Best Practices

  • Держите набор интерактивных состояний как стандарт дизайн-системы.
  • Всегда проверяйте сценарии мыши, клавиатуры и touch.
  • Используйте псевдоэлементы для декора, не для смысла.
  • Для форм заранее проектируйте :invalid, :disabled, :checked.
  • Перед релизом прогоняйте визуальный чек фокуса и доступности.
  • Если селектор сложно читать, упростите его или используйте класс.

Заключение

Псевдоклассы и псевдоэлементы - это основа «живого» CSS, который объясняет пользователю, что происходит в интерфейсе.
Когда состояния и декор оформлены правильно, UI становится понятным, доступным и легче поддерживается командой.

Ключевые мысли

  • Псевдокласс отвечает за состояние, псевдоэлемент - за визуальную часть.
  • focus-visible и доступность нельзя считать опциональными.
  • Чем чище логика селекторов, тем легче поддержка проекта.
🎯

Проверьте знания

Закрепите материал — пройдите тест по теме «CSS: псевдоклассы и псевдоэлементы»

Пройти тест →