Селекторы. Часть 4: структурные псевдоклассы

Чтение — около 7 минут· без учёта практики

В предыдущем уроке мы выбирали элементы по атрибутам и содержимому. Сегодня — по положению среди соседей: первый пункт меню, чётная строка таблицы, первый абзац после заголовка. Такие псевдоклассы называют структурными: они смотрят на структуру документа, а не на классы. Этот урок закрывает цикл уроков о селекторах; к ним мы будем возвращаться в отдельных примерах на протяжении всего учебника.

Дочерние элементы и селектор >

Элемент, вложенный непосредственно в другой элемент, — его дочерний элемент. На схеме ниже элементы <h2> и <p> — дочерние по отношению к <body>, а элемент <i> дочерним для <body> не является: он лежит внутри <p> и дочерний именно для абзаца. Дерево документа мы разбирали в уроке «Селекторы. Часть 2».

Дочерние элементы в HTML-документе: h2 и p — дети body, i — ребёнок p.
Дочерние элементы в HTML-документе.

Пусть нужно выбрать ссылку, выделенную на схеме оранжевым. Селектор потомков body a выберет все ссылки: все они вложены в <body>. Селектор p a выберет две ссылки внутри абзацев: обе — потомки <p>, хотя одна лежит ещё и в <span>.

Задача выбора: нужна ссылка, которая лежит прямо в абзаце, а не внутри span.
Задача выбора элемента на странице.

Здесь подходит дочерний селектор p > a: он выбирает только ссылки, которые лежат в абзаце непосредственно, без промежуточных элементов.

Дочерний селектор: попробуйте сами

p > a окрасил только первую ссылку — она непосредственный ребёнок абзаца. p a убрал подчёркивание у двух ссылок в абзацах, включая ссылку внутри span. Ссылка прямо в body не изменилась.

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Селектор дочерних элементов</title>
    <style>
      body { font-family: system-ui, sans-serif; background-color: linen; color: #2b211b; }
      p > a {
        /* ссылки — непосредственные дети абзаца */
        color: darkorange;
      }
      p a {
        /* все ссылки внутри абзаца на любой глубине */
        text-decoration: none;
      }
    </style>
  </head>
  <body>
    <p><a href="#">Ссылка</a> внутри &lt;p&gt;.</p>
    <a href="#">Ссылка</a> внутри &lt;body&gt;.
    <p><span><a href="#">Ссылка</a></span> внутри &lt;span&gt;, вложенного в &lt;p&gt;.</p>
  </body>
</html>

Первый и последний дочерний элемент

Псевдокласс :first-child выбирает элемент, если он первый среди дочерних элементов своего родителя, а :last-child — если последний. Важно понимать, как читается запись: p:first-child — это не «первый абзац», а «абзац, который стоит первым среди детей своего родителя». Если перед абзацем стоит заголовок, селектор не выберет ничего. Текст и комментарии между элементами при подсчёте не учитываются.

p:first-child выбирает абзац, если он первый ребёнок. Если перед ним стоит h2, абзац не выбирается.
Первый абзац не обязательно является первым дочерним элементом.

Что общего у элементов, выделенных на следующей схеме? Выделенные <h2> и <li> — первые дочерние элементы своих родителей, поэтому их выбирает :first-child.

Выделены первые дочерние элементы: первый h2 в body и в article, первые li в списках.
Элементы, которые выбирает :first-child.

С :last-child выделенными оказываются <article> и последние <li>. А ни один <h2> выбрать через h2:last-child нельзя: ни один заголовок не стоит последним у своего родителя — за каждым идёт список или статья. Это важно понять: подобные случаи нередко ставят в тупик.

Выделены последние дочерние элементы: article в body и последние li в списках.
Элементы, которые выбирает :last-child.
Схема: после каждого h2 есть другой элемент, поэтому h2:last-child ничего не выбирает.
Почему h2:last-child ничего не выбирает.

:first-child и :last-child: попробуйте сами

Синие — h2, которые стоят первыми у родителя: «Мои игрушки» в body и «Команды на немецком» в article. Первые пункты списков красные и крупнее, последние — зелёные, article — на оранжевом фоне. Добавьте h2:last-child { color: red; } — ни один заголовок не изменится.

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Псевдоклассы :first-child и :last-child</title>
    <style>
      body { font-family: system-ui, sans-serif; background-color: linen; color: #2b211b; }
      h2:first-child {
        /* h2, который стоит первым среди детей своего родителя */
        color: royalblue;
      }
      li:first-child {
        color: firebrick;
        font-size: 1.5rem;
      }
      article:last-child {
        /* article — последний ребёнок body */
        background-color: orange;
      }
      li:last-child {
        color: seagreen;
      }
    </style>
  </head>
  <body>
    <h2>Мои игрушки</h2>
    <ul>
      <li>Мячик</li>
      <li>Канат</li>
      <li>Косточка</li>
    </ul>
    <h2>Мои команды</h2>
    <article>
      <h2>Команды на немецком</h2>
      <ul>
        <li>Sitz</li>
        <li>Platz</li>
        <li>Fuß</li>
      </ul>
    </article>
  </body>
</html>

Есть и псевдокласс :only-child: он выбирает элемент, если тот — единственный ребёнок своего родителя, то есть одновременно первый и последний.

Псевдокласс :nth-child()

Остался неуловимый второй заголовок <h2> из примера выше. Его можно посчитать: он третий ребёнок <body> — после первого заголовка и списка. Псевдокласс :nth-child() выбирает дочерние элементы по порядковому номеру. Нумерация начинается с 1.

Выделены вторые пункты списков и третий ребёнок body — второй заголовок h2.
Элементы с номерами 2 и 3 среди детей своих родителей.

:nth-child(): попробуйте сами

На оранжевом фоне — заголовок «Мои команды» (третий ребёнок body) и вторые пункты обоих списков. Замените 2 на 3 у li — выделятся «Косточка» и «Fuß».

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Псевдокласс :nth-child() по номеру</title>
    <style>
      body { font-family: system-ui, sans-serif; background-color: linen; color: #2b211b; }
      /* h2 — третий ребёнок своего родителя, li — второй */
      h2:nth-child(3),
      li:nth-child(2) {
        background-color: orange;
      }
    </style>
  </head>
  <body>
    <h2>Мои игрушки</h2>
    <ul>
      <li>Мячик</li>
      <li>Канат</li>
      <li>Косточка</li>
    </ul>
    <h2>Мои команды</h2>
    <article>
      <h2>Команды на немецком</h2>
      <ul>
        <li>Sitz</li>
        <li>Platz</li>
        <li>Fuß</li>
      </ul>
    </article>
  </body>
</html>

Чётные и нечётные: even и odd

Вместо номера можно указать ключевое слово: even — чётные элементы, odd — нечётные. Так чередуют фон строк таблиц и списков, чтобы длинные строки было легче читать.

even и odd: попробуйте сами

В первой таблице выделены чётные строки tr — 2 и 4, во второй — нечётные: 1, 3 и 5. Строка заголовков тоже считается: она первая.

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Чётные и нечётные строки: even и odd</title>
    <style>
      body { font-family: system-ui, sans-serif; background-color: linen; color: #2b211b; }
      table { border-collapse: collapse; margin-bottom: 1rem; }
      th, td { border: 1px solid tan; padding: 0.25rem 0.5rem; }
      caption { color: firebrick; }
      .primer1 tr:nth-child(even) {
        /* чётные строки */
        background-color: #e6d5c3;
      }
      .primer2 tr:nth-child(odd) {
        /* нечётные строки */
        background-color: #e6d5c3;
      }
    </style>
  </head>
  <body>
    <table class="primer1">
      <caption>Значение even (чётные)</caption>
      <tr><th>1 строка</th><th>Время</th><th>Дело</th></tr>
      <tr><td>2 строка</td><td>7:00</td><td>Подъём</td></tr>
      <tr><td>3 строка</td><td>7:30</td><td>Прогулка</td></tr>
      <tr><td>4 строка</td><td>8:00</td><td>Завтрак</td></tr>
      <tr><td>5 строка</td><td>9:00</td><td>Сон</td></tr>
    </table>
    <table class="primer2">
      <caption>Значение odd (нечётные)</caption>
      <tr><th>1 строка</th><th>Время</th><th>Дело</th></tr>
      <tr><td>2 строка</td><td>7:00</td><td>Подъём</td></tr>
      <tr><td>3 строка</td><td>7:30</td><td>Прогулка</td></tr>
      <tr><td>4 строка</td><td>8:00</td><td>Завтрак</td></tr>
      <tr><td>5 строка</td><td>9:00</td><td>Сон</td></tr>
    </table>
  </body>
</html>

Формула An+B

Самое гибкое значение :nth-child() — формула An+B. Браузер подставляет вместо n числа 0, 1, 2, 3… и выбирает элементы с получившимися номерами. A — шаг, B — сдвиг:

CSS
td:nth-child(4n+2) { … } /* 4·0+2 = 2, 4·1+2 = 6, 10, 14… */
  • 4n — каждый четвёртый элемент;
  • +2 — начиная со второго.

An+B: попробуйте сами

Выделены ячейки td со 2-й, 6-й, 10-й и 14-й позиции в каждой строке. Замените формулу на 4n-1, затем на -n+3 и сравните, какие ячейки выделятся.

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Формула An+B</title>
    <style>
      body { font-family: system-ui, sans-serif; background-color: linen; color: #2b211b; }
      table { border-collapse: collapse; }
      td, th {
        border: 1px solid seagreen;
        width: 1.25rem;
        height: 1.5rem;
        padding: 0;
        text-align: center;
      }
      td:nth-child(4n + 2) {
        /* 2, 6, 10, 14: каждая четвёртая ячейка, начиная со второй */
        background-color: lightblue;
      }
    </style>
  </head>
  <body>
    <table>
      <tr><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th><th>8</th><th>9</th><th>10</th><th>11</th><th>12</th><th>13</th><th>14</th></tr>
      <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
      <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
      <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    </table>
  </body>
</html>

В формуле допустимы и знаки вычитания:

  • 4n-1 даёт номера −1, 3, 7, 11…: элемента с номером −1 нет, поэтому выбираются 3-й, 7-й, 11-й — каждый четвёртый, начиная с третьего. Это то же самое, что 4n+3.
  • -n+3 даёт 3, 2, 1, 0, −1…: выбираются первые три элемента. Отрицательный шаг удобен, когда нужно «не больше N первых».
  • n+4 выбирает все элементы, начиная с четвёртого, а 2n и 2n+1 — то же, что even и odd.

Псевдокласс :nth-last-child() работает так же, но считает с конца: li:nth-last-child(2) — предпоследний пункт. А в современных браузерах в скобках можно уточнить, кого считать: li:nth-child(2 of li.done) выбирает второй пункт среди пунктов с классом done. Если написать только of .done, в подсчёт попадут все соседи с этим классом, даже элементы другого типа.

Формулу удобно разобрать с подсветкой в тренажёре позиционных селекторов: вводите An+B и сразу видите, какие строки выбраны.

Псевдоклассы по типу: *-of-type

У каждого псевдокласса *-child есть пара *-of-type. Она считает не всех детей родителя, а только элементы того же типа:

  • :first-of-type — первый элемент своего типа среди детей родителя;
  • :last-of-type — последний элемент своего типа;
  • :nth-of-type() — элемент своего типа по номеру, ключевому слову even/odd или формуле An+B, как у :nth-child(). Например, p:nth-of-type(4n+2) — каждый четвёртый абзац, начиная со второго.

Пусть содержимое страницы разбито на блоки <div class="test">, и в каждом сначала идёт заголовок, затем абзацы, а в конце — <span>. Нужно выделить первый, второй и последний абзацы каждого блока:

*-of-type: попробуйте сами

Первый абзац каждого блока — оранжевый и жирный, второй — на жёлтом фоне, последний — на голубом. Замените p:first-of-type на p:first-child — выделение пропадёт: первым ребёнком стоит h2.

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Псевдоклассы :first-of-type, :nth-of-type() и :last-of-type</title>
    <style>
      body { font-family: system-ui, sans-serif; background-color: linen; color: #2b211b; }
      .test p:first-of-type {
        /* первый абзац, хотя первым ребёнком стоит h2 */
        background-color: orange;
        font-weight: bold;
      }
      .test p:nth-of-type(2) {
        /* второй абзац */
        background-color: khaki;
      }
      .test p:last-of-type {
        /* последний абзац, хотя последним ребёнком стоит span */
        background-color: lightblue;
      }
    </style>
  </head>
  <body>
    <div class="test">
      <h2>Утро</h2>
      <p>Бужу хозяина</p>
      <p>Гуляю у пруда</p>
      <p>Завтракаю</p>
      <span>Конец утра</span>
    </div>
    <div class="test">
      <h2>Вечер</h2>
      <p>Большая прогулка</p>
      <p>Ужин</p>
      <p>Сплю у хозяина в ногах</p>
      <span>Конец дня</span>
    </div>
  </body>
</html>

Отличие :nth-child() от :nth-of-type()

Разберём важный пример. В статье два абзаца, и нужно выделить второй. Подходят оба селектора: p:nth-child(2) и p:nth-of-type(2). Но в чём разница? Добавим в начало статьи заголовок <h2>:

:nth-child() и :nth-of-type(): попробуйте сами

Жёлтый фон (p:nth-of-type(2)) — у второго абзаца, красный пунктир (p:nth-child(2)) — у первого. Удалите заголовок h2 — оба оформления окажутся на втором абзаце.

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Отличие :nth-child() от :nth-of-type()</title>
    <style>
      body { font-family: system-ui, sans-serif; background-color: linen; color: #2b211b; }
      p:nth-of-type(2) {
        /* второй абзац среди абзацев */
        background-color: khaki;
      }
      p:nth-child(2) {
        /* абзац, который стоит вторым среди всех детей */
        outline: 2px dashed firebrick;
      }
    </style>
  </head>
  <body>
    <article>
      <h2>Заголовок второго уровня</h2>
      <p>Первый абзац</p>
      <p>Второй абзац</p>
    </article>
  </body>
</html>

p:nth-child(2) выбирает абзац, который стоит вторым среди всех детей. После добавления заголовка вторым ребёнком стал первый абзац — для нашей задачи это неприемлемо. p:nth-of-type(2) выбирает второй элемент того же типа, а число абзацев не изменилось. Поэтому, если между нужными элементами могут появиться элементы другого типа, выбирайте *-of-type. Учтите только, что тип — это тег: классы :nth-of-type() не учитывает, .note:first-of-type не означает «первый элемент с классом note».

Соседние селекторы + и ~

Соседние селекторы мы уже применяли в уроке «Селекторы. Часть 2»; здесь закрепим их. Элементы считаются соседними (сестринскими), если у них общий родитель.

Соседний селектор + выбирает элемент справа от знака, если он идёт сразу за элементом слева. Чтобы выбрать абзацы, которые стоят сразу после заголовков <h2>, нужен селектор h2 + p. Какие сестринские элементы не отмечены на схеме?

Выделены абзацы, которые стоят сразу после h2.
Выбор соседних элементов: h2 + p.

Соседний селектор: попробуйте сами

Выделены только первые абзацы после каждого заголовка h2. «Абзац два» внутри div не выбран: перед ним стоит абзац, а не заголовок.

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Соседний селектор +</title>
    <style>
      body { font-family: system-ui, sans-serif; background-color: linen; color: #2b211b; }
      h2 + p {
        /* абзац сразу после h2 у того же родителя */
        background-color: lightblue;
        color: firebrick;
      }
    </style>
  </head>
  <body>
    <div>
      <h2>Заголовок внутри div</h2>
      <p>Абзац один</p>
      <p>Абзац два</p>
    </div>
    <h2>Заголовок внутри body</h2>
    <p>Абзац один</p>
  </body>
</html>

Общий соседний селектор ~ выбирает все элементы справа от знака, которые идут после элемента слева у того же родителя. Между ними могут стоять другие элементы; соседи перед элементом слева не выбираются. h2 ~ p выбирает все абзацы после заголовка, а div ~ * — все элементы после блока <div>: универсальный селектор подходит под любой тип.

Выделены все абзацы, которые стоят после h2 у того же родителя.
Выбор следующих соседних элементов: h2 ~ p.

Общий соседний селектор: попробуйте сами

h2 ~ p выбрал все абзацы после заголовков — оба в div и абзац в body. div ~ * обвёл рамкой и сделал курсивом заголовок и абзац, которые идут после div.

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Общий соседний селектор ~</title>
    <style>
      body { font-family: system-ui, sans-serif; background-color: linen; color: #2b211b; }
      h2 ~ p {
        /* все абзацы после h2 у того же родителя */
        background-color: lightblue;
        color: firebrick;
      }
      div ~ * {
        /* все элементы после div у того же родителя */
        font-style: italic;
        border: 1px solid seagreen;
      }
    </style>
  </head>
  <body>
    <div>
      <h2>Заголовок внутри div</h2>
      <p>Абзац один</p>
      <p>Абзац два</p>
    </div>
    <h2>Заголовок внутри body</h2>
    <p>Абзац один</p>
  </body>
</html>

Потренируйтесь

Выберите первый и последний пункты меню, первый абзац вводного блока и строки режима дня Тони по формуле. Обратите внимание на задание с :first-of-type: перед абзацами стоит заголовок.

  1. Атрибуты и структура

    Первый пункт меню

    Выберите первый пункт меню .menu.

    <div class="intro">
      <h1>Привет! Меня зовут Тони</h1>
      <p>Я карликовый пинчер.</p>
      <p>Мой день рождения — 22 сентября.</p>
      <p>Моя родословная записана в РКФ.</p>
    </div>
    <ul class="menu">
      <li><a href="#">Главная</a></li>
      <li><a href="#">Мои игрушки</a></li>
      <li><a href="#">Фотоальбом</a></li>
      <li><a href="#">Запись на прогулку</a></li>
    </ul>
    <ol class="day">
      <li>7:00 — бужу хозяина</li>
      <li>7:30 — прогулка</li>
      <li>8:00 — завтрак</li>
      <li>13:00 — обед</li>
      <li>19:00 — вечерняя прогулка</li>
      <li>22:00 — сон</li>
    </ol>
  2. Атрибуты и структура

    Последний пункт меню

    Выберите последний пункт меню — «Запись на прогулку».

    <div class="intro">
      <h1>Привет! Меня зовут Тони</h1>
      <p>Я карликовый пинчер.</p>
      <p>Мой день рождения — 22 сентября.</p>
      <p>Моя родословная записана в РКФ.</p>
    </div>
    <ul class="menu">
      <li><a href="#">Главная</a></li>
      <li><a href="#">Мои игрушки</a></li>
      <li><a href="#">Фотоальбом</a></li>
      <li><a href="#">Запись на прогулку</a></li>
    </ul>
    <ol class="day">
      <li>7:00 — бужу хозяина</li>
      <li>7:30 — прогулка</li>
      <li>8:00 — завтрак</li>
      <li>13:00 — обед</li>
      <li>19:00 — вечерняя прогулка</li>
      <li>22:00 — сон</li>
    </ol>
  3. Атрибуты и структура

    Первый абзац вводного блока

    Выберите первый абзац .intro. Перед ним стоит заголовок, поэтому :first-child не подойдёт.

    <div class="intro">
      <h1>Привет! Меня зовут Тони</h1>
      <p>Я карликовый пинчер.</p>
      <p>Мой день рождения — 22 сентября.</p>
      <p>Моя родословная записана в РКФ.</p>
    </div>
    <ul class="menu">
      <li><a href="#">Главная</a></li>
      <li><a href="#">Мои игрушки</a></li>
      <li><a href="#">Фотоальбом</a></li>
      <li><a href="#">Запись на прогулку</a></li>
    </ul>
    <ol class="day">
      <li>7:00 — бужу хозяина</li>
      <li>7:30 — прогулка</li>
      <li>8:00 — завтрак</li>
      <li>13:00 — обед</li>
      <li>19:00 — вечерняя прогулка</li>
      <li>22:00 — сон</li>
    </ol>
  4. Атрибуты и структура

    Чётные строки режима дня

    Выберите чётные пункты списка .day.

    <div class="intro">
      <h1>Привет! Меня зовут Тони</h1>
      <p>Я карликовый пинчер.</p>
      <p>Мой день рождения — 22 сентября.</p>
      <p>Моя родословная записана в РКФ.</p>
    </div>
    <ul class="menu">
      <li><a href="#">Главная</a></li>
      <li><a href="#">Мои игрушки</a></li>
      <li><a href="#">Фотоальбом</a></li>
      <li><a href="#">Запись на прогулку</a></li>
    </ul>
    <ol class="day">
      <li>7:00 — бужу хозяина</li>
      <li>7:30 — прогулка</li>
      <li>8:00 — завтрак</li>
      <li>13:00 — обед</li>
      <li>19:00 — вечерняя прогулка</li>
      <li>22:00 — сон</li>
    </ol>
  5. Атрибуты и структура

    Каждый третий

    Выберите в .day пункты с номерами 2 и 5 — каждый третий, начиная со второго.

    <div class="intro">
      <h1>Привет! Меня зовут Тони</h1>
      <p>Я карликовый пинчер.</p>
      <p>Мой день рождения — 22 сентября.</p>
      <p>Моя родословная записана в РКФ.</p>
    </div>
    <ul class="menu">
      <li><a href="#">Главная</a></li>
      <li><a href="#">Мои игрушки</a></li>
      <li><a href="#">Фотоальбом</a></li>
      <li><a href="#">Запись на прогулку</a></li>
    </ul>
    <ol class="day">
      <li>7:00 — бужу хозяина</li>
      <li>7:30 — прогулка</li>
      <li>8:00 — завтрак</li>
      <li>13:00 — обед</li>
      <li>19:00 — вечерняя прогулка</li>
      <li>22:00 — сон</li>
    </ol>
  6. Атрибуты и структура

    Утро

    Выберите первые три пункта списка .day одним селектором с формулой.

    <div class="intro">
      <h1>Привет! Меня зовут Тони</h1>
      <p>Я карликовый пинчер.</p>
      <p>Мой день рождения — 22 сентября.</p>
      <p>Моя родословная записана в РКФ.</p>
    </div>
    <ul class="menu">
      <li><a href="#">Главная</a></li>
      <li><a href="#">Мои игрушки</a></li>
      <li><a href="#">Фотоальбом</a></li>
      <li><a href="#">Запись на прогулку</a></li>
    </ul>
    <ol class="day">
      <li>7:00 — бужу хозяина</li>
      <li>7:30 — прогулка</li>
      <li>8:00 — завтрак</li>
      <li>13:00 — обед</li>
      <li>19:00 — вечерняя прогулка</li>
      <li>22:00 — сон</li>
    </ol>

Формула An+B с подсветкой — в тренажёре позиционных селекторов

Проверьте себя

Выберите ответ — объяснение появится сразу. Ответ можно менять.

1. Что выбирает p > a в разметке <p><span><a>…</a></span></p>?
Показать ответ

Ничего: ссылка — ребёнок span, а не абзаца — Знак > выбирает только непосредственных детей. Эту ссылку выбрал бы селектор потомков p a.

2. В <div> сначала стоит <h2>, затем три абзаца. Что выберет div p:first-child?
Показать ответ

Ничего: первым ребёнком div стоит h2 — p:first-child — абзац, который стоит первым среди всех детей. Первый абзац выберет p:first-of-type.

3. Какие элементы выберет li:nth-child(4n+2)?
Показать ответ

2-й, 6-й, 10-й… — каждый четвёртый, начиная со второго — Подставьте n = 0, 1, 2: 4·0+2 = 2, 4·1+2 = 6, 4·2+2 = 10.

4. Какой селектор выберет первые три пункта списка?
Показать ответ

li:nth-child(-n+3) — -n+3 даёт 3, 2, 1, 0, −1…: существуют только номера 1–3.

5. Строки таблицы нужно чередовать: каждая вторая на цветном фоне. Какой селектор подходит?
Показать ответ

tr:nth-child(even) — even — чётные номера: 2, 4, 6. То же даёт 2n.

6. В статье заголовок h2 и два абзаца. Какой селектор выберет второй абзац и не сломается, если заголовок удалить?
Показать ответ

p:nth-of-type(2) — Он считает только абзацы, поэтому заголовок на результат не влияет.

7. Что выберет h2 + p?
Показать ответ

Абзацы, которые стоят сразу после заголовка h2 у того же родителя — + выбирает только ближайшего следующего соседа.

8. Чем h2 ~ p отличается от h2 + p?
Показать ответ

~ выбирает все следующие абзацы у того же родителя, даже если между ними есть другие элементы — + берёт только соседа сразу за заголовком, ~ — всех следующих.

Задание

Ожидаемый результат: на всех страницах перед словом «Главная» в меню стоит лапка. На главной первый абзац «Я карликовый пинчер…» крупнее двух следующих. .intro p:first-child не сработал, потому что первым ребёнком .intro стоит заголовок <h1>; подходит .intro p:first-of-type.

Выполните задание

css/style.css
CSS
/* Общие стили сайта Тони */

/* Ширина и высота включают внутренние отступы и рамку — у всех элементов и псевдоэлементов */
*,
*::before,
*::after {
  box-sizing: border-box;
}

/* Шрифт заголовков Nunito (лицензия SIL Open Font License): кириллица и латиница в разных файлах */
@font-face {
  font-family: "Nunito";
  src: url("../assets/nunito-cyrillic-800-normal.woff2") format("woff2");
  font-weight: 800;
  font-display: swap; /* пока шрифт загружается, текст виден запасным шрифтом */
  unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
  font-family: "Nunito";
  src: url("../assets/nunito-latin-800-normal.woff2") format("woff2");
  font-weight: 800;
  font-display: swap;
  unicode-range: U+0000-00FF, U+2000-206F, U+20AC, U+2122;
}

body {
  background-color: linen;
  color: #2b211b; /* цвет для потомков без собственного значения */
  font-size: 1.0625rem; /* 17px при настройке браузера по умолчанию */
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; /* системный шрифт устройства */
  line-height: 1.6; /* множитель: у каждого элемента интервал от его собственного размера шрифта */
  margin: 0; /* убираем отступ браузера: шапка и подвал во всю ширину окна */
}

/* Поля основного содержимого: текст не прижимается к краям окна */
main {
  padding: 1.5rem 1rem;
  max-width: 68rem; /* на широком экране строки не растягиваются на всё окно */
  margin: 0 auto; /* колонка по центру */
}

/* Изображения и видео не шире колонки, пропорции сохраняются */
img,
video {
  max-width: 100%;
  height: auto;
}

/* Фреймы, аудиоплеер, индикаторы и поля формы не выходят за колонку */
progress,
meter,
iframe,
audio,
input,
select,
textarea,
button {
  max-width: 100%;
}

/* Разрешаем группе полей сужаться вместе с колонкой. */
fieldset {
  min-width: 0;
}

/* Общий цвет заголовков — групповой селектор */
h1,
h2 {
  color: saddlebrown;
  font-family: "Nunito", "Trebuchet MS", system-ui, sans-serif;
  font-weight: 800;
  line-height: 1.2; /* крупному тексту хватает меньшего интервала */
}

/* Размеры заголовков в rem — от размера шрифта корня, а не родителя */
h1 {
  text-align: center;
  font-size: 2.5rem;
}

h2 {
  font-size: 1.75rem;
}

/* Вводный блок главной страницы */
.intro {
  background-color: hsl(30, 80%, 95%);
  padding: 1.5rem; /* фон вокруг текста; заодно не выпускает margin заголовка за пределы блока */
  border-radius: 16px; /* скругляется и фон, хотя рамки нет */
  /* Лапка в правом нижнем углу; цвет фона выше остаётся запасным, если картинка не загрузится */
  background-image: url("../assets/paw.svg");
  background-repeat: no-repeat;
  background-position: right 1rem bottom 1rem;
  background-size: 4rem;
}

/* Разделы главной — светлые карточки на фоне страницы */
main > section {
  background-color: #fffaf3;
  border: 1px solid hsl(28, 30%, 82%);
  border-radius: 16px;
  padding: 1.5rem;
  margin-top: 1.5rem;
}

/* Ширина вводных абзацев ограничена 60ch; количество букв в строке зависит от шрифта и текста */
.intro p {
  max-width: 60ch;
}

/* Важное предупреждение во вводном блоке — темнее основного акцента */
.intro strong {
  color: #6e3510;
}

/* Оглавление главной страницы — переносимый ряд «таблеток» на Flexbox */
.toc {
  background-color: white;
  border: 1px solid tan;
  display: flex;
  flex-wrap: wrap; /* «таблетки», которым не хватает места, переходят на новую строку */
  gap: 0.5rem; /* промежутки между «таблетками» и между строками */
  list-style: none;
  padding: 0.75rem;
}

/* Подчёркивание ссылок чуть ниже букв: не задевает выносные элементы */
a {
  text-underline-offset: 3px;
}

/* Тонкая линия отделяет шапку от страницы */
header {
  border-bottom: 1px solid tan;
}

/* Меню на Flexbox: пункты могут переноситься, промежутки задаёт gap */
nav ul {
  margin: 0;
  padding: 0.5rem 1rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  list-style: none;
}

/* Ссылка на запись стоит отдельно у правого края: автоматический отступ забирает свободное место */
nav li:last-child {
  margin-left: auto;
}

/* Ссылки меню в шапке — селектор потомков */
nav a {
  color: saddlebrown;
  text-decoration: none;
  display: inline-block; /* у строчной ссылки вертикальный padding не раздвигает строку */
  padding: 0.4rem 0.9rem;
  border-radius: 999px; /* «таблетка»: радиус больше половины высоты */
}

/* Ссылки оглавления главной страницы */
.toc a {
  color: #6b5d52; /* тёплый серый: контраст 6.34:1 на белом фоне оглавления */
  display: block; /* ссылка заполняет «таблетку» целиком */
  padding: 0.25rem 0.75rem;
  border: 1px solid tan;
  border-radius: 999px;
  text-decoration: none;
}

/* Фотографии со скруглёнными углами */
figure img {
  border-radius: 8px;
}

figcaption {
  color: #6b5d52; /* тёплый серый: контраст 5.64:1 на фоне linen */
  font-size: 0.95rem;
}

footer {
  background-color: hsl(30, 50%, 90%);
  text-align: center;
  padding: 1rem;
}

/* Ссылка в подвале берёт цвет текста подвала */
footer a {
  color: inherit;
}

/* Поля формы получают шрифт страницы вместо шрифта браузера */
input,
select,
textarea,
button {
  font: inherit;
}

/* Ссылки темнеют при наведении указателя */
a:hover {
  color: #5c2d0c;
}

/* Ссылки меню подчёркиваются при наведении и фокусе с клавиатуры */
nav a:hover,
nav a:focus-visible {
  text-decoration: underline;
}

/* Заметная рамка фокуса у ссылок, полей и кнопок при работе с клавиатуры */
:focus-visible {
  outline: 3px solid #1f6feb;
  outline-offset: 3px;
}

/* Цитата из книги — шрифтом с засечками и курсивом */
blockquote {
  font-family: Georgia, "Times New Roman", serif;
  font-style: italic;
  border-left: 4px solid tan; /* черта слева выделяет цитату */
  padding-left: 1rem;
}

/* Подпись под цитатой — у правого края */
blockquote + figcaption {
  text-align: right;
}

/* Строки формы на Flexbox: подпись — колонка постоянной ширины, поле занимает остаток строки,
   а на узком экране переносится под подпись */
fieldset p {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
}

fieldset p label {
  flex: 0 1 12rem; /* не растёт, но может сжаться в узкой строке */
  min-width: 0;
}

fieldset p input,
fieldset p select,
fieldset p textarea {
  flex: 1 1 12rem; /* растёт и сжимается от исходной ширины 12rem */
  min-width: 0; /* поле может стать уже своего автоматического минимума */
}

/* Фотоальбом на Grid: столько колонок, сколько помещается карточек шириной не меньше 15rem */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: 1rem;
  list-style: none;
  padding: 0;
}

.gallery figure {
  margin: 0;
}

.gallery img {
  width: 100%; /* фото заполняет ширину своей ячейки */
}

/* Список команд: первая колонка подстраивается под текст, оставляя место для перевода. */
dl {
  display: grid;
  grid-template-columns: fit-content(calc(50% - 0.5rem)) minmax(0, 1fr);
  gap: 0.5rem 1rem;
}

dt {
  overflow-wrap: anywhere;
  grid-column: 1;
  font-weight: bold;
}

dd {
  grid-column: 2;
  overflow-wrap: anywhere; /* длинный перевод переносится внутри своей колонки */
  margin: 0; /* браузерный отступ слева больше не нужен: колонку задаёт сетка */
}

/* Длинные слова и адреса переносятся, а не выходят за край узкого экрана */
body {
  overflow-wrap: break-word;
}

/* Таблица режима дня на узком экране прокручивается в своей рамке, а не сжимается до нечитаемых колонок */
.table-wrap {
  overflow-x: auto;
}

table {
  width: 100%;
  min-width: 28rem;
}

/* Подпись таблицы прокручивается вместе с ней: прижимаем её к началу, чтобы она была видна сразу */
caption {
  text-align: left;
}

/* Широкий экран: в разделе «Моя любимая игрушка» фото справа, текст слева.
   На узком экране правило не действует, и раздел остаётся одной колонкой. */
@media (width >= 48rem) {
  .toy {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 300px;
    column-gap: 1.5rem;
  }

  .toy figure {
    grid-column: 2;
    grid-row: 1 / span 6; /* фото рядом со всеми абзацами раздела */
    margin: 0;
  }

  .toy hr {
    width: 100%;
  }
}

/* Карточка альбома — точка отсчёта для значка: position: relative не сдвигает её и не меняет поток */
.gallery li {
  position: relative;
}

/* Значок «Любимая» в правом верхнем углу карточки; из потока исключён, поэтому фото не сдвигается */
.badge {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  padding: 0.2rem 0.7rem;
  border-radius: 999px;
  background-color: saddlebrown;
  color: white;
  font-size: 0.85rem;
  font-weight: bold;
}

/* Шапка прилипает к верхнему краю окна. Фон нужен, чтобы под шапкой не просвечивал текст страницы */
header {
  position: sticky;
  top: 0;
  z-index: 10; /* выше карточек альбома: они тоже позиционированы и записаны в HTML позже шапки */
  background-color: linen;
}

/* Липкая шапка должна быть низкой: пункты меню не сжимаются и не переносятся на вторую строку,
   а если им не хватает места, меню прокручивается внутри шапки */
nav ul {
  flex-wrap: nowrap;
  overflow-x: auto;
}

nav li {
  flex-shrink: 0;
}

/* Заголовок, к которому ведёт ссылка-якорь, не прячется под липкой шапкой.
   В rem: при увеличении текста растут и шапка, и отступ */
[id] {
  scroll-margin-top: 4.5rem;
}

/* Ссылка, которая открывается в новой вкладке, помечена стрелкой — посетитель знает, что страница не сменится */
a[target="_blank"]::after {
  content: " ↗";
}

/* Ссылка на электронную почту — с конвертом */
a[href^="mailto:"]::before {
  content: "✉ ";
}

/* Карточка альбома, в которой есть значок, выделена рамкой — без отдельного класса в HTML */
.gallery li:has(.badge) {
  outline: 3px solid tan;
  outline-offset: 4px;
  border-radius: 8px;
}
index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="Сайт карликового пинчера Тони: игрушки, режим дня и запись на прогулку.">
    <title>Сайт Тони</title>
    <link rel="stylesheet" href="css/style.css">
  </head>
  <body>
    <header>
      <!-- Меню сайта -->
      <nav>
        <ul>
          <li><a href="index.html">Главная</a></li>
          <li><a href="pages/toys.html">Мои игрушки</a></li>
          <li><a href="pages/signup.html">Запись на прогулку</a></li>
        </ul>
      </nav>
    </header>
    <main>
      <div class="intro">
        <h1 id="top">Привет! Меня зовут Тони</h1>
        <p>Я карликовый пинчер. Мне три года, я вешу 8&nbsp;кг и люблю гулять в любую погоду. Хозяин говорит: <q>Тони — лучший сторож в доме</q>.</p>
        <p>Мой день рождения — <time datetime="2023-09-22">22 сентября</time>. <strong>Пожалуйста, не кормите меня со стола!</strong></p>
        <p>Моя родословная записана в Российской кинологической федерации (<abbr title="Российская кинологическая федерация">РКФ</abbr>).</p>
      </div>
      <ul class="toc">
        <li><a href="#toy">Моя любимая игрушка</a></li>
        <li><a href="#commands">Команды, которые я знаю</a></li>
        <li><a href="#schedule">Мой режим дня</a></li>
        <li><a href="#walks">Где я гуляю</a></li>
        <li><a href="#song">Песня для прогулок</a></li>
      </ul>
      <section class="toy">
        <h2 id="toy">Моя любимая игрушка</h2>
        <p data-toy-id="17">Это канат с мячиком. Хозяин бросает его, а я приношу обратно — <em>почти</em> всегда. <a href="pages/toys.html">Посмотреть все игрушки Тони</a>.</p>
        <figure>
          <img src="assets/tony-toy.png" alt="Тони сидит и держит в зубах канат с красным мячиком" width="300" height="400" title="Мой канат &quot;Удав&quot;">
          <figcaption>Я и мой канат «Удав»</figcaption>
        </figure>
        <p><a href="assets/tony-toy.png" download>Скачать фотографию</a></p>
        <p>Подробнее о моей породе — в статье <a href="https://ru.wikipedia.org/wiki/Карликовый_пинчер" target="_blank">«Карликовый пинчер» в Википедии</a>.</p>
        <hr>
        <p>Вечером игра закончилась. Канат остался на полу, а я свернулся калачиком в кресле.</p>
      </section>
      <section>
        <h2>Мой стишок</h2>
        <p>
          Я маленький, но смелый,<br>
          Гуляю целый день,<br>
          А вечером на кресле<br>
          Сплю — и мне не лень.
        </p>
      </section>
      <section>
        <h2 id="commands">Команды, которые я знаю</h2>
        <p>Хозяин научил меня командам на немецком:</p>
        <dl>
          <dt lang="de">Sitz!</dt>
          <dd>сидеть</dd>
          <dt lang="de">Platz!</dt>
          <dd>лежать</dd>
          <dt lang="de">Fuß!</dt>
          <dd>рядом</dd>
        </dl>
        <details>
          <summary>Почему команды на немецком?</summary>
          <p>Карликовый пинчер — немецкая порода, и хозяину понравилась эта традиция.</p>
        </details>
      </section>
      <section>
        <h2 id="schedule">Мой режим дня</h2>
        <div class="table-wrap" tabindex="0" role="region" aria-label="Режим дня Тони">
          <table>
            <caption>Режим дня Тони</caption>
            <thead>
              <tr>
                <th scope="col">Время</th>
                <th scope="col">Будни</th>
                <th scope="col">Выходные</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <th scope="row">07:00</th>
                <td>Прогулка, 20 минут</td>
                <td>Сплю</td>
              </tr>
              <tr>
                <th scope="row">08:00</th>
                <td colspan="2">Завтрак</td>
              </tr>
              <tr>
                <th scope="row">13:00</th>
                <td>Жду хозяина и сплю</td>
                <td>Прогулка в парке, 1 час</td>
              </tr>
              <tr>
                <th scope="row">19:00</th>
                <td colspan="2">Ужин</td>
              </tr>
              <tr>
                <th scope="row">21:00</th>
                <td colspan="2">Вечерняя прогулка</td>
              </tr>
            </tbody>
          </table>
        </div>
      </section>
      <section>
        <h2 id="progress">Мои успехи</h2>
        <p>Учу команду «Апорт»: пройдено 3 занятия из 5. <progress value="3" max="5">3 из 5</progress></p>
        <p>Прогулка сегодня: 40 минут. <meter value="40" min="0" max="90" low="30" high="60" optimum="75">40 из 90 минут</meter></p>
      </section>
      <section>
        <h2 id="walks">Где я гуляю</h2>
        <p>Я люблю гулять в сквере у дома.</p>
        <p>
          <a href="pages/walks.html" target="walk">Маршрут</a> |
          <a href="assets/tony.png" target="walk">Фото с прогулки</a>
        </p>
        <iframe src="pages/walks.html" name="walk" title="Маршрут и фото прогулки Тони" width="320" height="420"></iframe>
        <h3>Видео с прогулки</h3>
        <p>Субтитры помогут, если вы смотрите видео без звука.</p>
        <video width="180" height="320" poster="assets/walk.jpg" controls>
          <source src="assets/walk.mp4" type="video/mp4">
          <track src="assets/ru.vtt" kind="subtitles" srclang="ru" label="Русский" default>
          <p><a href="assets/walk.mp4">Скачать видео</a></p>
        </video>
        <h3>Как я лаю</h3>
        <p>Так я разговариваю с хозяином — у нас целый диалог!</p>
        <audio controls>
          <source src="assets/bark.mp3" type="audio/mpeg">
          <p><a href="assets/bark.mp3">Скачать запись</a></p>
        </audio>
      </section>
      <section>
        <h2 id="song">Песня для прогулок</h2>
        <p>Хозяин включает эту песню, когда мы выходим гулять.</p>
        <iframe width="480" height="270" src="https://www.youtube.com/embed/ojULkWEUsPs?start=17" title="Baha Men — Who Let the Dogs Out" loading="lazy" allow="fullscreen"></iframe>
        <p><a href="https://www.youtube.com/watch?v=ojULkWEUsPs">Baha Men — Who Let the Dogs Out на YouTube</a></p>
      </section>
      <section>
        <h2>Моя любимая книга</h2>
        <p>Хозяин читал мне вслух рассказ <cite>«Каштанка»</cite> Антона Чехова. Он начинается так:</p>
        <figure>
          <blockquote>
            <p>Молодая рыжая собака — помесь таксы с дворняжкой — очень похожая мордой на лисицу, бегала взад и вперёд по тротуару и беспокойно оглядывалась по сторонам.</p>
          </blockquote>
          <figcaption>— Антон Чехов, <cite>«Каштанка»</cite></figcaption>
        </figure>
      </section>
      <p><a href="#top">Наверх</a></p>
    </main>
    <footer>
      <p><small>&copy; 2026 Тони и его хозяин</small></p>
      <address>Написать хозяину Тони: <a href="mailto:tony@example.com">tony@example.com</a></address>
    </footer>
  </body>
</html>
pages/signup.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="Запишитесь на совместную прогулку с карликовым пинчером Тони.">
    <title>Запись на прогулку с Тони</title>
    <link rel="stylesheet" href="../css/style.css">
  </head>
  <body>
    <header>
      <nav>
        <ul>
          <li><a href="../index.html">Главная</a></li>
          <li><a href="toys.html">Мои игрушки</a></li>
          <li><a href="signup.html">Запись на прогулку</a></li>
        </ul>
      </nav>
    </header>
    <main>
      <h1>Запись на прогулку</h1>
      <p>Гуляйте вместе с Тони! Оставьте заявку, и хозяин Тони напишет вам, чтобы договориться о встрече.</p>
      <p><a href="../index.html#walks">Где мы гуляем</a></p>
      <form>
        <fieldset>
          <legend>О вас</legend>
          <p>
            <label for="owner">Ваше имя</label>
            <input type="text" id="owner" name="owner" autocomplete="name" required>
          </p>
          <p>
            <label for="email">Электронная почта</label>
            <input type="email" id="email" name="email" autocomplete="email" placeholder="anna@example.com" required>
          </p>
        </fieldset>
        <fieldset>
          <legend>Ваша собака</legend>
          <p>
            <label for="breed">Порода</label>
            <input type="text" id="breed" name="breed" list="breeds">
            <datalist id="breeds">
              <option value="Карликовый пинчер"></option>
              <option value="Такса"></option>
              <option value="Йоркширский терьер"></option>
              <option value="Беспородная"></option>
            </datalist>
          </p>
          <p>
            <label for="dogs">Сколько собак придёт</label>
            <input type="number" id="dogs" name="dogs" min="1" max="3" value="1">
          </p>
        </fieldset>
        <fieldset>
          <legend>Когда гулять</legend>
          <p>
            <label for="date">Дата</label>
            <input type="date" id="date" name="date" required>
          </p>
          <label><input type="radio" name="time" value="morning" checked> Утром</label>
          <label><input type="radio" name="time" value="evening"> Вечером</label>
        </fieldset>
        <fieldset>
          <legend>Прогулка</legend>
          <p>
            <label for="leader">Ведёт прогулку</label>
            <input type="text" id="leader" name="leader" value="Тони" readonly>
          </p>
          <p>
            <label for="route">Маршрут</label>
            <select id="route" name="route">
              <optgroup label="В городе">
                <option value="square">Сквер у дома</option>
                <option value="pond" selected>Пруд с утками</option>
              </optgroup>
              <optgroup label="За городом">
                <option value="forest">Лес</option>
                <option value="river" disabled>Берег реки — закрыт до весны</option>
              </optgroup>
            </select>
          </p>
          <p>
            <label for="wishes">Пожелания</label>
            <textarea id="wishes" name="wishes" rows="4" cols="40" maxlength="300" placeholder="Например: моя собака боится велосипедов"></textarea>
          </p>
        </fieldset>
        <fieldset>
          <legend>Что взять с собой</legend>
          <label><input type="checkbox" name="take" value="ball"> Мячик</label>
          <label><input type="checkbox" name="take" value="rope"> Канат</label>
        </fieldset>
        <p>
          <button type="submit">Записаться на прогулку</button>
          <button type="reset">Очистить форму</button>
        </p>
      </form>
    </main>
    <footer>
      <p><small>&copy; 2026 Тони и его хозяин</small></p>
      <address>Написать хозяину Тони: <a href="mailto:tony@example.com">tony@example.com</a></address>
    </footer>
  </body>
</html>
pages/toys.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="Любимые игрушки Тони и правила игры в канат.">
    <title>Игрушки Тони</title>
    <link rel="stylesheet" href="../css/style.css">
  </head>
  <body>
    <header>
      <nav>
        <ul>
          <li><a href="../index.html">Главная</a></li>
          <li><a href="toys.html">Мои игрушки</a></li>
          <li><a href="signup.html">Запись на прогулку</a></li>
        </ul>
      </nav>
    </header>
    <main>
      <h1>Мои игрушки</h1>
      <ul>
        <li>Канат с мячиком «Удав» — моя любимая игрушка</li>
        <li>Резиновая косточка — для вечеров, когда гулять уже поздно</li>
        <li>Пищащий ёжик — его я прячу <del>под диваном</del> <ins>в своей лежанке</ins></li>
      </ul>
      <img src="../assets/tony.png" alt="Тони сидит и смотрит в камеру" width="300" height="400">
      <h2>Как играть со мной в канат</h2>
      <ol>
        <li>Покажите мне канат.</li>
        <li>Бросьте его подальше.</li>
        <li>Подождите, пока я принесу его обратно.</li>
        <li>Похвалите меня — и всё сначала!</li>
      </ol>
      <section>
        <h2 id="album">Мой фотоальбом</h2>
        <ul class="gallery">
          <li>
            <figure>
              <img src="../assets/album-puppy.png" alt="Тони-щенок сидит и смотрит в камеру" width="300" height="400">
              <figcaption>Я в детстве</figcaption>
            </figure>
          </li>
          <li>
            <figure>
              <img src="../assets/album-squirrel.png" alt="Тони лежит в обнимку с плюшевой белкой" width="300" height="400">
              <figcaption>С плюшевой белкой</figcaption>
            </figure>
            <span class="badge">Любимая</span>
          </li>
          <li>
            <figure>
              <img src="../assets/album-hoodie.png" alt="Тони стоит в бежевой толстовке с капюшоном" width="300" height="400">
              <figcaption>В худи для холодной погоды</figcaption>
            </figure>
          </li>
          <li>
            <figure>
              <img src="../assets/album-harness.png" alt="Тони в оранжевой шлейке ждёт прогулку" width="300" height="400">
              <figcaption>Шлейка надета — идём гулять!</figcaption>
            </figure>
          </li>
          <li>
            <figure>
              <img src="../assets/album-laugh.png" alt="Тони лежит, запрокинув голову, и широко открыл пасть, будто смеётся" width="300" height="400">
              <figcaption>Смеюсь над шуткой хозяина</figcaption>
            </figure>
          </li>
          <li>
            <figure>
              <img src="../assets/album-sleep.png" alt="Тони спит, положив голову на лапы" width="300" height="319">
              <figcaption>После прогулки</figcaption>
            </figure>
          </li>
        </ul>
      </section>
      <p><a href="../index.html#commands">Какие команды я знаю</a></p>
      <p><a href="../index.html">Вернуться на главную</a></p>
    </main>
    <footer>
      <p><small>&copy; 2026 Тони и его хозяин</small></p>
      <address>Написать хозяину Тони: <a href="mailto:tony@example.com">tony@example.com</a></address>
    </footer>
  </body>
</html>
pages/walks.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="Маршрут прогулки Тони: сквер, пруд и поляна для игры с канатом.">
    <title>Где гуляет Тони</title>
    <link rel="stylesheet" href="../css/style.css">
  </head>
  <body>
    <h1>Мой маршрут</h1>
    <ol>
      <li>Сквер у дома.</li>
      <li>Пруд с утками.</li>
      <li>Поляна для игры с канатом.</li>
    </ol>
  </body>
</html>

Продолжите в VS Code

Внесите те же правила в css/style.css своего сайта my-site и откройте главную страницу. Проверка: на вкладке Elements у первого абзаца вводного блока в Styles видно правило .intro p:first-of-type. Если результат отличается, нажмите в редакторе «Показать решение» и сравните его со своим кодом.

Дополнительные задачи

1. С помощью псевдоклассов дочерних элементов окрасьте абзацы: первый — оранжевым, второй и четвёртый — зелёным, третий — красным, последний — синим.

Ожидаемый результат: цвета абзацев сверху вниз — оранжевый, зелёный, красный, зелёный, синий.

Выполните дополнительную задачу 1

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Дополнительная задача</title>
    <style>
      body { font-family: system-ui, sans-serif; background-color: linen; color: #2b211b; }
    </style>
  </head>
  <body>
    <p>Абзац номер один.</p>
    <p>Абзац номер два.</p>
    <p>Абзац номер три.</p>
    <p>Абзац номер четыре.</p>
    <p>Абзац номер пять.</p>
  </body>
</html>

2. С помощью псевдоклассов по типу окрасьте абзацы в обоих блоках: первый — оранжевым, второй и четвёртый — зелёным, третий — красным. Заголовки не меняйте.

Ожидаемый результат: в каждом блоке абзацы оранжевый, зелёный, красный, зелёный; заголовки чёрные.

Выполните дополнительную задачу 2

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Дополнительная задача</title>
    <style>
      body { font-family: system-ui, sans-serif; background-color: linen; color: #2b211b; }
    </style>
  </head>
  <body>
    <div class="test">
      <h2>Заголовок второго уровня</h2>
      <p>Абзац один</p>
      <p>Абзац два</p>
      <p>Абзац три</p>
      <p>Абзац четыре</p>
    </div>
    <div class="test">
      <h2>Заголовок второго уровня</h2>
      <p>Абзац один</p>
      <p>Абзац два</p>
      <p>Абзац три</p>
      <p>Абзац четыре</p>
    </div>
  </body>
</html>

3. С помощью соседних селекторов окрасьте зелёным все абзацы после заголовка, а список, который идёт сразу после абзаца, выделите голубым фоном.

Ожидаемый результат: все три абзаца зелёные; второй список — на голубом фоне, первый список (сразу после заголовка) — без фона.

Выполните дополнительную задачу 3

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Дополнительная задача</title>
    <style>
      body { font-family: system-ui, sans-serif; background-color: linen; color: #2b211b; }
    </style>
  </head>
  <body>
    <h2>Заголовок второго уровня</h2>
    <ul>
      <li>Пункт списка 1</li>
      <li>Пункт списка 2</li>
      <li>Пункт списка 3</li>
    </ul>
    <p>Абзац один</p>
    <p>Абзац два</p>
    <ul>
      <li>Пункт списка 1</li>
      <li>Пункт списка 2</li>
      <li>Пункт списка 3</li>
    </ul>
    <p>Абзац три</p>
  </body>
</html>