Частые ошибки
1. ::before / ::after без 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».