Как сверстать комментарий пользователя
Эта статья основана на одном из практических заданий verstaem.online.
Вы можете читать материал как обычное руководство или сначала попробовать выполнить задание самостоятельно, а затем сравнить свое решение с подробным разбором.
Перейти к заданиюВ этой статье мы создадим блок комментария пользователя с аватаром, именем, должностью, бейджем роли, датой публикации и кнопками действий. На его примере разберем, как выравнивать сложные интерфейсы с помощью Flexbox, оформлять декоративные элементы без лишней разметки, работать с SVG-иконками и создавать переиспользуемые компоненты.
Создаем 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>
Идем дальше, верстаем комментарий. Он будет разделен на две части: аватар пользователя и вся информация справа. Такой подход делает структуру простой и понятной.
<div class="comment">
<img ...>
<div class="comment__inner">
</div>
</div>
Теперь наполним правую часть.
Первым элементом сделаем верхнюю строку. В ней находятся имя пользователя с должностью и временем публикации. Эти блоки находятся по разные стороны карточки, поэтому позже здесь пригодится Flexbox.
Внутри информации о пользователе также сделаем небольшую вложенную структуру. Имя и бейдж располагаются в одной строке, а должность — ниже.
После этого остается добавить текст комментария и нижний блок с кнопками. Обратите внимание, что обе кнопки — это именно <button>, а не ссылки. Они выполняют действие внутри страницы, а не переводят пользователя на другую страницу, поэтому использование кнопок здесь семантически правильнее.
<div class="comment">
<img src="img/avatar.png" alt="Марина Орлова" class="comment__avatar" />
<div class="comment__inner">
<div class="comment__top">
<div class="comment__info">
<div class="comment__user">
<div class="comment__name">Марина Орлова</div>
<div class="comment__status">Ментор</div>
</div>
<div class="comment__position">Product Designer</div>
</div>
<div class="comment__date">14 минут назад</div>
</div>
<p class="comment__text">
Мне нравится, когда интерфейс не пытается выглядеть “сложно”. Хорошая
композиция, понятные отступы и аккуратное выравнивание почти всегда
работают лучше, чем перегруженные декоративные решения.
</p>
<div class="comment__btns">
<button class="comment__btn">
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1.66666 7.91667C1.66668 6.98933 1.94799 6.08382 2.47344 5.31972C2.99889 4.55562 3.74376 3.96888 4.60967 3.637C5.47558 3.30511 6.4218 3.2437 7.32334 3.46087C8.22489 3.67803 9.03935 4.16356 9.65916 4.85333C9.70282 4.90001 9.7556 4.93722 9.81423 4.96266C9.87286 4.98811 9.93609 5.00123 10 5.00123C10.0639 5.00123 10.1271 4.98811 10.1858 4.96266C10.2444 4.93722 10.2972 4.90001 10.3408 4.85333C10.9587 4.15908 11.7733 3.66947 12.6764 3.44967C13.5794 3.22986 14.5279 3.29029 15.3957 3.6229C16.2635 3.95551 17.0095 4.54454 17.5343 5.31158C18.059 6.07862 18.3378 6.9873 18.3333 7.91667C18.3333 9.825 17.0833 11.25 15.8333 12.5L11.2567 16.9275C11.1014 17.1058 10.9099 17.2491 10.695 17.3478C10.4801 17.4464 10.2467 17.4982 10.0102 17.4997C9.77378 17.5012 9.5397 17.4524 9.32357 17.3564C9.10744 17.2605 8.91419 17.1197 8.75666 16.9433L4.16666 12.5C2.91666 11.25 1.66666 9.83333 1.66666 7.91667Z"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
32
</button>
<button class="comment__btn">
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M16.6667 15V13.3333C16.6667 12.4493 16.3155 11.6014 15.6903 10.9763C15.0652 10.3512 14.2174 10 13.3333 10H3.33333"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M7.49999 14.1667L3.33333 10L7.49999 5.83334"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
Ответить
</button>
</div>
</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/InterMedium.woff2");
font-display: swap;
font-weight: 500;
}
@font-face {
font-family: "Inter";
src: url("../fonts/InterSemiBold.woff2");
font-display: swap;
font-weight: 600;
}
@font-face {
font-family: "Inter";
src: url("../fonts/InterBold.woff2");
font-display: swap;
font-weight: 700;
}
body {
margin: 0;
padding: 20px;
font-family: "Inter", sans-serif;
background: #111;
}
Начнем с внешнего блока. Для него отлично подходит Flexbox. Нам нужно расположить аватар и содержимое в одну строку, поэтому достаточно задать display: flex. При этом я использую не align-items: center, а align-items: flex-start. Высота комментариев может быть разной, и если выравнивать элементы по центру, маленький аватар начнет «плавать» относительно длинного текста. Верхнее выравнивание выглядит значительно аккуратнее. Также добавим внутренние отступы, скругление и ограничим максимальную ширину блока.
.comment {
display: flex;
align-items: flex-start;
margin: 0 auto;
border-radius: 30px;
padding: 24px;
max-width: 760px;
gap: 20px;
background: #fffdf9;
}
Далее делаем аватар. Для изображения всегда полезно задавать сразу несколько свойств. Во-первых, фиксируем размеры. Во-вторых, используем display: block, чтобы убрать небольшой нижний отступ, который браузер оставляет у строчных изображений. И, конечно, используем object-fit: cover. Последнее особенно важно. Если однажды вместо квадратной фотографии загрузят вертикальную или горизонтальную, изображение не исказится, а просто аккуратно обрежется внутри своего контейнера.
.comment__avatar {
display: block;
border-radius: 24px;
width: 64px;
height: 64px;
object-fit: cover;
}
Теперь переходим к содержимому комментария. Здесь есть одна маленькая, но очень полезная строчка. Именно она говорит Flexbox: «Займи всё свободное пространство рядом с аватаром.» Благодаря этому комментарий автоматически растягивается на оставшуюся ширину карточки, независимо от размеров изображения.
.comment__inner {
flex: 1;
}
Делаем верхнюю строку комментария. Она состоит из двух элементов — информации о пользователе и даты публикации. Здесь снова помогает Flexbox. Используем justify-content: space-between, чтобы один блок оказался слева, а второй автоматически прижался к правому краю. Дополнительно задаем gap. Он пригодится, если ширины страницы станет недостаточно — элементы не будут прилипать друг к другу.
.comment__top {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 20px;
}
Имя и бейдж находятся в одной строке. Поэтому здесь удобно использовать display: inline-flex. В данном случае блок должен занимать только ширину своего содержимого, а не растягиваться на всю строку. Сам бейдж тоже оформлен через Flexbox. Даже если внутри сейчас только одно слово, такой способ позволяет без проблем менять высоту текста, добавлять иконки или делать бейджи разного размера без изменения верстки.
.comment__info {
margin-bottom: 20px;
}
.comment__date {
font-weight: 500;
font-size: 12px;
line-height: 120%;
color: #5e5e5e;
}
.comment__user {
display: inline-flex;
align-items: center;
gap: 8px;
}
.comment__name {
font-weight: 700;
font-size: 20px;
line-height: 120%;
color: #2d2218;
}
.comment__status {
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 100px;
padding: 4px 12px;
font-weight: 600;
font-size: 12px;
line-height: 120%;
color: #5e5e5e;
background: #eeeae4;
}
.comment__position {
margin-top: 8px;
font-weight: 400;
font-size: 14px;
line-height: 120%;
color: #5e5e5e;
}
.comment__text {
margin: 0;
font-weight: 400;
font-size: 16px;
line-height: 145%;
color: #433226;
}
Теперь остается оформить нижний блок. Сначала создадим контейнер для кнопок. И снова используем Flexbox. Он позволит одинаково выровнять обе кнопки и легко управлять расстоянием между ними. Сами кнопки тоже сделаем через flexbox, чтобы управлять содержимым внутри. И не забудем указать для svg-иконки currentColor, чтобы иконка имела цвет текста. Ну и как обычно, несмотря на отсутствие в макете состояния :hover, я его добавляю.
.comment__btns {
display: flex;
align-items: center;
margin-top: 20px;
gap: 12px;
}
.comment__btn {
display: inline-flex;
align-items: center;
justify-content: center;
border: none;
border-radius: 14px;
padding: 10px 12px;
font-family: inherit;
font-weight: 600;
font-size: 14px;
line-height: 140%;
color: #c2410c;
background: #fff3e3;
cursor: pointer;
transition: background 0.3s;
gap: 8px;
}
.comment__btn svg {
display: block;
width: 20px;
height: 20px;
stroke: currentColor;
}
.comment__btn:hover {
background: #dad0c3;
}
Теперь вы умеете создавать современный блок комментария пользователя с аватаром, информацией об авторе, датой публикации и кнопками действий. По пути мы разобрали несколько полезных приемов Flexbox, работу с SVG, currentColor, inline-flex и создание аккуратных интерфейсных компонентов, которые легко использовать в любых проектах.