Как сверстать панель аналитики
Эта статья основана на одном из практических заданий verstaem.online.
Вы можете читать материал как обычное руководство или сначала попробовать выполнить задание самостоятельно, а затем сравнить свое решение с подробным разбором.
Перейти к заданиюВ этой статье мы сверстаем панель аналитики, подобную тем, которые можно встретить в CRM-системах, интернет-магазинах и административных панелях. По пути разберем сложную сетку на CSS Grid, научимся комбинировать Grid и Flexbox, оформим статистические карточки, список популярных товаров и увидим, как строятся реальные Dashboard-интерфейсы.
Создаем 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>
Начнем с общей структуры. Она представлена дивом, а внутри него — контейнер, чтобы выровнять контент по центру. У контейнера также добавлен класс grid, чтобы управлять сеткой.
<div class="content">
<div class="container grid">
</div>
</div>
Верхняя строка панели состоит из двух блоков. Слева — приветственный с заголовком, справа — карточка с выручкой. Тут просто текстовые элементы, никакой сложности.
<div class="content__main">
<h2 class="content__title">
Панель аналитики
</h2>
<p class="content__descr">
Основные показатели интернет-магазина за последние семь дней
</p>
</div>
<div class="content__revenue">
<h2 class="content__subtitle">
Выручка
</h2>
<div class="content__val">
2,48 млн
</div>
<div class="content__percent">
▲ +14%
</div>
</div>
Далее идет контент чуть сложнее. Слева — список популярных товаров, а справа список статистики. Делаем все это именно списками, и обязательно выделяем карточки товара как отдельный элемент — <article>, так как этот тег отлично подходит для независимых элементов.
Обратите внимание на заголовки. «Популярные товары» это h2, заголовки товаров — h3, а вот заголовки в статистике уже h4. Все по иерархии, постепенно уменьшается смысловая нагрузка.
<div class="content__popular">
<h2 class="content__caption">
Популярные товары
</h2>
<ul class="content__items">
<li class="content__item">
<article class="product">
<img src="img/1.png" alt="MacBook Air" class="product__pic">
<div class="product__text">
<h3 class="product__title">
MacBook Air
</h3>
<div class="product__quantity">
184 продажи
</div>
</div>
</article>
</li>
<li class="content__item">
<article class="product">
<img src="img/2.png" alt="AirPods Pro" class="product__pic">
<div class="product__text">
<h3 class="product__title">
AirPods Pro
</h3>
<div class="product__quantity">
126 продаж
</div>
</div>
</article>
</li>
<li class="content__item">
<article class="product">
<img src="img/3.png" alt="Studio Display" class="product__pic">
<div class="product__text">
<h3 class="product__title">
Studio Display
</h3>
<div class="product__quantity">
48 продаж
</div>
</div>
</article>
</li>
</ul>
</div>
<div class="content__statistics">
<ul class="content__list">
<li class="content__list-item">
<h4 class="content__subt">Заказы</h4>
<div class="content__meaning">
184
</div>
</li>
<li class="content__list-item">
<h4 class="content__subt">Клиенты</h4>
<div class="content__meaning">
96
</div>
</li>
<li class="content__list-item">
<h4 class="content__subt">Конверсия</h4>
<div class="content__meaning">
5.8%
</div>
</li>
<li class="content__list-item">
<h4 class="content__subt">Возвраты</h4>
<div class="content__meaning">
67
</div>
</li>
<li class="content__list-item">
<h4 class="content__subt">Средний чек</h4>
<div class="content__meaning">
₽13k
</div>
</li>
<li class="content__list-item">
<h4 class="content__subt">Товаров</h4>
<div class="content__meaning">
812
</div>
</li>
<li class="content__list-item">
<h4 class="content__subt">Отзывы</h4>
<div class="content__meaning">
41
</div>
</li>
<li class="content__list-item">
<h4 class="content__subt">Подписки</h4>
<div class="content__meaning">
67
</div>
</li>
</ul>
</div>
</div>
Добавляем стили
Подключим файл стилей через <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;
}
body {
margin: 0;
padding: 20px;
background: #20242b;
font-family: "Inter", sans-serif;
}
.container {
margin: 0 auto;
padding: 0 15px;
max-width: 1310px;
}
.grid {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 20px;
}
Здесь обращаем внимание на grid, мы описываем в нем общую структуру сетки. repeat(12, 1fr) — 12 указано, потому что в макете сетка из 12 колонок. Размер контейнера же в макете 1280, но поскольку мы добавляем слева и справа по 15 пикселей, в итоге выходит 1310.
Далее поработаем с элементами первой строки. Они очень простые, поэтому детально останавливаться не будем. Укажу лишь, что мы явно используем здесь grid-column, чтобы дать понять браузеру, сколько колонок должна занимать каждая часть.
.content__main {
grid-column: 8 span;
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 20px;
padding: 24px;
background: #4338ca;
}
.content__title {
margin: 0;
margin-bottom: 12px;
font-weight: 700;
font-size: 36px;
line-height: 100%;
color: #fff;
}
.content__descr {
margin: 0;
font-weight: 400;
font-size: 16px;
line-height: 120%;
color: rgba(255, 255, 255, 0.9);
}
.content__revenue {
display: flex;
flex-direction: column;
gap: 12px;
grid-column: 4 span;
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 20px;
padding: 24px;
background: #2d333d;
}
.content__subtitle {
margin: 0;
font-weight: 400;
font-size: 14px;
line-height: 100%;
color: #94a3b8;
}
.content__val {
font-weight: 700;
font-size: 48px;
line-height: 100%;
color: #fff;
}
.content__percent {
font-weight: 700;
font-size: 16px;
line-height: 100%;
color: #22c55e;
}
Идем дальше, и здесь у нас две колонки с двумя списками. Займемся заголовком и списком популярных товаров.
.content__popular {
grid-column: 4 span;
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 20px;
padding: 24px;
background: #2d333d;
}
.content__caption {
margin: 0;
margin-bottom: 20px;
font-weight: 700;
font-size: 14px;
line-height: 100%;
letter-spacing: -0.01em;
text-transform: uppercase;
color: #94a3b8;
}
.content__items {
display: flex;
flex-direction: column;
margin: 0;
padding: 0;
list-style: none;
}
.content__item:last-child .product {
border: none;
}
Здесь есть один важный момент — это работа с border. Саму обводку мы еще не задали, она будет ниже, но уже сейчас отмечаем, что у последнего элемента списка ищем .product, и у него сбрасываем обводку, т. к. по макету она не нужна.
Далее стилизуем непосредственно товары. Из важного здесь конечно работа с изображением. Ему стоит четко задать размеры, скругления, а также указать object-fit: cover, чтобы при вставке изображения даже другого размера, оно встало как надо.
.product {
display: flex;
align-items: center;
gap: 12px;
border-bottom: 1px solid #555;
padding: 12px 0;
}
.product__pic {
display: block;
border-radius: 12px;
width: 52px;
height: 52px;
object-fit: cover;
}
.product__title {
margin: 0;
margin-bottom: 8px;
font-weight: 700;
font-size: 16px;
line-height: 100%;
color: #fff;
}
.product__quantity {
font-weight: 400;
font-size: 12px;
line-height: 100%;
color: #94a3b8;
}
Теперь статистика. Здесь я решил снова использовать grid, и поэтому внутри блока мы создадим свою сетку, которая будет состоять из 4х колонок, по количеству элементов в строке — grid-template-columns: repeat(4, 1fr);. Остальное в этом блоке делается просто, поэтому просто показываю код.
.content__statistics {
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 20px;
padding: 24px;
grid-column: 8 span;
background: #2d333d;
}
.content__list {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
margin: 0;
padding: 0;
list-style: none;
}
.content__list-item {
border-radius: 16px;
padding: 16px;
min-height: 122px;
background: #363d48;
}
.content__subt {
margin: 0;
margin-bottom: 12px;
font-weight: 400;
font-size: 12px;
line-height: 100%;
color: #94a3b8;
}
.content__meaning {
font-weight: 700;
font-size: 28px;
line-height: 100%;
color: #fff;
}
Теперь вы умеете создавать Dashboard-интерфейсы с помощью CSS Grid. Мы построили многоуровневую сетку, объединили различные компоненты страницы, сверстали карточки статистики и список популярных товаров. Именно подобные приемы используются при разработке CRM, административных панелей, аналитических сервисов и корпоративных приложений.