Каскадность в CSS
Чтение — около 12 минут· без учёта практики
В предыдущем уроке мы увидели, что
ссылка не стала зелёной вместе с <body>: правило браузера оказалось сильнее унаследованного
значения. Теперь разберём, как браузер выбирает значение, когда к одному элементу относится несколько правил.
Каскад — алгоритм, по которому браузер определяет итоговое значение каждого свойства элемента: собирает все подходящие объявления из всех источников и, если они конфликтуют, выбирает одно. Поэтому таблицы стилей и называют каскадными (англ. Cascading Style Sheets).
Источники стилей
Стили, которые образуют каскад, приходят из трёх источников:
- Стили браузера по умолчанию (user agent stylesheet).
- Стили автора документа — разработчика страницы. Их можно указать в трёх местах:
- Стили пользователя. В некоторых браузерах свои стили для сайтов можно задать в настройках, в других для этого нужно расширение. Так пользователь может, например, увеличить шрифт или скрыть блоки, которые не хочет видеть.
Если к элементу относится несколько правил и они не конфликтуют — задают разные свойства, — браузер объединяет их. Рассмотрим абзац со ссылкой и три правила для неё:
Объединение правил: попробуйте сами
Ссылка получила цвет от a, жирное начертание от p a, фон и отсутствие подчёркивания от .main a. Цвет и подчёркивание из стилей браузера заменены авторскими значениями.
index.html
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Объединение правил</title>
<style>
a {
/* селектор типа */
color: brown; /* цвет текста */
}
p a {
/* селектор потомков */
font-weight: bold; /* жирное начертание */
}
.main a {
/* селектор потомков с классом */
background-color: orange; /* цвет фона */
text-decoration: none; /* убираем подчёркивание */
}
</style>
</head>
<body>
<p class="main">Все мои игрушки — на странице <a href="#toys">«Мои игрушки»</a>.</p>
</body>
</html>
Откройте инструменты разработчика на ссылке: на вкладке Styles все три авторских правила применились, а в правиле браузера для ссылок перечёркнуты цвет и подчёркивание. Авторские стили оказались сильнее стилей браузера. А как браузер поступит, если сами авторские правила задают одному свойству разные значения?
Конфликт значений
Зададим ссылке разные семейства шрифта свойством
font-family
во всех трёх правилах:
Конфликт значений: попробуйте сами
Ссылка получила моноширинный шрифт из правила .main a: его специфичность выше, чем у a и p a. Перенесите это правило в начало — результат сохранится. Затем удалите .main из его селектора: победит p a со шрифтом Georgia.
index.html
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Конфликт значений font-family</title>
<style>
a {
/* селектор типа */
color: brown; /* цвет текста */
font-family: Arial, sans-serif; /* шрифт Arial */
}
p a {
/* селектор потомков */
font-weight: bold; /* жирное начертание */
font-family: Georgia, serif; /* шрифт Georgia */
}
.main a {
/* селектор потомков с классом */
background-color: orange; /* цвет фона */
text-decoration: none; /* убираем подчёркивание */
font-family: "Courier New", monospace; /* шрифт Courier New */
}
</style>
</head>
<body>
<p class="main">Все мои игрушки — на странице <a href="#toys">«Мои игрушки»</a>.</p>
</body>
</html>
На вкладке Styles объявления font-family в правилах a и p a перечёркнуты.
Победило правило с более точным селектором .main a. Чтобы понять, почему, разберём, в каком порядке
браузер сравнивает конфликтующие объявления.
Как браузер выбирает победителя
Браузер сравнивает объявления одного свойства по этапам. Если на этапе одно объявление сильнее, оно побеждает, и
следующие этапы не рассматриваются. Ниже — упрощённая схема без учёта анимаций,
переходов и областей @scope (это правило ограничивает действие стилей частью документа, с ним мы ещё не знакомились).
Сначала браузер отбирает подходящие правила: селектор должен
выбирать элемент, а условия правила, если они есть, — выполняться. Затем сравнивает объявления:
- Происхождение и важность: стили браузера, пользователя или автора; обычное объявление или
!important. - Атрибут
style: при одинаковой важности объявление внутри элемента сильнее объявлений в таблицах стилей автора. -
Каскадные слои — группы стилей, которые создают с помощью правила
@layer, чтобы задать приоритет между этими группами. Для обычных объявлений более поздний слой сильнее, а объявления вне слоёв сильнее объявлений в слоях. Для!importantпорядок обратный. Мы ещё не использовали слои, поэтому пока достаточно знать, что браузер учитывает их перед специфичностью. Дополнительно познакомимся с ними ниже, а подробно разберём в уроке «Организация CSS». - Специфичность селектора: более точный селектор сильнее.
- Порядок: при прочих равных побеждает объявление, которое встретилось позже.
В полном каскаде есть дополнительные этапы: анимации сильнее обычных объявлений, но слабее важных,
а значение действующего перехода сильнее даже !important. При использовании @scope
после специфичности сравнивается близость корня области к элементу и только затем порядок объявлений.
Анимации и переходы рассмотрим в соответствующих уроках. @scope — дополнительная тема
за пределами основного курса; для следующих заданий она не нужна.
Каскад сравнивает только объявления, которые относятся к самому элементу. Унаследованное значение в нём не участвует:
для наследуемого свойства оно используется по умолчанию, если каскад не дал собственного значения.
Наследование также можно явно запросить значением inherit (с ним вы познакомились в
предыдущем уроке). Поэтому правило
h2 побеждает цвет, унаследованный от #page, хотя у селектора по идентификатору специфичность
выше.
Происхождение и !important
Для обычных объявлений самые слабые — стили браузера, затем стили пользователя, самые сильные — стили автора. Поэтому в примере выше авторский цвет ссылки заменил синий цвет браузера.
Ключевое слово !important в конце объявления делает его важным. Важные объявления сильнее
обычных из любого источника, а порядок источников для них обратный: важные стили пользователя сильнее важных стилей
автора, а важные стили браузера сильнее обоих. Так пользователь, которому нужен крупный шрифт или контрастные цвета,
может переопределить оформление сайта.
a {
color: red !important; /* важное объявление */
}
Объявление !important: попробуйте сами
Без !important ссылка была бы зелёной: селектор a.toys точнее, чем a. Удалите !important и сравните результат.
index.html
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Объявление !important</title>
<style>
a.toys {
/* тип и класс: (0, 1, 1) */
color: green;
}
a {
/* тип: (0, 0, 1) */
color: red !important; /* важное объявление */
}
</style>
</head>
<body>
<p><a class="toys" href="#toys">Мои игрушки</a></p>
</body>
</html>
!important не отменяет каскад, а переносит объявление в более сильную группу. Перебить такое объявление
в рассматриваемых здесь статических правилах можно другим важным объявлением. Например, если цвет кнопки задан
с !important, обычное правило для изменения цвета при наведении его не переопределит.
Возникает соблазн добавить ещё один !important, затем следующий. В результате становится труднее
понять, какое правило управляет оформлением, и менять стили компонентов.
Атрибут style
Обычные объявления в атрибуте style сильнее обычных объявлений из
таблиц стилей автора, какой бы ни была специфичность селекторов: каскад отдельно учитывает этот способ задания стилей.
Объявления из подходящих правил таблицы стилей тоже относятся к самому элементу. Важное объявление из таблицы стилей сильнее
обычного объявления в style.
На вкладке Styles такие объявления показаны в разделе element.style в самом верху. Мы перенесли стили
сайта Тони из атрибутов style в файл в уроке
«Создание первой таблицы стилей»:
забытый атрибут style перебивает правила файла и мешает менять оформление в одном месте.
Если задавать всё оформление через атрибут style, возникают трудности:
- Одинаковые объявления приходится повторять у разных элементов. Чтобы изменить оформление всех карточек или кнопок, нужно исправлять каждый такой атрибут.
- Обычные правила в CSS-файле не могут переопределить эти объявления. Это мешает менять оформление и подталкивает к лишнему использованию
!important. - Внутри атрибута нельзя записать отдельные правила для наведения, фокуса или разной ширины экрана. Для них нужна таблица стилей, причём объявления в
styleмогут мешать этим правилам применяться. - Длинные атрибуты смешивают оформление с HTML-разметкой и затрудняют её чтение.
Каскадные слои: дополнительное знакомство
Правило @layer объединяет стили в группы — слои. Их приоритет браузер учитывает перед
специфичностью селекторов. Для обычных объявлений более поздний слой сильнее раннего, а объявления вне слоёв
сильнее объявлений в слоях. Для !important порядок обратный.
Сейчас достаточно знать о существовании этого этапа каскада. На сайте Тони мы пока не используем слои, и добавлять их в небольшой проект необязательно. Подробно разберём синтаксис, примеры и применение слоёв в уроке «Организация CSS».
Специфичность
Специфичность — «вес» селектора, который показывает, насколько точно он выбирает элемент. Её записывают тремя числами (A, B, C):
- A — количество идентификаторов (
#toy); - B — количество классов (
.toc); - C — количество селекторов типа (
a).
Универсальный селектор * и комбинаторы (пробел, >, +, ~)
специфичность не меняют. Для группы селекторов через запятую специфичность считается отдельно для каждого селектора.
#toy a { } /* (1, 0, 1) — идентификатор и тип */
.toc a { } /* (0, 1, 1) — класс и тип */
nav ul a { } /* (0, 0, 3) — три типа */
.intro .toc a { } /* (0, 2, 1) — два класса и тип */
В следующих уроках появятся и другие селекторы, у них тоже есть место в этих столбцах. Псевдоклассы из
следующего урока считаются как классы,
псевдоэлементы — как типы, а селекторы атрибутов и псевдоклассы :is(), :where(),
:not() и :has() со своими правилами разберём в уроке
«Селекторы. Часть 3».
Специфичность сравнивают по столбцам слева направо. Сначала — число идентификаторов: у кого больше, тот и победил.
Если поровну — сравнивают классы, затем типы. Большое число в правом столбце не перевешивает единицу в левом:
селектор с одним идентификатором (1, 0, 0) сильнее селектора с одиннадцатью классами
(0, 11, 0).
Рассмотрим абзац, у которого есть класс и идентификатор, и три правила для него. Внутри абзаца — элемент
<span>
с атрибутом style:
Сравнение специфичности: попробуйте сами
Абзац красный: идентификатор (1, 0, 0) сильнее класса и типа. Фрагмент в span зелёный: атрибут style задан самому span, а остальное он только унаследовал бы. Удалите правило #warning — абзац станет синим.
index.html
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Сравнение специфичности</title>
<style>
#warning {
/* идентификатор: (1, 0, 0) */
color: red;
}
.note {
/* класс: (0, 1, 0) */
color: blue;
}
p {
/* тип: (0, 0, 1) */
color: green;
}
</style>
</head>
<body>
<p class="note" id="warning">Пожалуйста, <span style="color: green">не кормите</span> меня со стола!</p>
</body>
</html>
Специфичность любого селектора можно узнать в Google Chrome: на вкладке Styles наведите указатель на селектор правила — появится подсказка Specificity: (1,0,0).
Порядок правил
В нашей схеме, если у конфликтующих объявлений одинаковы источник, важность, слой и специфичность
и ни одно не имеет преимущества атрибута style, побеждает объявление, которое встретилось
позже: ниже в таблице стилей или в таблице, подключённой позже. Если поменять такие правила местами, победит другое.
Порядок правил: попробуйте сами
Оба правила — .toc a с одинаковой специфичностью, поэтому ссылки получили цвет из нижнего. Поменяйте правила местами и сравните.
index.html
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Порядок правил</title>
<style>
.toc a {
/* (0, 1, 1) */
color: dimgray;
}
.toc a {
/* снова (0, 1, 1), но правило ниже */
color: saddlebrown;
}
</style>
</head>
<body>
<ul class="toc">
<li><a href="#toy">Моя любимая игрушка</a></li>
<li><a href="#commands">Команды, которые я знаю</a></li>
</ul>
</body>
</html>
Порядок — самый слабый этап, и на него легко не обратить внимания: правило где-то в конце файла незаметно перебивает правило с тем же селектором выше. Старайтесь не задавать одному элементу одно свойство в нескольких правилах с равной специфичностью без необходимости. Такие ошибки быстро находятся на вкладке Styles: перечёркнутое объявление показывает, что победило другое правило.
Сброс и нормализация стилей браузера
Стили браузера немного различаются: в разных браузерах у заголовков, списков и полей формы бывают разные отступы, размеры и оформление. Чтобы получить общую основу оформления, можно использовать сброс или нормализацию стилей браузера. Это два подхода к подготовке базового оформления страницы.
Сброс убирает выбранные стили браузера, чтобы задать оформление самостоятельно. Например, можно обнулить отступы заголовков и абзацев, а затем установить свои. При более широком сбросе убирают также различия в размере шрифта, выделение заголовков жирным и маркеры списков. После этого нужное оформление придётся задать заново.
Нормализация сохраняет полезное оформление по умолчанию и точечно исправляет различия между браузерами. Например, заголовки сохраняют отличие от обычного текста, а списки — маркеры. Правила добавляют там, где нужно согласовать отображение элементов, например полей формы.
Эти подходы можно сочетать: сбросить отступы, которые мешают макету, и сохранить остальные полезные стили.
Для обоих подходов существуют готовые CSS-библиотеки — наборы правил, которые можно подключить к странице как обычную таблицу стилей. Они избавляют от необходимости писать все базовые правила самостоятельно. Обычно такой файл подключают перед собственными стилями сайта, чтобы затем задавать нужное оформление. Перед подключением стоит посмотреть, что именно меняет библиотека: разные наборы правил могут по-разному оформлять заголовки, списки и поля формы. Использовать библиотеку необязательно — можно самостоятельно написать только те правила, которые нужны вашему сайту.
Базовые правила тоже участвуют в каскаде. Чтобы их было удобно переопределять, используют невысокую специфичность или каскадный слой с меньшим приоритетом. Сам по себе порядок в файле не гарантирует, что правило ниже окажется сильнее.
Потренируйтесь
Определите, какое правило победит, и назовите этап каскада, который решил спор: порядок, специфичность, !important, атрибут style или слои. После верного ответа появится объяснение.
Проверьте себя
Выберите ответ — объяснение появится сразу. Ответ можно менять.
Задание
Ожидаемый результат: все заголовки на всех страницах цвета saddlebrown, главные заголовки по
центру, в pages/toys.html не осталось атрибута style. Для каждой из четырёх правок назовите
этап каскада, на котором побеждало лишнее объявление. Обратите внимание: после удаления !important один
заголовок всё ещё отличается от остальных — значит, у него был второй, более слабый конфликт.
Выполните задание
Условие задания
css/style.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;
}
/* Заголовки разделов */
h2 {
color: teal !important;
}
/* Заголовок любимой игрушки */
#toy {
color: tomato;
}
h1 {
text-align: left;
}
index.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 кг и люблю гулять в любую погоду. Хозяин говорит: <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="Мой канат "Удав"">
<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>© 2026 Тони и его хозяин</small></p>
<address>Написать хозяину Тони: <a href="mailto:tony@example.com">tony@example.com</a></address>
</footer>
</body>
</html>
pages/signup.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>© 2026 Тони и его хозяин</small></p>
<address>Написать хозяину Тони: <a href="mailto:tony@example.com">tony@example.com</a></address>
</footer>
</body>
</html>
pages/toys.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 style="color: green">Мои игрушки</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>© 2026 Тони и его хозяин</small></p>
<address>Написать хозяину Тони: <a href="mailto:tony@example.com">tony@example.com</a></address>
</footer>
</body>
</html>
pages/walks.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>
Если какой-то конфликт найти не получается, нажмите «Показать решение» и сравните файлы. Свой my-site в
этом уроке менять не нужно. В
следующем уроке мы вернёмся к нему и
оформим состояния ссылок: наведение и фокус.