Flex CSS: примеры меню, колонок и центрирования блоков

Flexbox в CSS выравнивает блоки, переносит их на новые строки и меняет порядок элементов. Задайте родителю display: flex, затем настройте оси, расстояния и размеры. В статье собраны рабочие примеры меню, колонок одинаковой высоты, центрирования и адаптивного порядка.

Как создать flex-контейнер

Правило display: flex превращает родителя во flex-контейнер. Его непосредственные дочерние элементы становятся flex-элементами. Создайте общий контейнер с тремя блоками:

<div class="container">
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
</div>

Добавьте правила в CSS-файл, подключенный к странице:

.container {
  display: flex;
}

.box {
  width: 200px;
  height: 200px;
  margin: auto;
  background: #eee;
}

Три блока расположатся в ряд внутри родителя. Автоматические отступы разделят свободное пространство вокруг элементов поровну.

Когда контейнеру не хватает места, Flexbox может уменьшить ширину блоков. Правило width само по себе не запрещает сжатие элемента.

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

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

display

Включите гибкую раскладку внутри выбранного элемента через display: flex:

.container {
  display: flex;
}

Контейнером может стать div, список ul или другой HTML-элемент.

flex-direction

Направление главной оси задает правило flex-direction. При горизонтальном письме слева направо значения работают так:

  • row располагает элементы слева направо.
  • row-reverse располагает элементы справа налево.
  • column располагает элементы сверху вниз.
  • column-reverse располагает элементы снизу вверх.
.container {
  display: flex;
  flex-direction: row;
}

При другом направлении письма начало и конец строки меняются. Значения row и row-reverse учитывают направление текста.

flex перенос на новую строку: свойство flex-wrap

По умолчанию Flexbox размещает элементы в одной строке. Перенос при нехватке места включает свойство flex-wrap.

.container {
  display: flex;
  flex-wrap: wrap;
}
  • nowrap оставляет элементы в одной строке.
  • wrap переносит элементы на следующую строку.
  • wrap-reverse переносит элементы и меняет направление строк по поперечной оси.

При row новые строки идут вниз. Значение wrap-reverse размещает их снизу вверх, но не меняет порядок элементов внутри строки.

flex-flow

Два правила можно объединить записью flex-flow, которая задает направление и перенос:

.container {
  display: flex;
  flex-flow: row wrap;
}

Такая запись располагает элементы в строку и переносит их при нехватке места.

gap

Промежутки между flex-элементами задает свойство gap. Оно не добавляет внешний отступ перед первым и после последнего элемента.

.container {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

Значения row-gap и column-gap задают расстояния отдельно по двум осям:

.container {
  row-gap: 24px;
  column-gap: 16px;
}

Используйте gap, когда расстояние должно сохраняться между элементами строки и между строками. Для новых макетов этот способ проще комбинации отрицательных полей и внешних отступов.

justify-content

Свободное пространство вдоль главной оси распределяет justify-content. При row правило управляет горизонтальным размещением, при column – вертикальным.

  • flex-start собирает элементы у начала главной оси.
  • flex-end собирает элементы у конца главной оси.
  • center размещает группу элементов по центру.
  • space-between оставляет одинаковые промежутки между элементами и прижимает крайние блоки к краям.
  • space-around распределяет пространство вокруг элементов.
  • space-evenly задает одинаковые промежутки между элементами и у краев.
.container {
  display: flex;
  justify-content: space-between;
}

align-items

Положение элементов вдоль поперечной оси каждой строки меняет align-items. При row и горизонтальном письме это вертикальное выравнивание.

  • flex-start выравнивает элементы по началу поперечной оси.
  • flex-end выравнивает элементы по концу поперечной оси.
  • center центрирует элементы по поперечной оси.
  • baseline выравнивает элементы по базовой линии текста.
  • stretch растягивает элементы с автоматическим поперечным размером в пределах строки.
.container {
  display: flex;
  align-items: center;
}

align-content

При переносе свободное место можно распределить между строками контейнера. Для этого используйте align-content по поперечной оси.

.container {
  display: flex;
  flex-wrap: wrap;
  align-content: space-between;
  min-height: 500px;
}
  • flex-start собирает строки у начала поперечной оси.
  • flex-end собирает строки у конца поперечной оси.
  • center размещает строки по центру контейнера.
  • space-between распределяет свободное место между строками.
  • space-around распределяет свободное место вокруг строк.
  • stretch растягивает строки по поперечной оси.

При flex-wrap: nowrap контейнер содержит одну строку, поэтому align-content не меняет ее положение.

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

Свойства дочерних элементов меняют их порядок, базовый размер, рост и сжатие. Назначайте эти правила самим блокам через класс или другой селектор.

order

По умолчанию flex-элементы следуют порядку HTML-разметки. Значение order меняет их визуальное размещение: браузер сначала показывает элементы с меньшим значением.

.box:nth-child(1) {
  order: 2;
}

.box:nth-child(2) {
  order: 3;
}

.box:nth-child(3) {
  order: 1;
}

Этот код разместит блоки в последовательности 3, 1, 2. Одинаковые значения order сохраняют взаимный порядок элементов из HTML.

Свойство order не меняет DOM и порядок клавиатурного обхода. Не переставляйте им шаги формы или другую смысловую последовательность.

flex-basis

Исходный размер элемента по главной оси задает flex-basis. При горизонтальном направлении правило определяет базовую ширину до распределения свободного места.

.box {
  flex-basis: 200px;
}

.box.wide {
  flex-basis: 320px;
}

Значение auto берет размер из свойства ширины или содержимого. Значение 0 убирает вклад исходной ширины из распределения свободного места, но ограничения вроде min-width влияют на результат.

flex-grow

Свободное место можно разделить между элементами через flex-grow. Его начальное значение 0 запрещает элементу забирать свободное место.

.container {
  display: flex;
}

.box {
  flex-basis: 200px;
  flex-grow: 1;
}

.box:nth-child(2) {
  flex-grow: 2;
}

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

Чтобы распределить свободное место пропорционально 1:2:1, задайте всем блокам одинаковый flex-basis: 0 и значения роста 1, 2 и 1.

flex-shrink

При нехватке места коэффициент flex-shrink управляет сжатием элементов. Начальное значение 1 разрешает сжатие, значение 0 запрещает его.

.container {
  display: flex;
  width: 500px;
}

.box {
  flex-basis: 200px;
  flex-shrink: 1;
  min-width: 0;
}

.box:nth-child(2) {
  flex-shrink: 0;
}

Три блока с базой 200px требуют 600px, но контейнер вмещает 500px. Второй блок сохранит базовый размер, а соседние элементы примут на себя сжатие.

При разных базовых размерах браузер учитывает произведение базы на коэффициент сжатия. Поэтому одинаковый flex-shrink не гарантирует одинаковую потерю пикселей.

Сокращенная запись flex

Свойство flex объединяет flex-grow, flex-shrink и flex-basis:

.box {
  flex: 1 1 0;
}

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

Шпаргалка по свойствам Flexbox

Сначала задайте свойства контейнеру, затем настройте размеры и поведение отдельных элементов. Таблица помогает быстро выбрать нужное правило.

ЗадачаСвойствоЧто меняет
Включить FlexboxdisplayДелает элемент flex-контейнером.
Выбрать направлениеflex-directionЗадает строку или колонку.
Разрешить переносflex-wrapПереносит элементы на новые строки.
Объединить направление и переносflex-flowЗадает два свойства одной записью.
Задать промежуткиgapРазделяет элементы и строки без внешних отступов.
Распределить место по главной осиjustify-contentМеняет положение группы и промежутки.
Выровнять элементы в строкеalign-itemsМеняет положение элементов по поперечной оси.
Распределить строкиalign-contentМеняет положение строк при переносе.
Изменить визуальный порядокorderПереставляет элементы без изменения HTML.
Задать исходный размерflex-basisОпределяет базовый размер по главной оси.
Разрешить ростflex-growРаспределяет свободное место между элементами.
Управлять сжатиемflex-shrinkОпределяет потерю размера при нехватке места.

Как сверстать меню навигации с Flexbox

Flexbox распределяет пункты меню с учетом их содержимого и доступного места. Разрешите перенос ссылок, а на узком экране переключите список в колонку.

Добавьте список ссылок внутрь элемента nav:

<nav class="site-navigation">
  <ul>
    <li><a href="#home">Home</a></li>
    <li><a href="#services">Services</a></li>
    <li><a href="#products">Products</a></li>
    <li><a href="#about">About</a></li>
    <li><a href="#contact">Contact</a></li>
  </ul>
</nav>

Задайте списку гибкую раскладку:

.site-navigation ul {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: space-around;
  list-style: none;
  margin: 0;
  padding: 0;
  background: #eee;
}

.site-navigation a {
  display: block;
  padding: 1rem;
  color: #333;
  text-align: center;
  text-decoration: none;
}

.site-navigation a:hover,
.site-navigation a:focus-visible {
  background: #d4d4d4;
}

@media (max-width: 600px) {
  .site-navigation ul {
    flex-direction: column;
  }
}

При ширине окна больше 600px меню располагается горизонтально. При ширине 600px и меньше список выстраивается вертикально.

Сузьте окно браузера и проверьте смену направления списка. Ссылки должны оставаться читаемыми и доступными с клавиатуры.

Как сделать столбцы одинаковой высоты

Если текста в колонках разное количество, фон коротких блоков может обрываться раньше. Растяните колонки до высоты общей строки с помощью align-items: stretch.

Добавьте три колонки с разным количеством текста:

<div class="column-container">
  <div class="column">
    <p>Основной контент.</p>
    <p>Дополнительный абзац увеличивает высоту первой колонки.</p>
  </div>
  <div class="column">
    <p>Боковая панель.</p>
  </div>
  <div class="column">
    <p>Дополнительные сведения.</p>
  </div>
</div>
.column-container {
  display: flex;
  align-items: stretch;
  gap: 16px;
}

.column {
  box-sizing: border-box;
  flex: 1 1 0;
  min-width: 0;
  padding: 2rem;
}

.column:nth-child(1) { background: #ffd8d8; }
.column:nth-child(2) { background: #d8e8ff; }
.column:nth-child(3) { background: #ddf5dd; }

@media (max-width: 600px) {
  .column-container {
    flex-direction: column;
  }
}

На широком экране нижние границы колонок совпадут. Для растяжения не задавайте блокам фиксированную высоту.

После перехода к вертикальному направлению высота каждой колонки зависит от содержимого. Свойство min-width: 0 разрешает длинному содержимому сжимать flex-элемент.

Как центрировать блок по двум осям

Для центрирования элемента по поперечной оси задайте контейнеру align-items: center. Добавьте justify-content: center, чтобы расположить его по центру обеих осей.

<div class="vertical-container">
  <div class="vertical-content">Блок по центру</div>
</div>
.vertical-container {
  display: flex;
  min-height: 500px;
  align-items: center;
  justify-content: center;
  background: #eee;
}

.vertical-content {
  box-sizing: border-box;
  max-width: 100%;
  padding: 3rem;
  background: #fff;
  text-align: center;
}

Блок окажется в центре серой области высотой не меньше 500px. Если родитель совпадает по высоте с содержимым, вертикальное смещение будет незаметным.

Как изменить порядок элементов в медиазапросе

Медиазапрос позволяет менять визуальный порядок блоков на узком экране. Все переставляемые элементы должны быть непосредственными детьми одного flex-контейнера.

Используйте общий контейнер с пятью областями:

<div class="page-layout">
  <header class="site-header">Заголовок</header>
  <aside class="left-sidebar">Левая панель</aside>
  <main class="main-content">Основной контент</main>
  <aside class="right-sidebar">Правая панель</aside>
  <footer class="site-footer">Подвал</footer>
</div>
.page-layout {
  display: flex;
  flex-wrap: wrap;
}

.site-header,
.site-footer {
  flex: 0 0 100%;
}

.left-sidebar,
.right-sidebar {
  flex: 1 1 0;
  min-width: 0;
}

.main-content {
  flex: 3 1 0;
  min-width: 0;
}

@media (max-width: 600px) {
  .page-layout {
    flex-direction: column;
    flex-wrap: nowrap;
  }

  .page-layout > * {
    flex: 0 1 auto;
  }

  .site-header { order: 2; }
  .main-content { order: 1; }
  .left-sidebar { order: 4; }
  .right-sidebar { order: 3; }
  .site-footer { order: 5; }
}

При ширине 600px и меньше области выстроятся так:

  • Основной контент.
  • Заголовок.
  • Правая боковая панель.
  • Левая боковая панель.
  • Подвал.

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

Поддержка браузерами

Современные браузеры поддерживают Flexbox, но совместимость зависит от конкретного свойства и версии браузера. Таблица совместимости на странице display в документации MDN показывает связанные спецификации и доступность свойства.

Проверяйте макет в целевых браузерах, если проект рассчитан на старую программную среду. Для новых макетов используйте стандартные свойства CSS из примеров статьи без устаревших префиксов.

Ошибки при работе с Flexbox

Проект Flexbugs на GitHub собирает описания ошибок Flexbox и способы их обхода. Учитывайте, к каким браузерам относится конкретная ошибка.

Если блок не сжимается, проверьте его минимальный размер. Длинная строка или фиксированная ширина содержимого могут создавать переполнение. Для сжимаемого flex-элемента задайте min-width: 0, а для длинного текста добавьте overflow-wrap: anywhere.

Совет от нашей редакции: меняйте по одному свойству за раз. Проверяйте макет с длинным текстом и при ширине окна 600px.

Комментарии

Оставьте свой комментарий
ДБ
девочка без имени

Спасибо, классная статья