Псевдоклассы и псевдоэлементы

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

До сих пор мы применяли стили к HTML-элементам с помощью селекторов типа, класса, идентификатора и комбинаторов. В предыдущем уроке мы разобрали, как браузер выбирает победителя среди этих правил.

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

Псевдоэлементы

Псевдоэлемент выбирает часть элемента или создаёт содержимое, которого нет в HTML-коде. Его добавляют к селектору через два двоеточия:

CSS
селектор::псевдоэлемент {
  свойство: значение;
}

В этом уроке мы рассмотрим пять распространённых псевдоэлементов: ::first-letter, ::first-line, ::selection, ::before и ::after. Другие, например ::marker для маркеров списка, встретятся дальше в учебнике.

Псевдоэлементы ::first-letter и ::first-line

Псевдоэлемент ::first-letter выбирает первую букву текстового блока. С его помощью создают инициал (буквицу) — увеличенную начальную букву, как в печатных изданиях, например в сказках.

Псевдоэлемент ::first-line выбирает первую строку текстового блока, чтобы она отличалась от основного текста. Где закончится первая строка, зависит от ширины блока: при изменении ширины окна оформление переходит на другие слова.

Псевдоэлементы ::first-letter и ::first-line: попробуйте сами

Первая буква каждого абзаца крупная и коричневая. Остальной текст первой строки стихотворения с классом poem — зелёный; шрифт всей первой строки — Arial. Сузьте область результата, чтобы первая строка стихотворения перенеслась, и сравните оформление.

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Псевдоэлементы ::first-letter и ::first-line</title>
    <style>
      p::first-letter {
        /* первая буква каждого абзаца */
        color: saddlebrown; /* цвет буквы */
        font-size: 32px; /* размер буквы */
      }
      .poem::first-line {
        /* первая строка стихотворения */
        color: green; /* цвет первой строки */
        font-family: Arial, sans-serif; /* шрифт первой строки */
      }
    </style>
  </head>
  <body>
    <p>Я карликовый пинчер. Мне три года, я вешу 8&nbsp;кг и люблю гулять в любую погоду.</p>
    <p class="poem">
      Я маленький, но смелый,<br>
      Гуляю целый день,<br>
      А вечером на кресле<br>
      Сплю — и мне не лень.
    </p>
  </body>
</html>

Эти псевдоэлементы работают с блочными элементами вроде абзацев и заголовков. Если записать селектор без элемента — ::first-letter, — он выберет первую букву каждого такого блока на странице.

Псевдоэлемент ::selection

Псевдоэлемент ::selection оформляет текст, который выделил пользователь. С ним используют ограниченный набор свойств: цвет текста, цвет фона, линии и тень текста. Работу с тенью мы подробно рассмотрим в уроке «Текстовая тень в CSS».

Псевдоэлемент ::selection: попробуйте сами

Выделите часть текста: выделение белое на коричневом фоне. Измените цвета в правиле и выделите текст снова.

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Псевдоэлемент ::selection</title>
    <style>
      ::selection {
        /* текст, выделенный пользователем */
        color: white; /* цвет текста */
        background-color: saddlebrown; /* цвет фона */
      }
    </style>
  </head>
  <body>
    <p>
      Карликовый пинчер — немецкая порода небольших собак. Пинчеры энергичные, смелые и внимательные: несмотря на
      маленький рост, они хорошие сторожа. Им нужны ежедневные прогулки и игры, а в холодную погоду — тёплая одежда.
    </p>
  </body>
</html>

Раньше Firefox поддерживал этот псевдоэлемент только с префиксом производителя (::-moz-selection), и правило приходилось дублировать. Сейчас все основные браузеры понимают ::selection без префикса. Псевдоэлемент долго не входил ни в одну спецификацию: его убрали из черновика модуля селекторов, а позже включили в модуль псевдоэлементов (CSS Pseudo-Elements).

Псевдоэлементы ::before и ::after

Псевдоэлемент ::before добавляет содержимое в начало элемента, перед его собственным содержимым, а ::after — в конец, после него. Оба используются со свойством content, которое задаёт добавляемое (сгенерированное) содержимое. Без content псевдоэлемент не появится.

Добавим значок лапки перед каждым заголовком <h2> и стрелку после ссылки на другой сайт:

Псевдоэлементы ::before и ::after: попробуйте сами

Перед заголовками появилась лапка, после ссылки с классом external — стрелка. В HTML-коде их нет. Попробуйте выделить и скопировать лапку вместе с заголовком.

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Псевдоэлементы ::before и ::after</title>
    <style>
      h2::before {
        /* перед каждым заголовком второго уровня */
        content: "🐾 "; /* декоративный значок */
      }
      .external::after {
        /* после ссылки с классом external */
        content: " ↗"; /* стрелка: ссылка ведёт на другой сайт */
      }
    </style>
  </head>
  <body>
    <h2>Моя любимая игрушка</h2>
    <p>Это канат с мячиком.</p>
    <h2>Моя порода</h2>
    <p>Подробнее — в статье <a href="https://ru.wikipedia.org/wiki/Карликовый_пинчер" class="external">«Карликовый пинчер» в Википедии</a>.</p>
  </body>
</html>

С помощью ::before и ::after добавляют не только текст, но и изображения, счётчики, разноцветные маркеры списков и так далее. Мы ещё вернёмся к этим псевдоэлементам с более глубокими знаниями CSS.

Псевдоклассы

Псевдокласс выбирает элемент в определённом состоянии или положении: ссылку под указателем мыши, поле в фокусе, первый дочерний элемент. Его добавляют к селектору через одно двоеточие:

CSS
селектор:псевдокласс {
  свойство: значение;
}

В CSS десятки псевдоклассов, и мы рассмотрим большинство из них по ходу учебника. В этом уроке — псевдоклассы фокуса и состояний ссылок. У рассматриваемых здесь псевдоклассов специфичность такая же, как у класса, а у псевдоэлементов — как у селектора типа: селектор a:hover имеет специфичность (0, 1, 1).

Фокус на элементе

Псевдокласс :focus выбирает элемент, который сейчас находится в фокусе, то есть принимает ввод с клавиатуры. Фокус получают ссылки, поля формы и кнопки: при щелчке мышью или при переходе клавишей Tab.

Псевдокласс :focus: попробуйте сами

Щёлкните в поле или перейдите к нему клавишей Tab: поле получит фон, цвет, размер текста и оранжевую границу. Когда поле теряет фокус, стиль возвращается к первоначальному.

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Псевдокласс :focus</title>
    <style>
      input:focus {
        /* поле, которое сейчас в фокусе */
        background-color: khaki; /* цвет фона */
        color: brown; /* цвет текста */
        font-size: 18px; /* размер шрифта */
        border: 2px solid orange; /* сплошная оранжевая граница толщиной 2 пикселя */
      }
    </style>
  </head>
  <body>
    <form>
      <p><label for="owner">Ваше имя</label> <input type="text" id="owner" name="owner"></p>
      <p><label for="email">Электронная почта</label> <input type="email" id="email" name="email"></p>
    </form>
  </body>
</html>

Видимый фокус: :focus-visible

Человеку, который работает с клавиатуры, нужен видимый индикатор фокуса — обычно это рамка. Браузеры рисуют её сами, но стандартная рамка бывает плохо заметна на цветном фоне. При этом рамка вокруг кнопки после щелчка мышью многим кажется лишней.

Псевдокласс :focus-visible выбирает элемент в фокусе, только когда браузер считает, что фокус нужно показать: при переходе клавишей Tab — обычно да, при щелчке мышью по кнопке или ссылке — обычно нет. У текстовых полей фокус показывается и после щелчка: в них сразу вводят текст.

Рамку фокуса рисуют свойством outline — контуром вокруг элемента, который не меняет его размеров и не сдвигает соседние элементы. Свойство outline-offset отодвигает контур от края элемента:

Псевдокласс :focus-visible: попробуйте сами

В Google Chrome щёлкните по обеим кнопкам: оранжевая рамка :focus появится после щелчка, синяя рамка :focus-visible обычно не появится. Теперь щёлкните в результат над кнопками и переходите клавишей Tab: синяя рамка видна у второй кнопки и ссылки. Поведение при щелчке зависит от браузера и настроек фокуса. На телефоне сравните рамки в разделе «Образец оформления»: они показаны постоянно, без получения фокуса. Измените цвет или толщину рамок в CSS — образцы тоже изменятся. Для проверки переходов клавишей Tab подключите физическую клавиатуру.

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Псевдокласс :focus-visible</title>
    <style>
      /* Классы образцов показывают те же рамки постоянно, без фокуса. */
      .focus:focus,
      .focus-sample {
        /* любой фокус: и щелчок мышью, и клавиатура */
        outline: 3px solid orange;
      }
      .focus-visible:focus-visible,
      .focus-visible-sample {
        /* только когда браузер считает, что фокус нужно показать */
        outline: 3px solid #1f6feb;
        outline-offset: 3px;
      }
    </style>
  </head>
  <body>
    <p><button type="button" class="focus">Кнопка с :focus</button></p>
    <p><button type="button" class="focus-visible">Кнопка с :focus-visible</button></p>
    <p><a href="#" class="focus-visible">Ссылка с :focus-visible</a></p>
    <h2>Образец оформления</h2>
    <p>Эти рамки видны постоянно, в том числе на телефоне. Это образцы оформления, а не элементы в фокусе.</p>
    <p><span class="focus-sample">Рамка из правила :focus</span></p>
    <p><span class="focus-visible-sample">Рамка из правила :focus-visible</span></p>
  </body>
</html>

Ещё один псевдокласс фокуса — :focus-within. Он выбирает элемент, если фокус находится в нём самом или в любом его потомке. Например, правило form p:focus-within { background-color: khaki; } подсветит абзац формы, пока в его поле вводят текст. Мы применим его в уроке об оформлении форм.

Рассмотрим четыре псевдокласса, которыми часто оформляют состояния ссылок:

  • :link — ссылка, по которой пользователь ещё не переходил (непосещённая);
  • :visited — ссылка, которую браузер считает посещённой с учётом истории и ограничений приватности;
  • :hover — на ссылку наведён указатель;
  • :active — ссылка во время активации, например пока на ней удерживают основную кнопку мыши.

:link и :visited относятся только к ссылкам с атрибутом href. Как правило, их используют вместе: :link оформляет непосещённые ссылки, :visited — посещённые.

Наведите указатель на ссылку — она станет оранжевой, нажмите и удерживайте кнопку мыши — красной. Поменяйте правила a:hover и a:link местами и снова наведите указатель. Во встроенном примере изменение цвета через :visited может не проявиться из-за изоляции предпросмотра и ограничений истории браузера.

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Состояния ссылок</title>
    <style>
      a:link {
        /* непосещённая ссылка */
        color: saddlebrown;
      }
      a:visited {
        /* посещённая ссылка */
        color: purple;
      }
      a:hover {
        /* указатель над ссылкой */
        color: orange;
      }
      a:active {
        /* ссылка нажата */
        color: red;
      }
    </style>
  </head>
  <body>
    <p><a href="#toy">Моя любимая игрушка</a></p>
    <p><a href="#commands">Команды, которые я знаю</a></p>
    <p><a href="#schedule">Мой режим дня</a></p>
    <h2 id="toy">Моя любимая игрушка</h2>
    <p>Люблю играть с мячом.</p>
    <h2 id="commands">Команды, которые я знаю</h2>
    <p>Знаю команды «Сидеть» и «Ко мне».</p>
    <h2 id="schedule">Мой режим дня</h2>
    <p>Утром гуляю, днём отдыхаю, вечером играю.</p>
  </body>
</html>

Наличие адреса в истории не гарантирует срабатывание :visited на любом сайте: браузеры могут учитывать, на каком сайте и в каком фрейме была посещена ссылка. Для :visited разрешён лишь ограниченный набор свойств цвета, например color, background-color, цвет границы и контура. Иначе по размерам или положению элементов сторонний сайт мог бы узнать, какие адреса есть в истории пользователя.

Псевдокласс :active

Псевдокласс :active применяется не только к ссылкам. Он выбирает элемент во время активации — например, пока пользователь удерживает на нём основную кнопку мыши. Кнопка также может активироваться с клавиатуры. Чаще всего этот псевдокласс используют для кнопок, чтобы показать нажатие.

Псевдокласс :active: попробуйте сами

Выберите любой элемент и удерживайте на нём кнопку мыши: пока кнопка нажата, фон элемента оранжевый.

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Псевдокласс :active</title>
    <style>
      p.test:active,
      h3.test:active,
      a.test:active,
      button:active {
        /* групповой селектор: элемент, пока нажата кнопка мыши */
        background-color: orange; /* цвет фона */
      }
    </style>
  </head>
  <body>
    <h3 class="test">Заголовок третьего уровня с классом test</h3>
    <p class="test">Абзац с классом test</p>
    <p><a class="test" href="#">Ссылка с классом test</a></p>
    <p><button type="button">Бросить мячик</button></p>
  </body>
</html>

Псевдокласс :hover

Псевдокласс :hover используется практически на каждом сайте. Он оформляет любой элемент, на который сейчас указывает курсор мыши. Чаще всего его применяют к ссылкам, кнопкам, пунктам меню и строкам таблиц. Подсветим строку таблицы под указателем:

Псевдокласс :hover: попробуйте сами

Наведите указатель на строку таблицы — она подсветится. Замените селектор tr:hover на td:hover и сравните.

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Псевдокласс :hover</title>
    <style>
      table {
        width: 50%; /* ширина таблицы в процентах от ширины родителя */
      }
      th,
      td {
        text-align: left; /* выравнивание текста по левому краю */
        border: 1px solid orange; /* сплошная оранжевая граница толщиной 1 пиксель */
      }
      tr:hover {
        /* строка под указателем */
        background-color: khaki; /* цвет фона */
      }
    </style>
  </head>
  <body>
    <table>
      <caption>Режим дня Тони</caption>
      <tr><th scope="col">Время</th><th scope="col">Будни</th><th scope="col">Выходные</th></tr>
      <tr><td>8:00</td><td>Прогулка</td><td>Сплю</td></tr>
      <tr><td>9:00</td><td>Завтрак</td><td>Прогулка</td></tr>
      <tr><td>14:00</td><td>Сплю</td><td>Игры в парке</td></tr>
      <tr><td>19:00</td><td>Прогулка</td><td>Прогулка</td></tr>
    </table>
  </body>
</html>

В этом примере ширина таблицы задана в процентах. Подробно об единицах измерения — в уроке «Единицы измерения CSS, размер шрифта».

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

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

Определите, каким цветом будет текст элемента <p>.

1 из 3

HTML

CSS

Какого цвета будет текст элемента <p>?

Для проверки ответов включите JavaScript. Пример: .note { color: red } сильнее записанного ниже p { color: blue } для <p class="note">: класс имеет вес (0, 1, 0), тег — (0, 0, 1).

Больше заданий и калькулятор специфичности — в тренажёре каскада

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

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

1. Чем псевдоэлемент отличается от псевдокласса?
Показать ответ

Псевдоэлемент выбирает часть элемента или создаёт содержимое, псевдокласс выбирает элемент в определённом состоянии — ::first-line выбирает часть абзаца, ::before создаёт содержимое, а :hover выбирает весь элемент под указателем.

2. Какая запись соответствует современному синтаксису?
Показать ответ

p::first-letter и a:hover — Псевдоэлементы пишут через два двоеточия, псевдоклассы — через одно.

3. Правило .note::before { content: "Внимание: вход по записи"; } — единственное место, где на странице сказано об условии входа. Что не так?
Показать ответ

Важный текст не должен существовать только в сгенерированном содержимом — Содержимое ::before обычно нельзя скопировать как обычный текст, оно пропадает без CSS и по-разному озвучивается программами экранного доступа. Важный текст пишите в HTML.

4. У изображения, которое успешно загрузилось, правило img::before { content: "★"; } не работает. Почему?
Показать ответ

Изображение — замещаемый элемент, у которого эти псевдоэлементы не создаются — У загруженного <img> содержимое заменено изображением. Для декора добавьте псевдоэлемент обёртке, например <figure>.

5. Правила записаны в порядке a:hover { color: orange; }, затем a:link { color: saddlebrown; }. Что произойдёт при наведении на непосещённую ссылку?
Показать ответ

Цвет не изменится: правило a:link ниже и перебивает a:hover — У обоих правил специфичность (0, 1, 1), поэтому побеждает последнее. :hover ставят после :link и :visited.

6. Почему не стоит писать :focus { outline: none; } без другого видимого индикатора фокуса?
Показать ответ

Пользователь клавиатуры перестанет видеть, какой элемент в фокусе — В этом случае рамка — единственный видимый индикатор фокуса при переходе клавишей Tab. Если она мешает, замените её своей через :focus-visible.

7. Чем :focus-visible отличается от :focus?
Показать ответ

Выбирает элемент в фокусе, только когда фокус нужно показать, например при переходе клавишей Tab — После щелчка мышью по кнопке рамка обычно не нужна, а при работе с клавиатуры она обязательна. :focus срабатывает в обоих случаях.

8. На сайте Тони nav a { color: saddlebrown; }, а ниже a:hover { color: #5c2d0c; }. Какого цвета ссылка меню под указателем?
Показать ответ

#5c2d0c — Специфичность a:hover — (0, 1, 1), nav a — (0, 0, 2). Псевдокласс считается как класс и перевешивает второй селектор типа.

Задание

Ожидаемый результат: при наведении ссылки меню подчёркиваются, а все ссылки, включая оглавление и адрес в подвале, темнеют. Щёлкните в результат и переходите клавишей Tab: вокруг каждой ссылки, поля формы и кнопки видна синяя рамка, у ссылок меню появляется подчёркивание. Объясните, почему правило a:hover меняет цвет ссылок меню, хотя правило nav a с цветом saddlebrown тоже их выбирает.

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

css/style.css
CSS
/* Общие стили сайта Тони */
body {
  background-color: linen;
  color: #2b211b; /* цвет для потомков без собственного значения */
}

/* Общий цвет заголовков — групповой селектор */
h1,
h2 {
  color: saddlebrown;
}

h1 {
  text-align: center;
}

/* Вводный блок главной страницы */
.intro {
  background-color: hsl(30, 80%, 95%);
}

/* Оглавление главной страницы */
.toc {
  background-color: white;
  border: 1px solid tan;
}

/* Ссылки меню в шапке — селектор потомков */
nav a {
  color: saddlebrown;
  text-decoration: none;
}

/* Ссылки оглавления главной страницы */
.toc a {
  color: dimgray;
}

figcaption {
  color: dimgray;
}

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

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

/* Поля формы получают шрифт страницы вместо шрифта браузера */
input,
select,
textarea,
button {
  font: inherit;
}
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>
        <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>
        <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>
      </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><br>
            <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>
          <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>
          </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, сохраните файл и пройдите все страницы сайта мышью и клавишей Tab. Если результат отличается, нажмите в редакторе «Показать решение» и сравните его со своим кодом.

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

На странице Red, Green and Blue у ссылок и абзацев уже есть классы red, green и blue. Оформите страницу:

  1. Ссылки по умолчанию имеют чёрный цвет текста.
  2. При наведении на ссылку цвет её текста соответствует названию (red, green или blue).
  3. При выделении текста ссылки цвет фона соответствует её названию.
  4. Первая буква каждого абзаца — цвета темы абзаца.
  5. При выделении текста абзаца цвет фона соответствует цвету первой буквы. Задайте также контрастный цвет выделенного текста: чёрный на красном фоне, белый на зелёном и синем.
  6. Пока на абзаце удерживается кнопка мыши, цвет его текста соответствует теме абзаца.
  7. Продвинутое задание: пока на абзаце удерживается кнопка мыши, первая буква — чёрная.
  8. Продвинутое задание: сократите код групповыми селекторами, которые задают один и тот же цвет в разных состояниях элементов.

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

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

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Red, Green and Blue page</title>
    <style>
      /* Напишите стили здесь */
    </style>
  </head>
  <body>
    <h1>Red, Green and Blue page</h1>
    <p><a href="#red" class="red">Red</a>, <a href="#green" class="green">Green</a> and <a href="#blue" class="blue">Blue</a></p>
    <p class="red" id="red">Красный (родственно ст.-слав. красьнъ красивый, прекрасный), также червлёный, рдяный (арх.) — область цветов в длинноволновой части видимого спектра, соответствует минимальным частотам электромагнитного излучения, воспринимаемого человеческим глазом. Диапазон красных цветов в спектре часто определяют длинами волн 620—740 нанометров, что соответствует частотам 484—405 терагерц. Длинноволновая граница восприятия зависит от возраста человека.</p>
    <p class="green" id="green">Зелёный цвет — один из трёх основных цветов, зелёным считают цвет видимого электромагнитного излучения (света) с длинами волн, лежащими в диапазоне приблизительно 500—560 нанометров. В системе CMYK в полиграфии зелёный получается при смешении жёлтого и сине-зелёного (циана).</p>
    <p class="blue" id="blue">Синий — наименование группы цветов. Спектральный синий цвет ощущается человеком под действием электромагнитного излучения с длинами волн в диапазоне 440—485 нм (иногда диапазон указывают шире — 420—490 нм).</p>
  </body>
</html>