Как сверстать карточки тарифов

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

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

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

В этой статье мы создадим блок с тарифными планами, состоящий из нескольких карточек с названием, ценой, описанием, списком возможностей и кнопкой действия. На его примере разберем, как создавать карточки одинаковой высоты, использовать Flexbox для построения вертикального интерфейса, оформлять различные состояния компонентов и применять модификаторы БЭМ.

Создаем 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>

Идем далее. Поскольку перед нами сразу несколько однотипных карточек, логично использовать обычный список <ul>. Каждая карточка станет отдельным элементом <li>, а внутри него разместим самостоятельный компонент — <article>.

<ul class="tariffs">
    <li class="tariffs__item">
        <article class="tariffs-card">

        </article>
    </li>
</ul>

Теперь можно переходить к содержимому карточки. Сверху разместим название тарифа, затем цену, описание и список возможностей. Для списка преимуществ отлично подходит обычный <ul>, как перечисление преимуществ тарифа. Последним элементом станет кнопка действия. После этого останется лишь продублировать карточку несколько раз и заменить текст. И еще помимо этого нужно добавить дополнительный класс, чтобы затем отдельно выделить среднюю карточку.

<ul class="tariffs">
  <li class="tariffs__item">
    <article class="tariffs-card">
      <h3 class="tariffs-card__title">Start</h3>
      <div class="tariffs-card__price">
        0 <span>₽ / месяц</span>
      </div>
      <p class="tariffs-card__descr">
        Для знакомства с платформой и первых практических заданий.
      </p>
      <ul class="tariffs-card__list">
        <li class="tariffs-card__item">
          Базовые задания
        </li>
        <li class="tariffs-card__item">
          Публичный профиль
        </li>
      </ul>
      <button class="tariffs-card__btn">
        Начать бесплатно
      </button>
    </article>
  </li>
  <li class="tariffs__item">
    <article class="tariffs-card tariffs-card--best">
      <h3 class="tariffs-card__title">Pro</h3>
      <div class="tariffs-card__price">
        990 <span>₽ / месяц</span>
      </div>
      <p class="tariffs-card__descr">
        Для полноценной практики, подробных разборов и постоянного развития навыков вёрстки.
      </p>
      <ul class="tariffs-card__list">
        <li class="tariffs-card__item">
          Все задания платформы
        </li>
        <li class="tariffs-card__item">
          Система достижений
        </li>
        <li class="tariffs-card__item">
          Подробные разборы решений
        </li>
        <li class="tariffs-card__item">
          Ранний доступ к новым заданиям
        </li>
      </ul>
      <button class="tariffs-card__btn">
        Выбрать тариф
      </button>
    </article>
  </li>
  <li class="tariffs__item">
    <article class="tariffs-card">
      <h3 class="tariffs-card__title">Team</h3>
      <div class="tariffs-card__price">
        2 490 <span>₽ / месяц</span>
      </div>
      <p class="tariffs-card__descr">
        Для совместной работы, командных проектов и общего отслеживания прогресса.
      </p>
      <ul class="tariffs-card__list">
        <li class="tariffs-card__item">
          Командные проекты
        </li>
        <li class="tariffs-card__item">
          Общий прогресс
        </li>
        <li class="tariffs-card__item">
          Совместные материалы
        </li>
      </ul>
      <button class="tariffs-card__btn">
        Связаться с нами
      </button>
    </article>
  </li>
</ul>

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

Подключим файл стилей через <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/InterBold.woff2");
  font-display: swap;
  font-weight: 700;
}

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

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

Далее работаем над списком и его элементами. Списку достаточно задать display: flex, а также gap, а карточкам — flex: 1. Благодаря этому все карточки автоматически поделят между собой доступную ширину и будут выглядеть одинаково аккуратно независимо от размера окна браузера.

.tariffs {
  display: flex;
  list-style: none;
  margin: 0 auto;
  padding: 20px;
  max-width: 1020px;
  gap: 20px;
}

.tariffs__item {
  flex: 1;
}

Теперь оформим саму карточку. Здесь снова нужен Flexbox, но направление вертикальное. Так все элементы будут располагаться сверху вниз, а мы сможем свободно управлять распределением пространства внутри карточки. Дополнительно добавим скругление, внутренние отступы и минимальную высоту. Именно min-height позволяет всем карточкам выглядеть одинаково даже несмотря на разное количество текста.

.tariffs-card {
  display: flex;
  flex-direction: column;
  border: 1px solid #f1e3d6;
  border-radius: 36px;
  padding: 24px;
  min-height: 550px;
  background: #fff;
}

Далее делаем цену. У цены есть два элемента с разным шрифтом и цветом. Поэтому одна часть и обернута в <span>. Здесь мы будем использовать align-items: flex-end, чтобы выронять элементы.

.tariffs-card__title {
  margin: 0;
  margin-bottom: 20px;
  font-weight: 800;
  font-size: 24px;
  color: #2a211c;
}

.tariffs-card__price {
  display: flex;
  align-items: flex-end;
  margin-bottom: 20px;
  font-weight: 800;
  font-size: 56px;
  line-height: 100%;
  color: #2a211c;
  gap: 8px;
}

.tariffs-card__price span {
  padding-bottom: 8px;
  font-weight: 400;
  font-size: 16px;
  line-height: 100%;
  color: #7c6758;
}

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

.tariffs-card__list {
  list-style: disc;
  margin: 0;
  padding-left: 20px;
  display: flex;
  flex-direction: column;
  font-weight: 400;
  font-size: 16px;
  line-height: 140%;
  color: #2a211c;
  gap: 12px;
}

И последнее — кнопка. Чтобы разместить ее внизу карточки, нужно добавить margin-top: auto, тогда отступ флекс-элемента займет все доступное пространство. Также делаем эффект наведения на кнопку. И не забудьте указать font-family: inherit, чтобы шрифт передался кнопке.

.tariffs-card__btn {
  margin-top: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 16px;
  padding: 16px 20px;
  width: 100%;
  font-family: inherit;
  font-weight: 700;
  font-size: 16px;
  line-height: 120%;
  color: #2a211c;
  background: #fff1ea;
  cursor: pointer;
  transition: background 0.3s;
}

.tariffs-card__btn:hover {
  background: #e3d8d2;
}

Далее нам нужно сделать среднюю карточку в другом стиле, выделить ее. Используем класс-модификатор, и через него меняем цвета элементов.

.tariffs-card--best {
  border: 1px solid #2a211c;
  background: #2a211c;
}

.tariffs-card--best .tariffs-card__title {
  color: #fff;
}

.tariffs-card--best .tariffs-card__price {
  color: #fff;
}

.tariffs-card--best .tariffs-card__price span {
  color: rgba(255, 255, 255, 0.64);
}

.tariffs-card--best .tariffs-card__descr {
  color: rgba(255, 255, 255, 0.74);
}

.tariffs-card--best .tariffs-card__list {
  color: #fff;
}

.tariffs-card--best .tariffs-card__btn {
  color: #fff;
  background: #ef4444;
}

.tariffs-card--best .tariffs-card__btn:hover {
  background: #c33737;
}

Теперь вы умеете создавать современные карточки тарифов с несколькими вариантами оформления, списком преимуществ и кнопкой действия. Заодно мы разобрали Flexbox, модификаторы БЭМ, одинаковую высоту карточек, margin-top: auto, выравнивание элементов по базовой линии и создание переиспользуемых интерфейсных компонентов.

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

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