Flexbox с нуля: собираем адаптивный ряд карточек по шагам
За полчаса вы соберёте на flexbox горизонтальный ряд карточек, который сам переносится на узких экранах и выравнивает содержимое. Разберём каждое свойство на живом примере.

К концу этой инструкции у вас будет рабочий ряд из трёх карточек: они стоят в строку на широком экране, равномерно распределяют пространство, выравниваются по высоте и переносятся на новую строку, когда места не хватает. Всё на чистом CSS без библиотек. По времени — около 30 минут, если вы впервые касаетесь flexbox.
Flexbox работает в любом актуальном браузере уже много лет, отдельных префиксов вроде -webkit- для современных версий Chrome, Firefox, Safari и Edge не требуется. Проверять будем в обычном браузере, открывая HTML-файл двойным кликом.
Что нужно до начала
Ничего устанавливать не придётся. Понадобятся:
- любой текстовый редактор — подойдёт даже «Блокнот», но удобнее VS Code или Sublime Text;
- браузер с инструментами разработчика (в Chrome и Firefox они открываются по F12);
- один файл
index.html, который мы создадим на первом шаге.
Базовое понимание того, что такое HTML-тег и CSS-свойство, пригодится, но глубоких знаний не нужно.
Ключевая идея flexbox в одном абзаце
Flexbox — это способ раскладки, где есть контейнер (родитель) и элементы (прямые дети). Вы задаёте display: flex контейнеру, и его дети выстраиваются вдоль одной оси. Свойства делятся на две группы: одни пишутся контейнеру и управляют всеми детьми сразу, другие пишутся конкретному ребёнку. Путаница между этими двумя группами — источник почти всех проблем у новичков.
Запомните разделение:justify-content,align-items,flex-wrap,gap— это свойства контейнера.flex-grow,flex-shrink,align-self— свойства отдельного элемента. Половина ошибок — от того, что свойство написано не тому.
Пошаговая сборка
Создайте файл и разметку. Сохраните в файл
index.htmlследующий код и откройте его в браузере.<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Ряд карточек</title> <style> /* стили добавим на следующих шагах */ </style> </head> <body> <div class="cards"> <div class="card"> <h3>Карточка 1</h3> <p>Короткий текст.</p> </div> <div class="card"> <h3>Карточка 2</h3> <p>Текст подлиннее, чтобы карточка была выше остальных и мы увидели выравнивание.</p> </div> <div class="card"> <h3>Карточка 3</h3> <p>Средний текст.</p> </div> </div> </body> </html>Проверка: в браузере появятся три блока, идущие сверху вниз друг под другом. Пока это обычные
divбез раскладки.Включите flex у контейнера. Внутри тега
<style>добавьте правило для.cards..cards { display: flex; }Проверка: обновите страницу — три карточки встанут в одну строку, вплотную друг к другу. Это и есть главный момент:
display: flexпревратил детей в ряд.Задайте промежутки между карточками. Используйте
gap— это самый чистый способ развести элементы, он не добавляет отступ по краям контейнера..cards { display: flex; gap: 16px; }Проверка: между карточками появится расстояние в 16 пикселей, а по краям строки отступа не будет.
Оформите сами карточки. Добавьте правило для
.card, чтобы их было видно и было что распределять..card { flex: 1; /* каждая карточка занимает равную долю ширины */ padding: 16px; border: 1px solid #d0d0d0; border-radius: 8px; background: #f7f7f7; }Проверка: три карточки станут одинаковой ширины и заполнят всю строку. Свойство
flex: 1— сокращение, которое разрешает карточке расти и сжиматься, деля пространство поровну.Выровняйте карточки по высоте. Обратите внимание: карточка с длинным текстом выше, но остальные две уже растянулись до её высоты. Так работает значение по умолчанию
align-items: stretchу контейнера. Если хотите, чтобы карточки прижались к верху и сохранили свою высоту, добавьте контейнеру:.cards { display: flex; gap: 16px; align-items: flex-start; }Проверка: с
flex-startкарточки перестанут тянуться и каждая станет по высоте своего содержимого. Уберите строку — вернётся выравнивание по высоте. Оставьте тот вариант, который вам нужен.Разрешите перенос на узких экранах. Сейчас на маленькой ширине карточки начнут сжиматься до нечитаемого. Добавьте перенос и минимальную ширину.
.cards { display: flex; gap: 16px; flex-wrap: wrap; } .card { flex: 1 1 200px; /* расти, сжиматься, базовая ширина 200px */ padding: 16px; border: 1px solid #d0d0d0; border-radius: 8px; background: #f7f7f7; }Проверка: сузьте окно браузера. Когда карточкам перестанет хватать 200 пикселей на каждую, они начнут переноситься на новую строку по одной. Это адаптивность без единого медиазапроса.
Что означает flex: 1 1 200px
Запись flex: 1 1 200px — это три свойства в одну строку:
- flex-grow: 1 — насколько карточка готова расти, если в строке остаётся свободное место. Одинаковое число у всех — растут поровну;
- flex-shrink: 1 — насколько готова сжиматься, если места не хватает;
- flex-basis: 200px — стартовая ширина до распределения свободного места. Именно она определяет порог переноса.
Если поставить flex-grow: 0, карточки перестанут растягиваться и останутся шириной ровно 200px, а свободное место соберётся сбоку. Поэкспериментируйте с этими числами — эффект виден сразу.
Направление и выравнивание: краткая шпаргалка
Эти свойства пишутся контейнеру и покрывают почти все повседневные задачи раскладки.
| Свойство | Что делает | Частые значения |
|---|---|---|
flex-direction | ось: строка или столбец | row (по умолчанию), column |
justify-content | распределение вдоль главной оси | flex-start, center, space-between |
align-items | выравнивание поперёк оси | stretch (по умолчанию), center, flex-start |
flex-wrap | перенос на новую строку | nowrap (по умолчанию), wrap |
gap | промежуток между элементами | любое значение: 16px, 1rem |
Важная деталь: justify-content и align-items меняются местами, когда вы ставите flex-direction: column. Главная ось идёт вниз — и justify-content начинает управлять вертикалью. Это сбивает с толку чаще всего.
Если не получилось
- Карточки не встали в ряд, а идут друг под другом. Скорее всего,
display: flexнаписан не тому элементу. Он должен стоять у родителя (.cards), а не у самих карточек. - justify-content не работает. Если карточки уже заняли всю ширину благодаря
flex-grow, распределять нечего — свободного места нет. Уберитеflex-grow(поставьтеflex: 0 1 200px), иspace-betweenзаработает. - Перенос не срабатывает при сужении. Проверьте, что у контейнера есть
flex-wrap: wrap. Без него по умолчанию стоитnowrap, и элементы будут сжиматься вместо переноса. - gap игнорируется в очень старом браузере. Поддержка
gapво flex-контейнерах появилась не сразу; в актуальных версиях Chrome, Firefox, Safari и Edge она есть. Если верстаете под давно устаревший браузер, вместоgapиспользуйтеmarginу элементов. - Карточка не сжимается ниже своего содержимого. У flex-элемента по умолчанию
min-width: auto, и он не станет уже содержимого. При проблемах с длинным текстом добавьте карточкеmin-width: 0.
Что делать дальше
Соберите вложенность: внутри карточки сделайте её содержимое тоже flex-контейнером с flex-direction: column и прижмите кнопку к низу через margin-top: auto — частый приём для карточек с кнопкой. Дальше стоит посмотреть в сторону CSS Grid: flexbox силён для раскладки вдоль одной оси, а для двумерных сеток (строки и колонки одновременно) удобнее grid. Полный список свойств и их значений держите под рукой в справочнике MDN.
Задачи: математика, физика, химия: Разбор задачи по шагам с проверкой и похожей задачей
Спросить за 10 ₽Источники: MDN Web Docs — CSS Flexible Box Layout, MDN — Basic concepts of flexbox
Частые вопросы
А если flexbox не работает в моём браузере?
Чем flexbox отличается от CSS Grid и что выбрать?
Почему justify-content: center не центрирует по вертикали?
gap работает во flexbox или только в grid?
Что делать, если карточки разной ширины, хотя я задал flex: 1?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.