</> Praktum

Главная / CSS / CSS-селекторы

Урок 1 · CSS

CSS-селекторы: как выбрать элемент

Редакция PraktumОбновлено 15 минут на урок с практикойУровень: новичок

Селектор — левая часть 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, классы, теги)
p0, 0, 1
.notice0, 1, 0
p.notice0, 1, 1
.card .notice0, 2, 0
#save-note1, 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 }.

Источники