Работа со шрифтами в CSS. Часть 2: веб-шрифты

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

В первой части мы выбрали для сайта Тони шрифты, которые уже есть на устройствах посетителей. У заголовков пока запасной шрифт без своего характера. В этом уроке подключим к ним округлый шрифт Nunito из файлов сайта.

Веб-шрифты

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

Форматы файлов шрифтов

  • WOFF2 (англ. Web Open Font Format 2) — основной формат для сайтов. Файл сжат лучше всех остальных и поэтому быстрее загружается. Поддерживается всеми современными браузерами.
  • WOFF (Web Open Font Format) — предыдущая версия формата со сжатием похуже. Нужен только для очень старых браузеров.
  • TTF/OTF (TrueType и OpenType Fonts) — форматы шрифтов для установки в операционную систему, разработанные Apple, Microsoft и Adobe. Браузеры их понимают, но файлы без сжатия больше. В этих форматах шрифты обычно и скачивают с сервисов шрифтов.
  • EOT (Embedded OpenType) — формат Microsoft, который понимал только Internet Explorer. Сейчас не нужен.
  • SVG-шрифты поддерживали некоторые старые браузеры, современные браузеры от них отказались. Это не то же самое, что SVG-глифы внутри OpenType-шрифтов.

Для собственного сайта достаточно WOFF2. Если у вас файл в TTF, его можно перевести в WOFF2 конвертером. Если шрифт уже доступен в WOFF2, скачайте готовый файл.

Лицензии и поиск шрифтов

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

Подключение шрифта правилом @font-face

Чтобы подключить веб-шрифт из своих файлов, нужно:

  • объявить шрифт правилом @font-face: указать имя шрифта и откуда загрузить файл. Правила @font-face принято размещать в начале таблицы стилей: так их проще найти;
  • указать это имя в свойстве font-family нужных элементов — так же, как имя установленного шрифта.

Подключим шрифт Nunito, который выберем для заголовков сайта Тони. Он распространяется по лицензии OFL (англ. SIL Open Font License — открытая лицензия на шрифты SIL); файл содержит кириллицу и полужирное начертание с насыщенностью 800:

Правило @font-face: попробуйте сами

Первый заголовок показан шрифтом Nunito из файла примера, второй — запасным шрифтом. Измените имя файла в url() на несуществующее — первый заголовок тоже получит запасной шрифт.

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Правило @font-face: свой шрифт</title>
    <style>
      /* Объявляем шрифт: имя для font-family, файл и насыщенность, которую он содержит */
      @font-face {
        font-family: "Nunito";
        src: url("assets/nunito-cyrillic-800-normal.woff2") format("woff2");
        font-weight: 800;
        font-display: swap;
      }
      h2 {
        font-weight: 800;
      }
      .nunito {
        font-family: "Nunito", "Trebuchet MS", sans-serif; /* свой шрифт и запасные */
      }
      .fallback {
        font-family: "Trebuchet MS", sans-serif; /* для сравнения — только запасные */
      }
    </style>
  </head>
  <body>
    <h2 class="nunito">Привет! Меня зовут Тони</h2>
    <h2 class="fallback">Привет! Меня зовут Тони</h2>
  </body>
</html>

В правиле @font-face мы указали:

  • font-family — имя, под которым шрифт будет доступен в стилях. Его задаёте вы: например, "Nunito" или "Tony Heading", независимо от имени файла и названия внутри шрифта. Для понятности лучше сохранить название шрифта. Имя удобно записывать в кавычках; затем используйте его в свойстве font-family у нужных элементов;
  • src — путь к файлу в функции url() и его формат в format(). Формат подсказывает браузеру, сможет ли он прочитать файл, ещё до загрузки. Путь считается от файла, в котором записано правило: из css/style.css к папке assets — ../assets/…;
  • font-weight и font-style — какую насыщенность и начертание содержит файл. По умолчанию normal;
  • font-display: swap — пока шрифт загружается, текст показан запасным шрифтом, а затем заменяется. Без этого браузер может некоторое время не показывать текст совсем.

Один файл — одно начертание

Статический файл шрифта содержит одну насыщенность и одно начертание. Например, статический набор Roboto может состоять из отдельных файлов Roboto-Regular, Roboto-Bold, Roboto-Italic, Roboto-BoldItalic и другие. Если на странице нужны обычный, полужирный и курсив, каждый подключается своим правилом @font-face с тем же именем, но с разными font-weight и font-style:

CSS
@font-face {
  font-family: "Roboto"; /* одно имя для всех начертаний */
  src: url("../fonts/Roboto-Regular.woff2") format("woff2");
  font-weight: 400; /* обычная насыщенность */
  font-style: normal;
}
@font-face {
  font-family: "Roboto";
  src: url("../fonts/Roboto-Bold.woff2") format("woff2");
  font-weight: 700; /* полужирный — отдельный файл */
  font-style: normal;
}
@font-face {
  font-family: "Roboto";
  src: url("../fonts/Roboto-Italic.woff2") format("woff2");
  font-weight: 400;
  font-style: italic; /* курсив — ещё один файл */
}
h2,
p,
b,
i {
  font-family: "Roboto", sans-serif; /* если шрифт не загрузится — любой шрифт без засечек */
}

Теперь браузер сам выберет файл: для <b> и заголовков (у них полужирное начертание из стилей браузера) — Roboto-Bold, для <i> — Roboto-Italic, для обычного текста — Roboto-Regular. Файл загружается, только если на странице есть текст с этим начертанием.

Если начертания хранятся в отдельных файлах, каждое использованное на странице начертание требует загрузки своего файла. Поэтому при оформлении страницы старайтесь обходиться небольшим набором начертаний — это уменьшает объём загружаемых шрифтов. Само объявление неиспользуемого начертания в @font-face загрузку не вызывает.

Вариативные шрифты: несколько начертаний в одном файле

Вариативный шрифт (англ. variable font) позволяет менять параметры букв в пределах диапазона, заложенного автором шрифта. Например, один файл может содержать насыщенности от 100 до 900. Тогда для обычного текста и жирных заголовков не нужны отдельные файлы; можно выбрать и промежуточную насыщенность, например font-weight: 550.

Подключают такой файл тем же правилом @font-face, но в font-weight указывают диапазон, например font-weight: 100 900. У элементов задают нужное значение: 400 для основного текста, 700 для заголовков. Браузер использует один файл для обеих насыщенностей. Диапазон нужно брать из описания выбранного шрифта: запись 100 900 сама по себе не превращает статический файл в вариативный.

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

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

Несколько файлов и наборов символов

В src можно перечислить несколько файлов через запятую — браузер возьмёт первый, который сможет прочитать. Порядок важен: первым указывают предпочтительный формат.

CSS
@font-face {
  font-family: "Roboto";
  src:
    url("../fonts/Roboto-Regular.woff2") format("woff2"),
    url("../fonts/Roboto-Regular.woff") format("woff"); /* запасной файл для очень старых браузеров */
}

Перед адресами файлов можно указать функцию local("Roboto"): браузер сначала поищет шрифт среди установленных на устройстве. Недостаток этого способа — зависимость от установленной версии: она может отличаться от файла на сайте по форме и ширине символов. Из-за этого у посетителей могут различаться внешний вид текста и переносы строк. Если важно использовать именно подготовленный вами файл, укажите его адрес без local().

Свойство unicode-range указывает, для каких символов предназначен файл. Сервисы шрифтов делят шрифт на части по алфавитам: латиница в одном файле, кириллица в другом. Браузер загружает только ту часть, символы которой есть на странице. Так подключим и шрифт заголовков Тони: два правила с одним именем "Nunito", у каждого свой файл и свой unicode-range. Значения диапазонов в задании мы возьмём готовыми: это номера символов кириллицы и латиницы в Юникоде.

Подключение шрифта со стороннего сервиса

Шрифт можно не скачивать, а подключить прямо с сервера службы шрифтов. Рассмотрим это на примере Google Fonts. Шаги описаны для интерфейса сервиса на момент написания урока; названия кнопок со временем могут меняться.

  1. Откройте сайт Google Fonts и найдите шрифт по названию, например Roboto. Чтобы видеть только шрифты с кириллицей, выберите в фильтре языка «Кириллица» (Cyrillic).
  2. Откройте страницу шрифта и нажмите «Get font», затем «Get embed code».
  3. Выберите нужные начертания: например, Regular 400, Bold 700 и Italic 400.
  4. Оставьте способ подключения <link> и скопируйте код из блока для веб-страниц. В нём — три элемента <link> и правило с font-family.

Подключение элементом <link>. Код вставляется в <head> каждой страницы, где нужен шрифт, перед подключением собственной таблицы стилей:

HTML
<head>
  <meta charset="utf-8">
  <title>Подключение шрифта с Google Fonts</title>
  <!-- заранее устанавливаем соединение с серверами шрифтов -->
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <!-- таблица стилей сервиса с правилами @font-face для выбранных начертаний -->
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,700;1,400&display=swap">
  <link rel="stylesheet" href="css/style.css">
</head>
CSS
/* css/style.css */
h2,
p,
b,
i {
  font-family: "Roboto", sans-serif;
}

В адресе таблицы стилей перечислены название шрифта (family=Roboto), начертания (ital,wght@… — пары «курсив или нет, насыщенность») и display=swap. Это обычная внешняя таблица стилей, как в уроке «Создание первой таблицы стилей»: внутри неё — правила @font-face со ссылками на файлы в формате WOFF2, разделённые по наборам символов через unicode-range. Сервис сам выбирает подходящий браузеру формат.

Подключение правилом @import. Ту же таблицу стилей можно подключить в начале своего CSS-файла правилом @import. Тогда не нужно добавлять код на каждую страницу — достаточно файла стилей, который уже подключён ко всем:

CSS
@import url("https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,700;1,400&display=swap");

h2,
p,
b,
i {
  font-family: "Roboto", sans-serif;
}

Правило @import должно стоять в начале таблицы стилей, перед остальными правилами (раньше него допускаются только @charset — указание кодировки CSS-файла, например @charset "UTF-8";, — и объявления порядка слоёв вроде @layer base, theme;, но не блоки @layer { … }), иначе браузер его пропустит.

Использовать @import для шрифтов я не рекомендую: браузер узнаёт о таблице шрифтов, только когда загрузит и прочитает ваш CSS-файл, и загрузка выстраивается в цепочку. Страница показывается позже, чем с <link>, — об этом предупреждают и рекомендации по скорости загрузки Lighthouse.

Шрифт в инструментах разработчика

Каким шрифтом на самом деле показан текст, можно проверить в инструментах разработчика браузера. Например, в Google Chrome выберите элемент на вкладке Elements, откройте вкладку Computed и прокрутите её вниз до раздела «Rendered Fonts»: там указан шрифт, которым браузер нарисовал текст, и сколько символов показано каждым шрифтом. Если там запасной шрифт, проверьте на вкладке Network, загрузился ли файл шрифта, и путь в url().

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

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

1. В каком формате файлы шрифтов лучше всего подключать на сайт?
Показать ответ

WOFF2 — WOFF2 сжат лучше остальных форматов и поддерживается всеми современными браузерами.

2. На странице нужны обычный текст и полужирный шрифта Roboto. Сколько правил @font-face понадобится, если у каждого начертания свой файл?
Показать ответ

Два: с одним именем "Roboto" и разными font-weight — Каждый файл подключается своим правилом. По font-weight браузер сам выберет файл для обычного и полужирного текста.

3. Правило @font-face записано в css/style.css, файл шрифта лежит в assets/nunito.woff2 в корне сайта. Какой путь указать в url()?
Показать ответ

../assets/nunito.woff2 — Путь в url() считается от CSS-файла: из папки css поднимаемся на уровень выше и заходим в assets.

4. Что делает font-display: swap в правиле @font-face?
Показать ответ

Пока шрифт загружается, текст показан запасным шрифтом, а затем заменяется — Так текст виден сразу. Без этого браузер может некоторое время не показывать текст совсем.

5. Почему для подключения шрифтов не рекомендуется правило @import?
Показать ответ

Браузер узнаёт о таблице шрифтов только после загрузки вашего CSS-файла, и страница показывается позже — Загрузки выстраиваются в цепочку: сначала ваш файл, потом импортированная таблица, потом шрифты. Элемент <link> в <head> браузер видит сразу.

6. Шрифт подключён двумя правилами @font-face с одним именем: в одном файле кириллица, в другом латиница, у каждого свой unicode-range. Этим шрифтом оформлено только слово «Привет» без пробелов и знаков препинания. Все его буквы входят только в кириллический диапазон. Какой файл потребуется браузеру при первой загрузке без кэша?
Показать ответ

Только файл с кириллицей — unicode-range сообщает, для каких символов файл. В слове «Привет» все буквы входят в кириллический диапазон. Для фразы с пробелами и знаками препинания может понадобиться и латинский файл: важны диапазоны символов, а не язык текста.

7. Заголовок выглядит запасным шрифтом, хотя правило @font-face записано. Где в Google Chrome посмотреть, каким шрифтом браузер на самом деле нарисовал текст?
Показать ответ

На вкладке Computed выбранного элемента, в разделе «Rendered Fonts» — «Rendered Fonts» показывает шрифт, которым нарисован текст. Если там запасной шрифт, проверьте на вкладке Network загрузку файла и путь в url().

Задание

Ожидаемый результат: заголовки на всех страницах — округлым жирным шрифтом Nunito; основной текст и цитата не изменились. Проверьте на вкладке Computed в разделе «Rendered Fonts», что заголовок нарисован шрифтом Nunito, а не запасным.

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

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


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

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

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

h2 {
  font-size: 1.75rem;
}

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

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

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

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

/* Ссылки оглавления главной страницы */
.toc a {
  color: #6b5d52; /* тёплый серый: контраст 6.34:1 на белом фоне оглавления */
}

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

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

/* Ссылка в подвале берёт цвет текста подвала */
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;
}
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

Нажмите «Скачать ZIP» в редакторе выше и возьмите из архива папку assets с файлами шрифта: скопируйте оба файла .woff2 в папку assets своего сайта my-site. Добавьте правила @font-face и "Nunito" в списке заголовков в свой css/style.css, сохраните файл и откройте сайт в браузере. Проверка: заголовки показаны шрифтом Nunito на всех четырёх страницах. Если результат отличается, нажмите в редакторе «Показать решение» и сравните его со своим кодом.

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

Обе задачи выполняются в VS Code: нужны файлы с Google Fonts и подключение к интернету. Скачайте страницу задачи кнопкой «Скачать HTML» и откройте её в VS Code.

Задача 1. Скачайте с Google Fonts шрифты Roboto для заголовка и Open Sans для остального текста (кнопка «Download all» в подборке шрифтов). Распакуйте архивы и скопируйте в папку fonts рядом со страницей вариативные файлы Roboto[wdth,wght].ttf, OpenSans[wdth,wght].ttf и OpenSans-Italic[wdth,wght].ttf. Сверьте имена со скачанными файлами: они могут измениться. Часть имени [wdth,wght] обозначает оси вариации: wdth (англ. width — ширина) и wght (англ. weight — насыщенность). Это часть имени файла, а не специальная запись CSS: в url() указывайте точное имя вместе со скобками. Если переименуете файл, измените и путь к нему. Подключите их тремя правилами @font-face: у Roboto задайте диапазон font-weight: 100 900, у обоих файлов Open Sans — 300 800, а у курсивного — font-style: italic. Обычное и полужирное начертания Open Sans теперь берутся из одного файла.

Ожидаемый результат: заголовок «Бурый медведь» — шрифтом Roboto, абзацы — шрифтом Open Sans, причём выделения <b> показаны настоящим полужирным Open Sans, а <i> — курсивом Open Sans. На вкладке Network видны загрузки трёх файлов. Решение показывает подключение вариативных шрифтов; если имена в вашем архиве отличаются, исправьте пути в url().

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

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Дополнительное задание</title>
    <style>

    </style>
  </head>
  <body>
    <h2>Бурый медведь</h2>
    <p><b>Бурый медведь</b>, или <b>обыкновенный медведь</b> (лат. <i>Ursus arctos</i>) — хищное млекопитающее семейства медвежьих; один из самых крупных наземных хищников.</p>
    <p>Некогда <b>бурый медведь</b> был обычен по всей Европе, включая <i>Англию</i> и <i>Ирландию</i>, на юге его ареал достигал северо-запада <i>Африки</i> (<b>Атласский медведь</b>), а на востоке через <i>Сибирь</i> и <i>Китай</i> доходил до <i>Японии</i>. В <i>Северную Америку</i> он, вероятно, попал около <b>40 000 лет</b> назад из <i>Азии</i>, через Берингов перешеек, и широко расселился в западной части континента от <b>Аляски</b> и до севера <b>Мексики</b>.</p>
  </body>
</html>

Задача 2. Найдите на Google Fonts шрифт Ubuntu, выберите обычное, полужирное и курсивное начертания и подключите его элементом <link>. Задайте шрифт всему тексту страницы.

Ожидаемый результат: весь текст страницы об омарах, включая выделения, показан шрифтом Ubuntu. Если в результате обычный шрифт без засечек — проверьте адрес в <link> и подключение к интернету.

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

index.html
HTML
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Дополнительное задание</title>
    <style>

    </style>
  </head>
  <body>
    <h2>Омары</h2>
    <p><b>Омары</b> (лат. <i>Nephropidae</i>) — семейство крупных морских <i>десятиногих ракообразных</i>.</p>
    <p>В просторечии, в отношении употребляемых в пищу <b>омаров</b> и <b>лангустов</b> также употребляется калька <b>«лобстеры»</b> (от англ. <i>lobsters</i> — <b>омары</b>).</p>
  </body>
</html>