Урок 1 · CSS
CSS-селекторы: как выбрать элемент
Селектор — левая часть CSS-правила, которая указывает, к каким элементам применить стили: p выбирает все абзацы, .card — элементы с классом card, #menu — элемент с id menu. Селекторы комбинируют, чтобы выбрать элемент внутри другого или рядом с ним.
- Тег —
p, класс —.card, id —#menu, атрибут —[type="email"]. - Пробел — потомок на любом уровне,
>— прямой ребёнок,+— соседний элемент. - Запятая группирует:
h1, h2 { … }. - Класс сильнее тега, id сильнее класса; при равенстве побеждает правило ниже.
- Для оформления компонентов используй классы, id и !important — редко.
Зачем этот урок сейчас
Каждое CSS-правило начинается с селектора. Если селектор выбрал не то, ни одно свойство не поможет: стиль не применится или покрасит лишнее. Разобравшись с селекторами и их силой, ты перестанешь гадать, почему правило «не работает».
Как устроено правило CSS
h1 {
color: #2a62d9;
font-size: 40px;
}Слева — селектор h1, он выбирает все заголовки первого уровня. В фигурных скобках — объявления «свойство: значение», каждое заканчивается точкой с запятой. Пропущенная точка с запятой ломает следующее объявление — частая причина «половина стилей не применилась».
Основные селекторы
<p class="notice is-warning" id="save-note" data-state="draft">Сохрани изменения.</p>p { line-height: 1.6; } /* все абзацы */
.notice { padding: 12px; } /* класс */
.notice.is-warning { background: #fff4e5; } /* оба класса сразу */
#save-note { scroll-margin-top: 80px; } /* id */
[data-state="draft"] { opacity: .8; } /* атрибут */
* { box-sizing: border-box; } /* все элементы */| Селектор | Выбирает |
|---|---|
p | все элементы с тегом p |
.notice | элементы с классом notice |
#save-note | элемент с id save-note |
[href] | элементы, у которых есть атрибут href |
[href^="https"] | значение атрибута начинается с https |
[href$=".pdf"] | значение заканчивается на .pdf |
* | все элементы |
Комбинаторы: потомок, ребёнок, сосед
.card h2 { margin-top: 0; } /* h2 на любом уровне внутри .card */
.menu > li { display: inline-block; } /* только прямые дети */
.card + .card { margin-top: 16px; } /* карточка сразу после карточки */
h2 ~ p { color: #555; } /* все p после h2 у того же родителя */Пробел между селекторами означает «внутри на любой глубине», > — «прямой ребёнок». + выбирает элемент, стоящий сразу после другого у того же родителя, ~ — все следующие соседи. Не путай .card .title (title внутри card) и .card.title (один элемент с двумя классами).
Группировка
h1, h2, h3 {
font-family: Inter, system-ui, sans-serif;
line-height: 1.2;
}Запятая применяет одни объявления к нескольким селекторам. Если в списке хотя бы один селектор с ошибкой, всё правило игнорируется. Для длинных списков удобнее :is(h1, h2, h3) — он прощает неизвестные селекторы.
Специфичность: какое правило победит
Когда два правила задают одно свойство одному элементу, побеждает более специфичный селектор. Специфичность считают тремя числами: id, классы (а также атрибуты и псевдоклассы), теги.
| Селектор | Вес (id, классы, теги) |
|---|---|
p | 0, 0, 1 |
.notice | 0, 1, 0 |
p.notice | 0, 1, 1 |
.card .notice | 0, 2, 0 |
#save-note | 1, 0, 0 |
style="…" в HTML | сильнее любого селектора |
Сравнение идёт слева направо: один id сильнее любого числа классов. При равном весе побеждает правило, написанное ниже в файле. !important перебивает всё, но его потом можно перебить только другим !important — начинается война правил.
Классы: как называть
/* по роли — хорошо */
.article-card { … }
.main-menu { … }
.is-active { … }
/* по виду — плохо: цвет поменяется, имя останется */
.blue-text { … }
.margin-20 { … }Называй классы по роли элемента, а не по виду. Состояние выноси в отдельный класс-модификатор вроде is-active или card--featured. Один класс на компоненте с низкой специфичностью легко переопределить; цепочка .page .content .card .title ломается от любой перестановки тегов.
id в CSS
id в стилях работает, но для оформления почти не нужен: он должен быть уникальным на странице, а его вес настолько велик, что перебить такое правило можно только другим id. Оставь id для якорных ссылок, связи label for и JavaScript, а оформление делай классами.
Как проверить селектор
Выдели элемент в DevTools: во вкладке Styles видны все правила, которые к нему применяются, сверху — самые сильные. Перечёркнутые объявления проиграли каскаду. Проверить, что выбирает селектор, можно в консоли: document.querySelectorAll('.card + .card') вернёт список подходящих элементов.
Класс или тег
Оформление конкретного компонента: карточка, кнопка, сообщение. Точно и легко переопределить.
Базовые правила для всех элементов: шрифт абзацев, цвет ссылок, отступы заголовков.
Частые ошибки
- Пишут
noticeбез точки — CSS ищет тег notice, а не класс. - Ставят пробел в
.card .title, когда нужен один элемент с двумя классами. - Усиливают селектор длинной цепочкой тегов вместо одного класса.
- Используют
!important, чтобы «быстрее сработало». - Оформляют через id, а потом не могут перебить стиль.
Доступность
Селекторы по атрибутам доступности помогают держать оформление и семантику вместе: [aria-expanded="true"], [aria-current="page"], [hidden]. Так видимое состояние кнопки меню всегда совпадает с тем, что слышит скринридер, — не нужно отдельного класса, который можно забыть переключить.
Поддержка браузерами
Селекторы по тегу, классу, id, атрибуту и все комбинаторы работают во всех браузерах. Современные :is(), :where() и :has() поддерживаются актуальными версиями браузеров.
Практика
Добавь абзац с классом tip и оформи его: отступ, светлый фон, цветная левая граница. Сделай вариант tip is-warning с другим фоном. Добавь отступ сверху только между соседними абзацами-подсказками, а ссылкам на PDF — значок через атрибутный селектор.
Показать решение
.tip {
padding: 16px;
background: #eff5ff;
border-left: 4px solid #2a62d9;
}
.tip.is-warning {
background: #fff4e5;
border-left-color: #d97706;
}
.tip + .tip { margin-top: 12px; }
a[href$=".pdf"]::after { content: " (PDF)"; }Частые вопросы
Чем .card .title отличается от .card.title?
С пробелом — элемент с классом title внутри элемента с классом card. Без пробела — один элемент, у которого есть оба класса.
Что такое специфичность?
Вес селектора, по которому браузер решает, какое правило победит. id весит больше классов, классы — больше тегов. При равенстве побеждает правило ниже.
Почему моё правило не применяется?
Его перебивает более специфичный селектор или правило ниже в файле. Посмотри в DevTools во вкладке Styles — проигравшее объявление будет зачёркнуто.
Можно ли использовать id в CSS?
Можно, но не стоит для оформления: он слишком сильный, и перебить такое правило сложно. Для стилей — классы.
Когда использовать !important?
Почти никогда. Исключения — служебные классы вроде .visually-hidden и правило [hidden] { display: none !important }.