Полное руководство по Flexbox CSS: от основ до продвинутых техник

Флексим по правилам

Полное руководство по Flexbox CSS: от основ до продвинутых техник

Когда-то страницы верстали на таблицах и float. А когда в CSS появились сначала Flexbox, потом и Grid, верстальщики наконец-то выдохнули. 

Про Grid мы уже писали, а теперь разберёмся с Flexbox: как он работает, почему это стандарт адаптивной вёрстки и какие трюки с ним должен знать каждый фронтендер.

Что такое Flexbox в CSS?

Flexbox — это современный способ выстраивать и выравнивать элементы внутри контейнера. Он появился как ответ на проблемы старой вёрстки: бесконечные float, clear, костыли с margin и position: absolute, которые приходилось комбинировать ради простейшего выравнивания.

Спецификация Flexbox начала разрабатываться ещё в 2009 году, а стабильной и кроссбраузерной стала ближе к 2016-му. С тех пор флексбокс стал стандартом для большинства макетов.

Главная фишка Flexbox — адаптивность. Элементы могут сами подстраиваться под пространство: сжиматься, растягиваться, переноситься на новую строку. 

Основные понятия Flexbox

Чтобы включить Flexbox, достаточно задать родительскому элементу: display: flex; и он становится флекс-контейнером, а его потомки — флекс-элементами. Эти элементы перестают подчиняться стандартной потоковой вёрстке и начинают жить по новым правилам.

Их можно выстраивать в строку или колонку, задавать расстояния между ними, управлять тем, как они растягиваются или сжимаются, и даже менять их порядок — всё через CSS, без изменения HTML-разметки.

Flexbox работает вдоль двух осей:

  • Main axis — основная, или главная, ось (по умолчанию горизонтальная, слева направо).
  • Cross axis — поперечная ось (перпендикулярная основной).

Примерно так:

Оси в Flexbox динамические. Что будет главной, а что поперечной осью, зависит от того, какой flex-direction вы задали:

  • Если flex-direction: row → главная ось — горизонтальная, поперечная — вертикальная.
  • Если flex-direction: column → наоборот: главная — вертикаль, поперечная — горизонталь.

Подробнее об этом позже.

Преимущества использования Flexbox перед другими методами вёрстки

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

Сравните с тем, как раньше верстали на float, inline-block и margin: приходилось городить обёртки, следить за clearfix, выравнивать всё вручную. Flexbox решает эти задачи нативно и лаконично, и в итоге мы получаем такие преимущества:

  • Простое выравнивание по вертикали и горизонтали.
  • Элементы сами подстраиваются под ширину и высоту контейнера.
  • Можно менять порядок элементов, не трогая HTML.
  • Почти не нужны дополнительные обёртки — меньше разметки, проще поддержка.

А что насчёт Grid? Он нужен, когда макет двухосевой — например, табличная раскладка, галерея, журнал. Но на практике в 80% задач хватает Flexbox — он проще, легче читается, быстрее верстается. Если вы только начинаете — осваивайте Flex в первую очередь.

Flexbox предназначен для управления элементами по одной оси, Grid — для управления по двум осям. Источник: YouTube

Как работает display: flex?

Весь CSS построен на разных режимах раскладки, которые называются layout modes. По умолчанию используется так называемый поток документа (Flow layout) — он работает просто: блочные элементы идут сверху вниз, занимая всю ширину, а строчные выстраиваются в одну линию, пока не упрутся в край.

Вот так будут вести себя блочные элементы в обычном контейнере: они идут сверху вниз и занимают всю доступную ширину родителя. Отступы задаются отдельно через margin:

Но когда вы переключаете display на другой режим, то запускаете другой алгоритм раскладки. В нашем случае — Flexbox. Это называется flex formatting context.

Активация flex-контейнера

Как только элемент получает display: flex, то браузер уже не раскладывает его потомков один под другим, как в документе Word. Включается Flexbox и начинает управлять выравниванием, направлением, отступами и порядком.

Родитель становится флекс-контейнером, а его прямые потомки — флекс-элементами, которые подчиняются новому набору правил. 

Например:

 <div class="flex-container">
   <div class="item">1</div>
   <div class="item">2</div>
   <div class="item">3</div>
   <div class="item">4</div>
   <div class="item">5</div>
   <div class="item">6</div>
 </div>
.flex-container {
  display: flex;
}

Теперь .flex-container — это флекс-контейнер, а шесть <div> внутри — флекс-элементы. Они перестают быть обычными блочными элементами и выстраиваются в одну строку (по умолчанию), при этом мы можем управлять их отступами, выравниванием, переносом, ростом и сжатием.

Flexbox не влияет на все стили страницы, он включается локально на конкретном контейнере. Хотите флекс в одном блоке — включили. Хотите грид в другом — пожалуйста. Главное — понимать, какой режим раскладки вы сейчас активировали.

Разница между flex и inline-flex

По умолчанию флекс-контейнер ведёт себя как блочный элемент: занимает всю ширину строки, начинается с новой строки и отталкивает от себя всё остальное — как привычный <div>. Такое поведение даёт display: flex.

Но если нужно, чтобы контейнер встраивался прямо внутрь текста, не ломая поток и не выталкивая соседей, то используется inline-flex. Внешне он работает как строчный <span>: занимает только нужную ширину, спокойно помещается в одну строчку рядом с другими элементами. При этом внутри остаётся полноценным флекс-контейнером со всеми возможностями выравнивания, распределения и направления.

Например, если вы делаете кнопку, где рядом должны быть иконка и текст — inline-flex идеально подойдёт. Кнопка встанет в строку с другими, но внутри всё красиво выстроится по центру.

Когда что использовать:

  • flex — когда нужен полноценный блочный макет.
  • inline-flex — когда нужно красиво встроить что-то мелкое внутрь строки, но при этом управлять выравниванием.

Основные свойства flex-контейнера

Мы включили display: flex, и теперь элементы стали вести себя по-новому. Дальше разберёмся, как ими управлять: задать направление, выравнивание и распределение пустого пространства.

Разберём три ключевые группы свойств:

  • Направление оси (flex-direction) — по горизонтали, по вертикали, в обратную сторону.
  • Выравнивание по главной оси (justify-content).
  • Выравнивание по поперечной оси (align-items и align-content) — по вертикали или в пределах нескольких строк.

Flex-direction: управление направлением элементов

Это свойство определяет, в каком направлении будут выстраиваться флекс-элементы: в строку или в колонку, слева направо или наоборот. У него есть четыре режима:

flex-direction: row;        /* по умолчанию — в строку слева направо */
flex-direction: row-reverse; /* в строку справа налево */
flex-direction: column;      /* в колонку сверху вниз */
flex-direction: column-reverse; /* в колонку снизу вверх */

Выглядит это так:

👉 Главное, что нужно запомнить: flex-direction меняет основную ось (main axis), и все остальные свойства (justify-content, align-items) начинают работать относительно этой оси.

В инструментах разработчика в браузерах есть полезная штука. Если мы выберем флекс-контейнер в «Элементах», то в правом блоке стилей увидим иконку с прямоугольниками с выпадающим меню.

Здесь можно:

  • сразу увидеть, в каком направлении построена основная ось;
  • менять разные свойства и смотреть, что происходит на странице;
  • посмотреть, как меняются оси при переключении с row на column:

Это самый быстрый способ понять, как работает Flexbox не в теории, а в реальности.

justify-content (включая space-between)

Это свойство управляет распределением элементов по основной оси, то есть:

  • если flex-direction: row — элементы выравниваются по горизонтали;
  • если flex-direction: column — выравниваются по вертикали.

У этого свойства есть 6 режимов:

/* Элементы прижаты к началу оси (слева или сверху) */
justify-content: flex-start;
/* Элементы прижаты к концу оси (справа или снизу) */
justify-content: flex-end;
/* Все элементы выравниваются по центру оси */
justify-content: center;
/* Первый элемент у начала, последний — у конца, между остальными равные отступы */
justify-content: space-between;
/* Элементы равномерно распределены, но по краям отступы вдвое меньше */
justify-content: space-around;
/* Абсолютно равные отступы между всеми элементами, включая края */
justify-content: space-evenly;

Выглядит это так:

Три последних значения — space-between, space-around и space-evenly — могут поначалу вызывать путаницу. В маленьком контейнере они реально выглядят почти одинаково, но если контейнер широкий, различия бросаются в глаза. 

  • space-between — элементы максимально растягиваются по ширине контейнера. Отступы есть только между элементами, а по краям — ноль. Свойство используют в хедерах, навигации, футерах — когда вам нужно два блока по краям и что-то посередине. 
  • space-around — отступы есть и между элементами, и снаружи, но внешние — в два раза меньше. Каждый элемент получает одинаковое «поле» вокруг себя. Используют, если нужно немного воздуха между элементами, но не хочется, чтобы они прям прилипали к краям. 
  • space-evenly — пространство равномерно распределяется и между элементами, и снаружи. То есть, расстояние между элементами и между элементом и краем одинаковое. Используют в галереях, карточках товаров, списках с равными отступами. Даёт симметрию и баланс, особенно на широком контейнере.

align-items и align-content

Теперь рассмотрим выравнивание перпендикулярно основной оси.

  • align-items управляет выравниванием флекс-элементов в пределах одной строки/колонки;
  • align-content работает, когда у вас несколько строк (например, при flex-wrap: wrap) и управляет выравниванием всей группы строк.

align-items — это выравнивание флекс-элементов вдоль поперечной оси (обычно по вертикали), внутри одной линии раскладки. То есть работает в пределах одной «флекс-строки».

align-items: stretch;    /* по умолчанию — элементы растягиваются по высоте */
align-items: flex-start; /* прижаты к началу поперечной оси */
align-items: flex-end;   /* прижаты к концу */
align-items: center;     /* по центру */
align-items: baseline;   /* по базовой линии текста */

Здесь важно уточнить два нюанса:

  1. stretch не сработает, если у флекс-элемента явно задана высота height (или width при flex-direction: column). Растягиваться просто некуда — браузер следует заданному размеру.
  2. baseline имеет смысл только при наличии текста и особенно заметен, когда шрифты в элементах различаются по размеру. Если контент одинаковый, визуальной разницы с flex-start почти не будет.

Дальше рассмотрим align-content — это свойство управляет выравниванием групп флекс-элементов внутри контейнера по поперечной оси.

Оно работает, только если флекс-элементы переносятся на несколько строк (flex-wrap: wrap) и у контейнера задана фиксированная высота или ширина. Можно задать 6 режимов выравнивания:

/* Все строки прижаты к началу поперечной оси (обычно верх) */
align-content: flex-start;
/* Все строки прижаты к концу поперечной оси (обычно низ) */
align-content: flex-end;
/* Строки выровнены по центру поперечной оси */
align-content: center;
/* Первая строка у начала, последняя — у конца, между остальными — равные отступы */
align-content: space-between;
/* Равные отступы между строками, но по краям — в два раза меньше */
align-content: space-around;
/* Строки растянуты, чтобы занять всё пространство */
align-content: stretch;

Главное отличие align-content от align-items:

  • align-items работает внутри одной строки — выравнивает сами элементы.
  • align-content управляет положением всех строк целиком, как группы.

Свойства flex-элементов

До этого мы рассматривали свойства контейнера — display: flex, flex-direction, justify-content, align-items и т. д. Но у каждого отдельного элемента внутри контейнера тоже есть свои настройки. С их помощью можно управлять:

  • ростом или сжатием элементов (flex-grow, flex-shrink);
  • размером по умолчанию (flex-basis);
  • индивидуальным выравниванием (align-self);
  • порядком отображения (order).

Разберём их по порядку.

flex-grow, flex-shrink и flex-basis

Три свойства — flex-grow, flex-shrink и flex-basis — управляют тем, как флекс-элемент ведёт себя внутри контейнера: будет ли он растягиваться, сжиматься и какой размер будет использоваться в качестве базового.

В большинстве случаев их записывают через сокращённую форму flex, например: flex: 1; Такое сокращение расшифровывается как:

flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;

Это значит:

  • flex-grow: 1 — если в контейнере есть свободное место, элемент будет расти, причём в равной доле с другими, у кого тоже grow = 1.
  • flex-shrink: 1 — если места не хватает, элемент будет сжиматься, тоже в равной доле.
  • flex-basis: 0 — вот тут начинается магия: мы говорим, что начальный размер элемента — 0, и дальше весь расчёт идёт не от width, не от контента, а от этого нуля.

Допустим, у нас есть три элемента в контейнере и у всех прописано flex: 1; Сам контейнер шириной 600px. У каждого элемента flex-basis: 0, а flex-grow: 1, поэтому всё доступное пространство делится между ними поровну:

  • 600px / 3 = 200px каждому.

А если бы мы написали flex-basis: auto, то начальный размер брался бы из ширины элемента (width или по контенту). И уже после этого, если останется место, оно делилось бы по grow.

Другой пример: у нас есть несколько элементов во флекс-контейнере. И каждому из них мы задали разное значение свойства flex — кто-то растёт в два раза быстрее, кто-то не растёт вообще, а кто-то сжимается, но не меньше определённого минимума.

.item-1 {
  flex: 0 1 auto; /* не растёт, но может сжиматься до auto */
}
.item-2 {
  flex: 1; /* растёт равномерно, не учитывает начальный размер (0) */
}
.item-3 {
  flex: 2; /* растёт в два раза быстрее, чем элемент с flex: 1 */
}
.item-4 {
  flex: 1 1 auto; /* растёт, сжимается, начальная ширина — auto */
}
.item-5 {
  flex: 0 0 120px; /* фиксированная ширина, не растёт и не сжимается */
}
.item-6 {
  flex: auto; /* сокращение для 1 1 auto — растёт, сжимается, начальная ширина по содержимому */
}

Когда контейнер расширяется или сужается, элементы автоматически подстраиваются под доступное пространство, сохраняя заданные пропорции:

В реальной жизни чаще всего используют два сценария:

  • flex: 1 — чтобы элементы делили всё пространство поровну, без учёта их контента или ширины;
  • flex: auto или flex: 1 1 auto — когда нужно, чтобы элементы учитывали свой размер, но всё равно могли адаптироваться.

align-self для индивидуального выравнивания

Если align-items задаёт общее выравнивание по поперечной оси для всех флекс-элементов, то align-self позволяет переопределить это правило для одного конкретного элемента.

Это полезно, когда один блок нужно выровнять иначе, чем остальные. Значения align-self такие же, как у align-items: flex-start, flex-end, center, [/tags]stretch[/tags], baseline.

На примере ниже третий элемент не растягивается по высоте контейнера, а прижимается к нижнему краю — потому что у него явно задано align-self: flex-end. Остальные два следуют общему правилу align-items: stretch.

order: изменение порядка элементов

По умолчанию флекс-элементы располагаются в том порядке, в каком они идут в HTML. Но с помощью свойства order можно изменить визуальный порядок, не трогая саму разметку. Элементы с меньшим значением order идут первыми, с большим — позже. Значение по умолчанию — 0.

Например, у нас есть такой контейнер с тремя элементами:

<div class="flex-container">
   <div class="item item-1">1<br><small>order: 2</small></div>
   <div class="item item-2">2<br><small>order: 1</small></div>
   <div class="item item-3">3<br><small>order: 3</small></div>
 </div>

Если не прописывать никаких свойств, то элементы будут следовать друг за другом так:

Теперь задаём свойства и переопределяем порядок:

 .item-1 {
     order: 2;
   }
   .item-2 {
     order: 1;
   }
   .item-3 {
     order: 3;
   }

Теперь второй элемент (order: 1) окажется первым, затем order: 2, потом order: 3. А в HTML всё осталось без изменений.

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

Поэтому свойство order хорошо использовать для визуальных перестановок, когда порядок не важен с точки зрения логики (например, для карточек товаров). А если порядок важен — лучше перестроить HTML или использовать aria-атрибуты, чтобы пояснить структуру.

Практическое применение Flexbox

Мы разобрались, как работает Flexbox, теперь пора перейти к самому интересному. Ниже рассмотрим несколько типичных ситуаций, которые постоянно встречаются в интерфейсах.

Создание адаптивных навигационных меню

Когда нужно разместить пункты меню в одну строку, а при уменьшении экрана — аккуратно сжать, перекинуть на новую строку или выстроить в столбик, флекс становится незаменим.

Например, мы хотим сверстать адаптивное меню для журнала:

На десктопе у нас будет красивая строка с отступами. На мобилке — меню станет вертикальным списком (в стиле бургер-меню). Такой подход можно реализовать через медиазапросы:

.menu {
     /* Строим флекс-контейнер */
     display: flex;
     /* По умолчанию располагаем в строку */
     flex-direction: row;
     /* Разрешаем перенос */
     flex-wrap: wrap;
     /* Центрируем по горизонтали */
     justify-content: center;
     /* Отступы между пунктами */
     gap: 24px;
     padding: 16px 32px;
     background-color: #1b2b4c;
     border-radius: 9999px;
     list-style: none;
     color: white;
   }

   /* Адаптив: при ширине экрана до 600px переключаемся в колонку */
   @media (max-width: 600px) {
     .menu {
       flex-direction: column;
       gap: 12px;

       /* Меняем радиус, чтобы фон выглядел нормально */
       border-radius: 24px;
       /* Растягиваем элементы по ширине */
       align-items: stretch;
       padding-right: 1em;
     }
   }

Если вы добавляете кнопку бургер-меню и хотите, чтобы меню появлялось и скрывалось, — это уже следующий уровень с JavaScript. Но для базовой адаптивной вёрстки достаточно медиазапросов и flex-direction: column.

Вёрстка карточек товаров

Карточки товаров (статей, услуг или чего угодно) — классический пример применения flex. При этом сам родительский контейнер может не быть флекс-контейнером — достаточно, чтобы внутри каждой карточки была своя flex-структура. Это позволяет удобно выравнивать текст, иконки, теги и другие элементы по вертикали и горизонтали, задавать отступы и управлять порядком блоков.

Например, карточка для статьи — это компактный элемент с чёткой структурой: заголовок, краткое описание и список тегов. Чтобы всё выглядело аккуратно и адаптивно, сделаем такую разметку:

<div class="card">
  <div class="card-content">
    <h3>Можно ли программировать на телефоне?</h3>
    <p class="desc">Как ни странно, можно</p>
    <div class="tags">
      <span class="tag">easy</span>
      <span class="tag">это как</span>
    </div>
  </div>
</div>

Карточка состоит из нескольких элементов:

  • Вся карточка обёрнута в div.card: здесь мы задаём общий фон, скругления, отступы.
  • Внутри блока card-content мы включим flex и выстроим контент в колонку.
  • Заголовок (h3) и описание (p) — это блочные элементы, им не нужны обёртки.
  • А вот теги — это короткие фрагменты текста, поэтому используем строчный элемент span. Они идут внутри блочного элемента div.tags, который мы сделаем флекс-контейнером с gap, чтобы настроить отступы между тегами.

Теперь задаём стили, чтобы карточка выглядела опрятно и адаптивно:

/* Обёртка карточки */
   .card {
     /* Светло-серый фон */
     background: #f1f1f1;
     /* Внутренние отступы */
     padding: 24px;
     /* Скруглённые углы */
     border-radius: 24px;
     /* Ограничиваем максимальную ширину */
     max-width: 320px;
   }
   /* Содержимое карточки */
   .card-content {
     /* Включаем флекс-контейнер */
     display: flex;
     /* Располагаем элементы в столбик */
     flex-direction: column;
     /* Пространство распределяется равномерно */
     justify-content: space-between;
     /* Контейнер растягивается по высоте */
     height: 100%;
     /* Отступы между дочерними элементами */
     gap: 16px;
   }
   /* Контейнер для тегов */
   .tags {
     /* Включаем флекс */
     display: flex;
     /* Отступы между тегами */
     gap: 12px;
     /* Разрешаем перенос тегов на новую строку */
     flex-wrap: wrap;
   }
   .tag {
     /* Тёмный фон */
     background: #1b2b4c;
     /* Белый текст */
     color: #fff;
     /* Отступы внутри тега */
     padding: 4px 12px;
     /* Скругление */
     border-radius: 9999px;
     /* Размер текста */
     font-size: 14px;
   }

В результате получается так:

Если мы откроем инструменты разработчика, то в инспекторе будет видно, какие элементы — это флекс-контейнеры. В HTML-разметке рядом с ними появляется кнопка flex. Если её нажать, то в вёрстке увидим направляющие линии, которые помогают понять поведение элементов внутри контейнера.

Центрирование элементов по вертикали и горизонтали

Один из главных мемов с фронтендерских собеседований: «Как отцентрировать элемент?»

Flexbox очень упрощает то, что раньше приходилось делать через костыли, таблицы или абсолютное позиционирование. Теперь это делается буквально в пару строк:

.container {
  /* Включаем флекс-контейнер */
  display: flex;
  /* Вырыванием по горизонтали */
  justify-content: center; 
  /* Вырыванием по вертикали */
  align-items: center;    
  height: 300px;
  background: #1b2b4c;
  border-radius: 16px;
  color: white;
}
<div class="container">
  Центр
</div>

Полезные техники и свойства

Теперь разберёмся с приёмами, которые делают вёрстку удобной, гибкой и адаптивной. Это базовые штуки, которые важно знать, чтобы уверенно использовать Flexbox в реальных проектах.

Использование flex-wrap для переноса элементов

По умолчанию flex-wrap стоит в значении nowrap — то есть все элементы пытаются уместиться в одну строку. Это может привести к «сплющиванию» элементов при уменьшении экрана. Особенно плохо это выглядит в навигационных меню, списках тегов или карточках.

Чтобы разрешить перенос на следующую строку, просто указываем flex-wrap: wrap.

Например, у нас есть контейнер с тегами:

<div class="tag-list">
  <span class="tag">JavaScript</span>
  <span class="tag">CSS</span>
  <span class="tag">Frontend</span>
  <span class="tag">Adaptive</span>
  <span class="tag">UI/UX</span>
  <span class="tag">Производительность</span>
</div>

Чтобы они не наползали друг на друга, задаём им такие стили:

/* Контейнер для тегов */
.tag-list {
  /* Флекс + перенос */
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}
/* Стиль тега */
.tag {
  background-color: #1b2b4c;
  color: white;
  padding: 4px 12px;
  border-radius: 9999px;
  font-size: 14px;
}

Теперь при уменьшении размера экрана теги будут переноситься на другую строку:

Работа с flex-gap (современная альтернатива margin)

Раньше, чтобы расставить отступы между флекс-элементами, нужно было мучиться с margin: margin-right, margin-bottom, потом обнулять значение у последнего. А если элементы переносились на другую строку — всё ломалось.

Теперь есть нормальный способ — свойство gap. Он работает прямо в flex и задаёт расстояние между элементами по горизонтали и вертикали.

Например, у нас есть группа кнопок во флекс-контейнере:

 <div class="btn-group">
   <button>Лайк</button>
   <button>Шер</button>
   <button>Подписка</button>
 </div>

Задаём стили:

/* Группа кнопок */
.btn-group {
  /* Включаем флекс */
  display: flex;
  /* Расстояние между кнопками */
  gap: 12px;
}

В одну строчку мы добились равного расстояния между кнопками:

А если нужно управлять отступами отдельно по горизонтали и вертикали, можно напрямую прописывать column-gap и row-gap. Например, column-gap: 20px задаст горизонтальный интервал между элементами, расположенными в колонках — даже если это флекс-контейнер с переносом.

Оптимальные сочетания свойств

Flexbox хорош тем, что из нескольких свойств можно собрать универсальные шаблоны для вёрстки блоков. Ниже разберём наиболее полезные комбинации, которые стоит запомнить: они встречаются почти в каждом проекте.

Выравнивание по центру экрана

.centered {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 60vh;
}

Удобный способ, чтобы разместить контент строго по центру экрана. Часто используется для экранов «пусто/загрузки» или в лендингах, чтобы подчеркнуть главный блок.

Хедер с кнопкой справа

<header class="header">
  <a class="logo">Brand</a>
  <nav>...</nav>
  <div class="header__spacer"></div>
  <button>Войти</button>
</header>
.header {
  display: flex;
  align-items: center;
  gap: 12px;
}
.header__spacer {
  /* Отправляет кнопку вправо */
  margin-left: auto; 
}

Стандартный вариант: логотип слева, навигация рядом, а кнопка «Войти» уезжает вправо. Хитрость в использовании «пустого» блока-распорки с margin-left: auto. Такой паттерн отлично масштабируется: можно добавить и бургер-меню, и иконки, и переключатели языка — margin-left: auto всегда толкает блок к правому краю.

Ряд карточек, которые красиво переносятся

.cards {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}
.card {
/* Примерно 3–4 в ряд, на мобилках по одной */
  flex: 1 1 280px; 
}

Карточки занимают от 280 пикселей и равномерно растягиваются, чтобы в ряд влезло несколько штук. При уменьшении экрана они сами переносятся и становятся по одной. Работает на любом разрешении.

Вообще, профессиональные верстальщики редко набирают всё с нуля. Вместо этого они:

  • используют сниппеты (шаблоны кода) в редакторе — например, flexwrap → автозаполняется display: flex; flex-wrap: wrap;
  • создают свои фрагменты для часто используемых конструкций (.container-center, .card, .btn);
  • подключают плагины для быстрой выставки готовых структур.

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

Частые проблемы и их решения

Если флекс ведёт себя странно — не паникуйте. Откройте devtools, выделите нужный элемент и посмотрите, как считаются размеры и какие свойства применяются. Дальше разберём самые распространённые проблемы.

Почему не работают flex-свойства?

Если элементы в флекс-контейнере не растягиваются, не сжимаются или ведут себя не так, как задумано, то, скорее всего, дело в свойствах flex-grow, flex-shrink и flex-basis. Именно они управляют тем, как элемент занимает пространство.

Например, у нас есть карточки, где мы явно прописываем ширину в 300px:

.card {
  flex: 1 1 300px;
}

На первый взгляд кажется, что ширина будет строго 300px. Но на деле карточки могут и растягиваться, и сжиматься. Почему?

Потому что 300px здесь — это базовая (начальная) ширина (flex-basis), а единицы в flex-grow и flex-shrink говорят: «можно адаптироваться под доступное пространство». Поэтому элемент будет вести себя гибко, а не держать точную ширину.

Чтобы задать жёсткую ширину, нужно отключить гибкость так:

.card {
  flex: 0 0 300px;
}

Нулевые параметры запрещают рост и сжатие, 300px задаёт жёсткую ширину, как будто вы написали width: 300px.

Свойства flex часто вызывают путаницу, особенно если писать их в сокращённой форме. Лучший способ разобраться — открыть инструменты разработчика и понаблюдать, как меняется размер и поведение элементов при разных значениях.

Неожиданное растягивание по высоте

По умолчанию у align-items стоит режим stretch, и все флекс-элементы вытягиваются по высоте контейнера. Это не баг, а фича. Если нужно, чтобы высота считалась по контенту, явно укажите:

.container {
  align-items: flex-start; /* или center */
}

Так каждый блок будет занимать столько места, сколько ему реально нужно.

Как избежать «схлопывания» контейнера

Иногда бывает, что контейнер как будто «пропадает» — у него нет видимой высоты, хотя внутри есть содержимое. В инспекторе браузера контейнер отображается как тонкая полоска. 

Например, у нас есть серый .container, в котором располагается синий блок .box, но видим только верхнюю границу родительского контейнера:

Это называется «схлопывание по высоте». Оно происходит, когда контейнер не получает высоту от вложенных элементов. Чаще всего это случается, если:

  • Внутри находятся блоки с position: absolute — они выпадают из потока, и родитель их не учитывает.
  • Вложенные элементы используют float, и без дополнительной обёртки не передают высоту родителю.
  • Внутри просто нет контента или он имеет нулевую высоту.

В нашем случае дочерний элемент .box абсолютно спозиционирован. Он выпадает из потока, и родитель .container не получает от него высоту. Чтобы пофиксить это, можно сделать так:

  • Добавить контейнеру min-height, если знаете, сколько примерно нужно:
.container {
  min-height: 120px;
}
  • Проверить позиционирование вложенных элементов. Если они абсолютно спозиционированы, родитель их «не видит». Возможно, стоит изменить логику отображения элементов.
  • Проверить, что хотя бы один элемент внутри имеет явную высоту или контент, который её задаёт.

Совет для отладки: временно добавьте рамку (border) или фоновый цвет, чтобы убедиться, где именно находится контейнер и есть ли у него высота. Это поможет быстрее отследить проблему.

Совместимость с браузерами и префиксы

Flexbox поддерживается в большинстве современных браузеров:

Вендорные префиксы (-webkit-, -ms-) сегодня почти не требуется добавлять вручную. Если вы используете автопрефиксер (например, через PostCSS), то нужные префиксы подставятся автоматически.

Но если вы разрабатываете под Smart TV, старые android-браузеры или корпоративные устройства, где могут встречаться древние версии WebKit или IE, — стоит проверить актуальность поддержки на caniuse.com.

Если вы хотите убедиться, что флекс-раскладка применится только там, где это точно поддерживается, используйте конструкцию @supports:

@supports (display: flex) {
      .container {
          display: flex;
      }
  }

Это называется feature query, так мы говорим браузеру: «Применяй эти стили, только если ты точно умеешь работать с display: flex». Такой подход особенно полезен, если вы подключаете запасной макет для старых браузеров и хотите избежать конфликтов.

Бонус для читателей

Скидка 20% на все курсы Практикума до 30 ноября! «Чёрная пятница» и такие скидки бывают раз в год.

Вам слово

Приходите к нам в соцсети поделиться своим мнением о статье и почитать, что пишут другие. А ещё там выходит дополнительный контент, которого нет на сайте — шпаргалки, опросы и разная дурка. В общем, вот тележка, вот ВК — велком!

Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Вам может быть интересно
easy
[anycomment]
Exit mobile version