Как сверстать шапку сайта

Эта статья основана на одном из практических заданий verstaem.online.

Вы можете читать материал как обычное руководство или сначала попробовать выполнить задание самостоятельно, а затем сравнить свое решение с подробным разбором.

Перейти к заданию

В этой статье мы создадим классическую шапку сайта с логотипом, навигацией, поиском и кнопкой действия. На ее примере разберем, как выстраивать элементы в одну линию с помощью Flexbox, создавать переиспользуемый контейнер, оформлять навигацию и работать с SVG-иконками через CSS.

Создаем HTML-разметку

Сначала создадим базовую HTML-разметку с помощью Emmet. Для этого достаточно ввести ! и нажать Tab. Обратите внимание на атрибут lang. Поскольку основной контент страницы написан на русском языке, здесь используем значение ru.

<!doctype html>
<html lang="ru">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Шапка сайта</title>
  </head>
  <body>
  </body>
</html>

И конечно, для шапки мы будем использовать специальный тег — <header>. Внутри шапки разместим контейнер — блок, который выровняет контент сайта по центру.

<header class="header">
    <div class="container header__container">

    </div>
</header>

Далее размечаем внутренние элементы. Логотип — ссылкой. Вообще, если сайт у вас одностраничный, делать логотип ссылкой не нужно. Он будет вести якобы на главную, но вы и так на ней. Но для примера добавим ссылку.

После этого делаем меню с помощью навигации и списка — так будет верно с точки зрения семантики, и так скринридер озвучит и то, что это навигация, и то, что в списке определенное количество элементов. Справа же будет блок с двумя кнопками.

<header class="header">
  <div class="container header__container">
    <a href="#" class="header__logo">DevPath</a>
    <nav class="nav">
      <ul class="nav__list">
        <li class="nav__item">
          <a href="#" class="nav__link">Главная</a>
        </li>
        <li class="nav__item">
          <a href="#" class="nav__link">Задания</a>
        </li>
        <li class="nav__item">
          <a href="#" class="nav__link">Статьи</a>
        </li>
        <li class="nav__item">
          <a href="#" class="nav__link">Прогресс</a>
        </li>
      </ul>
    </nav>
    <div class="header__btns">
      <button class="header__search" aria-label="Открыть поиск">
        <svg
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
        >
          <path
            d="M21 21L16.66 16.66"
            stroke-width="2"
            stroke-linecap="round"
            stroke-linejoin="round"
          />
          <path
            d="M11 19C15.4183 19 19 15.4183 19 11C19 6.58172 15.4183 3 11 3C6.58172 3 3 6.58172 3 11C3 15.4183 6.58172 19 11 19Z"
            stroke-width="2"
            stroke-linecap="round"
            stroke-linejoin="round"
          />
        </svg>
      </button>
      <button class="header__start">Начать обучение</button>
    </div>
  </div>
</header>

Обратите внимание, что кнопка с иконкой поиска имеет атрибут aria-label. Он нужен для доступности, чтобы элемент имел описание, если в нем нет текста.

Добавляем стили

Подключим файл стилей через <link> и зададим несколько базовых правил. Для этого задания достаточно переопределить box-sizing, сбросить отступ у <body> и подключить шрифт Inter, который используется в макете.

* {
  box-sizing: border-box;
}

@font-face {
  font-family: "Inter";
  src: url("../fonts/InterRegular.woff2");
  font-display: swap;
  font-weight: 400;
}

@font-face {
  font-family: "Inter";
  src: url("../fonts/InterMedium.woff2");
  font-display: swap;
  font-weight: 500;
}

@font-face {
  font-family: "Inter";
  src: url("../fonts/InterBold.woff2");
  font-display: swap;
  font-weight: 700;
}

body {
  margin: 0;
  font-family: "Inter", sans-serif;
}

Шрифт подключаем, используя одно и то же название семейства, а вот отличие между ними реализуется через font-weight.

Отдельное внимание уделим контейнеру. Это блок, который удерживает контент сайта по центру, оставляя слева и справа лишь пустые поля. Контейнер у нас на сайте шириной 1680px, но делать контейнер без отступов по краям — ошибка, так как при сжатии экрана контент прилипнет к краям. Поэтому мы добавляем отступы по 10px, а затем компенсируем их размер в максимальной ширине. Получается 1680+10+10=1700.

.container {
  margin: 0 auto;
  padding: 0 10px;
  max-width: 1700px;
}

Далее нам стоит поработать с шапкой, а также с дополнительными стилями контейнера. Шапке зададим отступы сверху и снизу, а контейнеру через дополнительный класс добавим flexbox, чтобы легко ровнять элементы внутри. Именно justify-content: space-between позволит нам «растащить» элементы по шапке.

.header {
 padding: 20px 0;
}

.header__container {
 display: flex;
 align-items: center;
 justify-content: space-between;
}

Дальше добавим стили для внутренностей. Это и стили текста для лого, и flexbox для списка меню, и flexbox для кнопок.

.header__logo {
 font-weight: 700;
 font-size: 24px;
 text-decoration: none;
 color: #0f172a;
}

.nav__list {
 margin: 0;
 padding: 0;
 list-style: none;
 display: flex;
 align-items: center;
 gap: 32px;
}

.nav__link {
 font-weight: 400;
 font-size: 16px;
 color: #64748b;
 text-decoration: none;
 transition: color 0.3s;
}

.nav__link:hover {
 color: #404a58;
}

.header__btns {
 display: flex;
 align-items: center;
 gap: 20px;
}

И последнее, что стоит сделать, это стили для кнопок + их состояние :hover. Несмотря на то, что в макете состояния нет, я его добавляю сам. И советую вам на будущее делать также, даже если дизайнер забыл.

.header__search {
 display: block;
 border: none;
 padding: 0;
 width: 24px;
 height: 24px;
 color: #0f172a;
 background: transparent;
 cursor: pointer;
 transition: color 0.3s;
}

.header__search svg {
 stroke: currentColor;
}

.header__search:hover {
 color: #243662;
}

.header__start {
 display: inline-flex;
 align-items: center;
 justify-content: center;
 border: none;
 border-radius: 16px;
 padding: 16px 20px;
 font-family: inherit;
 font-weight: 500;
 font-size: 16px;
 color: #fff;
 background: #0f172a;
 cursor: pointer;
 transition: background 0.3s;
}

.header__start:hover {
 background: #243662;
}

Здесь, в реализации кнопки поиска, я использую фишку с currentColor. Я задаю кнопке цвет текста (даже если у нее нет текста), а затем меняю stroke у иконки на currentColor, то есть на этот самый цвет. Таким образом, если я захочу поменять цвет иконки, мне надо будет поменять цвет текста в кнопке. Это будет отлично работать также, если в этой кнопке когда-то появится текст. И важно: у самого svg-кода иконки убраны все атрибуты stroke, иначе такая реализация не сработает.

Теперь вы умеете создавать шапку сайта с логотипом, навигацией, поиском и кнопкой действия. Заодно мы разобрали Flexbox, контейнеры, списки для меню, работу с SVG-иконками, наследование цвета через currentColor и построение переиспользуемой структуры сайта.

Решение задачи

предыдущий пост следующий пост