Урок 41. Ошибки: Псевдоклассы и псевдоэлементы

📁 Раздел: Современный CSS ⏱️ Время изучения: ~80 мин 🎯 Сложность: Средняя
#hover #focus #active #nth-child #first-child #checked #not #is #where #before #after #first-line #placeholder #selection

⚡ Кратко

Топ-3: ::before без content (ничего не видно), только :hover без :focus (слепая клавиатура), путаница : и ::. Ниже — как ломается и как правильно.

Частые ошибки

1. ::before / ::after без content

Самая частая ловушка: написал псевдоэлемент, задал размеры и фон — а на экране пусто. Без свойства content псевдоэлемент не создаётся вообще.

пусто
без content
есть маркер
с content: ''
/* ❌ ничего не появится */
.dot::before {
  background: #16a34a;
  width: 9px; height: 9px;
}

/* ✅ обязательно content, пусть и пустой */
.dot::before {
  content: '';
  display: inline-block;
  background: #16a34a;
  width: 9px; height: 9px;
  border-radius: 50%;
}

2. Только :hover, забыт :focus

Кнопка красиво реагирует на мышь, но пользователь с клавиатуры (Tab) не видит, где он находится — интерфейс становится недоступным.

/* ❌ только мышь */
.button:hover { background: #1d4ed8; }

/* ✅ + видимое состояние для клавиатуры */
.button:hover,
.button:focus-visible { background: #1d4ed8; }
.button:focus-visible { outline: 3px solid #2563eb; outline-offset: 3px; }

3. Путаница : и ::

Одно двоеточие — псевдокласс (состояние), два — псевдоэлемент. :before с одним двоеточием — это устаревший синтаксис CSS2 (браузеры его терпят для совместимости), но для псевдоэлементов правильно ::before. А вот у псевдоклассов всегда одно двоеточие — ::hover просто не сработает.

/* ❌ */ p::hover { }    /* псевдокласс с двумя двоеточиями — не работает */
/* ✅ */ p:hover  { }

/* ✅ современный синтаксис псевдоэлемента */ p::before { content: ''; }

4. Смысловой текст в content

Текст из ::before/::after нельзя выделить, скопировать, и его часто пропускают скринридеры. Туда — только декор; смысл держите в HTML.

5. Сломанная зебра из-за :not() и порядка

:nth-child считает все элементы-соседи, а не только подходящие под другой селектор. Если в списке затесался не-li, нумерация «съедет». Помните: :nth-child(2) — это «второй ребёнок, если он li», а не «второй li».

⚠️ Проверить по документации: разницу между :nth-child() и :nth-of-type() — на MDN :nth-child().

Навигация