Как сверстать галерею фотографий на CSS Grid
Эта статья основана на одном из практических заданий verstaem.online.
Вы можете читать материал как обычное руководство или сначала попробовать выполнить задание самостоятельно, а затем сравнить свое решение с подробным разбором.
Перейти к заданиюВ этой статье мы создадим галерею фотографий с использованием CSS Grid. По пути разберем, как организовать сетку, правильно оформить карточки изображений, использовать семантические теги, работать с изображениями и подготовить компонент, который легко масштабируется при добавлении новых фотографий.
Создаем 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>
Теперь давайте верстать галерею. Начнем мы с того, что сделаем секцию — <section>. Внутри разместим контейнер — блок, который центрирует контент. Ну, а затем реализуем верхушку. Тут будет заголовок и кнопка.
<div class="gallery__top">
<h2 class="gallery__title">Галерея</h2>
<button class="gallery__btn">Загрузить</button>
</div>
Саму галерею будет делать стандартно — списком, поскольку у нас одинаковые элементы идут друг за другом. Для списка, помимо прочего, добавим класс grid. Это нужно для того, чтобы управлять CSS Grid на этом элементе.
<ul class="gallery__list grid">
<li class="gallery__item">
</li>
</ul>
Сама карточка будет реализована как отдельный компонент, отдельный див. Внутри — изображение, заголовок, а также время через тег <time>.
<section class="gallery">
<div class="container">
<div class="gallery__top">
<h2 class="gallery__title">Галерея</h2>
<button class="gallery__btn">Загрузить</button>
</div>
<ul class="gallery__list grid">
<li class="gallery__item">
<div class="gallery-card">
<img src="img/1.png" alt="Горное озеро" class="gallery-card__pic">
<div class="gallery-card__text">
<h3 class="gallery-card__title">
Горное озеро
</h3>
<time datetime="2026-06-12 00:00" class="gallery-card__time">12 Июня 2026</time>
</div>
</div>
</li>
<li class="gallery__item">
<div class="gallery-card">
<img src="img/2.png" alt="Ночной город" class="gallery-card__pic">
<div class="gallery-card__text">
<h3 class="gallery-card__title">
Ночной город
</h3>
<time datetime="2026-06-10 00:00" class="gallery-card__time">10 Июня 2026</time>
</div>
</div>
</li>
<li class="gallery__item">
<div class="gallery-card">
<img src="img/3.png" alt="Океанский пляж" class="gallery-card__pic">
<div class="gallery-card__text">
<h3 class="gallery-card__title">
Океанский пляж
</h3>
<time datetime="2026-06-08 00:00" class="gallery-card__time">8 Июня 2026</time>
</div>
</div>
</li>
<li class="gallery__item">
<div class="gallery-card">
<img src="img/4.png" alt="Лесная тропа" class="gallery-card__pic">
<div class="gallery-card__text">
<h3 class="gallery-card__title">
Лесная тропа
</h3>
<time datetime="2026-06-06 00:00" class="gallery-card__time">6 Июня 2026</time>
</div>
</div>
</li>
<li class="gallery__item">
<div class="gallery-card">
<img src="img/5.png" alt="Водопад" class="gallery-card__pic">
<div class="gallery-card__text">
<h3 class="gallery-card__title">
Водопад
</h3>
<time datetime="2026-06-04 00:00" class="gallery-card__time">4 Июня 2026</time>
</div>
</div>
</li>
<li class="gallery__item">
<div class="gallery-card">
<img src="img/6.png" alt="Городские улицы" class="gallery-card__pic">
<div class="gallery-card__text">
<h3 class="gallery-card__title">
Городские улицы
</h3>
<time datetime="2026-06-02 00:00" class="gallery-card__time">2 Июня 2026</time>
</div>
</div>
</li>
</ul>
</div>
</section>
Обязательно заполняйте alt у изображений по смыслу, а также поддерживайте верный формат атрибута datetime.
Добавляем стили
Подключим файл стилей через <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;
background: #f4f6f9;
font-family: "Inter", sans-serif;
}
Важный нюанс, который вы можете увидеть в коде — это шрифты. Я намеренно указал font-family внутри @font-face одинаковым, потому что сам шрифт имеет одно название — Inter, отличаются лишь его начертания. Именно так мы и будем делать — указываем шрифт для <body> один раз, а затем с помощью font-weight меняем толщину шрифта там, где нам нужно.
Далее создаем контейнер. Это блок, который должен быть по центру. Видим в макете ширину 1200, но нам стоит быть умнее, и предусмотреть отступы. Ведь если сайт будет сжиматься, его контент не должен липнуть к краям. Чтобы это реализовать, нужно добавить padding. Именно поэтому, когда мы добавим отступ, нужно и ширину изменить. Сделаем отступы по 15, получится 1200+15+15 = 1230.
.container {
margin: 0 auto;
padding: 0 15px;
max-width: 1230px;
}
Далее поработаем с классом grid. Нам нужно определить нашу сетку. Если посмотреть в макет, увидим три широкие колонки, разделенные отступом. Именно на это и стоит ориентироваться.
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24px;
}
Мы задаем display: grid, а затем свойство grid-template-columns, которое управляет колонками. Написав функцию repeat(), и передав в нее два параметра (первый — количество колонок, второй — их размер), мы получаем три идентичных по ширине колонки, которые будут тянуться. И сюда же добавляем gap.
Далее реализуем верхушку. Тут все просто. С помощью flexbox разместим элементы в строку, раскинем их по сторонам, и зададим стили самим элементам. Не забудьте написать font-family для кнопки.
.gallery__top {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 36px;
gap: 20px;
}
.gallery__title {
margin: 0;
font-weight: 700;
font-size: 32px;
line-height: 100%;
color: #111827;
}
.gallery__btn {
display: inline-flex;
align-items: center;
justify-content: center;
border: none;
border-radius: 12px;
padding: 12px 24px;
font-family: inherit;
font-weight: 500;
font-size: 16px;
color: #f4f6f9;
background: #111827;
cursor: pointer;
transition: background 0.3s;
}
.gallery__btn:hover {
background: #2a3b5f;
}
В качестве стилей списка будут только сбросы. Сброс margin, padding и list-style. А дальше уже делаем карточку. Здесь обязательно нужно указать overflow: hidden, иначе картинка не обрежется по углу карточки. Самому изображению обязательно нужно задать display: block и max-width: 100%, чтобы изображение встало по размеру карточки. В остальном просто забираем стили из макета.
.gallery__list {
margin: 0;
padding: 0;
list-style: none;
}
.gallery-card {
position: relative;
overflow: hidden;
border-radius: 16px;
background: #fff;
}
.gallery-card__pic {
display: block;
max-width: 100%;
}
.gallery-card__text {
padding: 16px;
}
.gallery-card__title {
margin: 0;
margin-bottom: 8px;
font-weight: 600;
font-size: 20px;
line-height: 100%;
color: #111827;
}
.gallery-card__time {
font-weight: 400;
font-size: 12px;
line-height: 100%;
color: #6b7280;
}
Теперь вы умеете создавать современные галереи изображений с помощью CSS Grid. Мы разобрали семантическую разметку, организацию карточек, работу с фотографиями, использование компонента Grid и подготовили основу, которую можно использовать практически в любом проекте — от блога до интернет-магазина или портфолио.