12 Модуль 3 Знакомство с CSS 16 мин урок 12 из 25

Селекторы: как выбрать нужный элемент

По тегу, классу и id, комбинации, потомки и соседи, атрибуты, псевдоклассы и псевдоэлементы.

Что ты научишься делать

  • Попадёшь стилем ровно в тот элемент, который нужен
  • Разберёшься, чем потомок отличается от прямого ребёнка
  • Добавишь состояния при наведении и фокусе без единой строчки JavaScript

#Три базовых селектора

CSSОснова основ
/* по тегу — все абзацы страницы */p { color: #333; }/* по классу — все элементы с class="card" */.card { background: #f4f4f8; }/* по id — единственный элемент с id="hero" */#hero { min-height: 300px; }/* вообще все элементы */* { box-sizing: border-box; }

Девяносто процентов настоящего CSS — это селекторы по классу. Тег берут для базовых вещей (сброс отступов, типографика), id в стилях лучше не использовать вовсе: почему — в следующем уроке.

#Комбинации

ЗаписьКого выбирает
h1, h2, h3Группа: все три сразу. Запятая значит «или»
.card pПотомок: любой абзац внутри карточки, на любой глубине
.card > pПрямой ребёнок: только абзацы, лежащие непосредственно в карточке
h2 + pСледующий сосед: абзац сразу после заголовка
h2 ~ pВсе следующие соседи: все абзацы после заголовка в том же родителе
a.btnОдновременно: ссылка, у которой есть класс btn. Без пробела!

Лаборатория селекторов

Пишешь селектор — подсвечиваются подходящие элементы и виден счётчик попаданий.

СелекторКого выбирает
pВсе абзацы
.cardВсё с классом card
#heroЭлемент с id hero
ul > liТолько прямых детей списка
a:hoverСсылку под курсором

#Выбор по атрибуту

CSSАтрибуты
/* у элемента есть атрибут */[required] { border-color: #c8394a; }/* точное значение */input[type="email"] { background: #f0f6ff; }/* значение начинается с… */a[href^="https://"] { color: #0f8f6a; }/* заканчивается на… */a[href$=".pdf"]::after { content: " (PDF)"; }/* содержит подстроку */a[href*="youtube"] { color: #c8394a; }

#Псевдоклассы: состояние и положение

Псевдокласс пишется через одно двоеточие и выбирает элемент в определённом состоянии или на определённом месте.

ПсевдоклассКогда срабатывает
:hoverКурсор над элементом
:focusЭлемент получил фокус — например, после Tab
:focus-visibleФокус пришёл с клавиатуры. Именно его берут для обводки
:activeКнопку прямо сейчас нажимают
:first-childЭлемент — первый ребёнок своего родителя
:last-childПоследний ребёнок
:nth-child(2)Второй ребёнок
:nth-child(odd)Все нечётные — удобно для полосатых таблиц
:not(.active)Все, кроме тех, что подходят под скобки
:checkedВключённый флажок или переключатель
:disabledОтключённое поле
Состояния вживую — наведи и нажми Tab
В песочницу

#nth-child: формула

В скобках у :nth-child() может стоять число, слово odd или even, а может — формула an + b.

  • :nth-child(3n) — каждый третий: 3, 6, 9…
  • :nth-child(3n + 1) — первый в каждой тройке: 1, 4, 7…
  • :nth-child(-n + 3) — первые три.

#Группировка и :is()

Одно правило можно повесить сразу на несколько селекторов, перечислив их через запятую. Запятая означает «или»: каждая часть работает сама по себе, и достаточно совпасть любой.

Когда общая у них только концовка, список быстро разрастается: .card h2, .card h3, .card h4. Псевдокласс :is() сворачивает такое перечисление в скобки — .card :is(h2, h3, h4). Читается короче, а ведёт себя так же.

CSSОдно и то же двумя способами
/* Через запятую: каждый селектор пишется целиком */.card h2,.card h3,.card h4 {  margin-block: 0 8px;}/* То же самое короче */.card :is(h2, h3, h4) {  margin-block: 0 8px;}

#:has() — селектор родителя

Долгие годы в CSS нельзя было выбрать элемент по его содержимому. Теперь можно: :has() выбирает элемент, внутри которого есть что-то определённое.

CSSКарточка, в которой есть картинка
.card:has(img) {  padding-top: 0;}/* Поле, у которого рядом отмечен флажок */label:has(input:checked) {  font-weight: 700;}

#Псевдоэлементы: то, чего нет в разметке

Псевдоэлемент пишется через два двоеточия и создаёт кусочек содержимого, которого в HTML нет. Самые ходовые — ::before и ::after.

Им обязательно нужно свойство content, даже пустое: без него элемент не появится.

Значки без единой картинки
В песочницу

Где спотыкаются почти все

Лишний пробел в селекторе

Почему a .btn вместо a.btn ищет потомка вместо самого элемента. Правило молча не срабатывает.

Как надо Нет пробела — «этот же элемент». Есть пробел — «внутри него».

Длинные цепочки вроде <code>body div.wrap ul li a span</code>

Почему Такое правило намертво привязано к структуре разметки: поменяешь один тег — всё развалится. И вес у него огромный, перекрыть почти невозможно.

Как надо Дай элементу класс и цепляйся за него: .menu__link.

Забыт content у псевдоэлемента

Почему Без content псевдоэлемент не создаётся вообще. Правило есть, эффекта нет.

Как надо Пиши content: ""; даже когда текст не нужен.

Стили только на :hover

Почему На телефоне наведения нет, а с клавиатуры приходит :focus. Кнопка, которая реагирует только на мышь, для половины людей неотличима от неактивной.

Как надо Пиши состояния группой: .btn:hover, .btn:focus-visible { … }.

Селектор selector
Выражение, описывающее, к каким элементам применить правило.
Потомок descendant
Любой элемент внутри другого, на любой глубине. Записывается пробелом.
Прямой ребёнок child
Элемент на один уровень внутри. Записывается знаком >.
Псевдокласс pseudo-class
Состояние или положение элемента: :hover, :first-child.
Псевдоэлемент pseudo-element
Виртуальный кусочек содержимого: ::before, ::after.

Проверь себя

  1. Чем <code>.card p</code> отличается от <code>.card > p</code>?

    Пробел — «где-то внутри», знак <code>&gt;</code> — «непосредственно внутри, на один уровень».

  2. Что выберет селектор <code>a.btn</code>?

    Без пробела части относятся к одному элементу. Пробел означал бы «внутри», запятая — «или».

  3. Что нужно псевдоэлементу ::before, чтобы он появился?

    Без <code>content</code> псевдоэлемент не создаётся. Пустая строка тоже подходит: <code>content: "";</code>

  4. Какой селектор покрасит каждую вторую строку таблицы?

    <code>:nth-child(2)</code> — ровно вторая строка. <code>even</code> — все чётные.

  5. Какие селекторы стоит писать вместе, чтобы кнопка работала и с мышью, и с клавиатуры?

    Верных вариантов несколько.

    <code>:hover</code> — для мыши, <code>:focus-visible</code> — для клавиатуры. <code>:visited</code> относится к посещённым ссылкам и к состоянию нажатия не имеет отношения.

Задание

Попасть шестью селекторами

В разметке шесть целей. Напиши шесть правил, не трогая HTML:

  • всем пунктам списка — внутренний отступ не меньше 8px;
  • только первому пункту — жирный шрифт;
  • только последнему — убрать нижнюю границу (border-bottom: none);
  • чётным пунктам — серый фон;
  • ссылке с классом btn при наведении — другой цвет фона;
  • полю ввода в фокусе — видимая обводка через :focus-visible.
Открыть в песочнице
    Подсказка 1

    Первый и последний выбираются так: .menu li:first-child и .menu li:last-child.

    Подсказка 2

    Чётные пункты: .menu li:nth-child(even) { background: #f4f4f8; }

    Подсказка 3

    Состояние наведения: .btn:hover { background: #5334cf; }. Обводка: input:focus-visible { outline: 3px solid #6544e0; }

    Показать решение
    HTMLindex.html
    <ul class="menu">  <li>Эспрессо</li>  <li>Капучино</li>  <li>Раф</li>  <li>Флэт уайт</li></ul><p><a class="btn" href="#">Заказать</a></p><p><input type="text" aria-label="Комментарий к заказу"></p>
    CSSstyle.css
    .menu {  max-width: 280px;  padding: 0;  list-style: none;}.menu li {  padding: 10px 12px;  border-bottom: 1px solid #ddd;}.menu li:first-child {  font-weight: 700;}.menu li:last-child {  border-bottom: none;}.menu li:nth-child(even) {  background: #f4f4f8;}.btn {  display: inline-block;  padding: 10px 20px;  color: #fff;  background: #6544e0;  border-radius: 999px;  text-decoration: none;}.btn:hover {  background: #5334cf;}input:focus-visible {  outline: 3px solid #6544e0;  outline-offset: 2px;}

    Проверь себя