Menu

Flexbox CSS: display flex, оси, выравнивание и flex

Flexbox выстраивает элементы в строку или колонку и управляет тем, как они делят пространство и выравниваются. Разберем display: flex, главную и поперечную оси, все свойства контейнера, flex-grow, flex-shrink и flex-basis в живой песочнице, которая измеряет, куда попадает каждый элемент.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Что делает display: flex

Задайте родителю display: flex, и его прямые дочерние элементы выстроятся в строку, бок о бок, и растянутся до одинаковой высоты. Это одно объявление заменяет float, inline-block и большинство трюков с позиционированием для раскладки ряда элементов.

В первом блоке каждый div занимает целую строку. Во втором три элемента стоят в одной строке, каждый шириной только в свое содержимое, а One и Three растягиваются до высоты Two. Изменился только родитель: display: flex задается контейнеру, а не элементам.

Песочница flexbox

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

Что попробовать:

  • justify-content: space-between: элемент 1 оказывается на x 0, а элемент 3 касается дальнего края.
  • align-items: center: три элемента сохраняют свою высоту, а их центры выравниваются. При stretch по умолчанию у элемента 1 нет своей высоты, и он заполняет все 170px контейнера.
  • flex-direction: column: теперь justify-content двигает элементы по вертикали, а align-items по горизонтали. Оба свойства следуют осям, а не экрану.

Главная и поперечная оси

У каждого flex-контейнера две оси. Главная ось это направление, в котором идут элементы, его задает flex-direction. Поперечная ось идет поперек нее.

flex-directionГлавная осьПоперечная осьjustify-content двигает элементыalign-items двигает элементы
row (по умолчанию)горизонтальная, в порядке чтениявертикальнаяпо горизонталипо вертикали
row-reverseгоризонтальная, обратнаявертикальнаяпо горизонталипо вертикали
columnвертикальная, сверху внизгоризонтальнаяпо вертикалипо горизонтали
column-reverseвертикальная, снизу вверхгоризонтальнаяпо вертикалипо горизонтали

На странице справа налево (dir="rtl") row начинается от правого края, потому что главная ось следует направлению письма.

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

Они задаются элементу с display: flex:

СвойствоЧто делаетПо умолчанию
flex-directionСтрока или колонка и в какую сторонуrow
flex-wrapПереходят ли элементы на новую строку, когда им не хватает местаnowrap
flex-flowСокращение для flex-direction и flex-wraprow nowrap
justify-contentРазмещение и промежутки вдоль главной осиnormal (работает как flex-start)
align-itemsРазмещение элементов вдоль поперечной осиnormal (работает как stretch)
align-contentПромежутки между строками, когда элементы переносятсяnormal
gapПромежуток между элементами (row-gap, column-gap)0

У justify-content и align-items своя страница со всеми значениями: justify-content и align-items. Перенос и направление разобраны на странице про flex-wrap.

Свойства элементов: flex-grow, flex-shrink, flex-basis

Они задаются дочерним элементам и решают, как те делят ширину контейнера:

  • flex-basis: размер, с которого элемент начинает до раздела свободного пространства (auto означает «возьми мою ширину или мое содержимое»).
  • flex-grow: сколько долей оставшегося пространства берет элемент. 0 означает, что он никогда не растет.
  • flex-shrink: сколько элемент уступает, когда места не хватает. 0 означает, что он никогда не сжимается.

Сокращенное свойство flex задает все три:

Вы пишетеЭто значитПоведение
flex: initial (по умолчанию)0 1 autoРазмер по содержимому, может сжиматься, никогда не растет
flex: 11 1 0%Начинает с нуля и берет равную долю пространства
flex: auto1 1 autoРазмер по содержимому плюс доля оставшегося пространства
flex: none0 0 autoРовно по содержимому или ширине, не растет и не сжимается
flex: 22 1 0%Вдвое большая доля, чем у элемента с flex: 1

Каждая строка шириной 480px внутри padding, а два промежутка по 8px оставляют элементам 464px. Выведенные ширины показывают, как пространство поделено: около 155px каждому в первой строке, 116 + 232 + 116 во второй (элемент с flex: 2 получает вдвое больше каждого соседа) и 100 + 372 в третьей, где элемент с flex: none сохраняет свою ширину, а другой забирает все остальное.

Реальные раскладки на flexbox

Шапка с логотипом в начале и ссылками в конце это самая частая flex-раскладка. margin-inline-start: auto у одного элемента забирает все свободное пространство перед ним и отодвигает его и все, что идет после, в конец:

align-items: center выравнивает более крупный текст логотипа со ссылками, а gap расставляет промежутки между ссылками без отступов, которые пришлось бы убирать у последней.

Второй повседневный прием это медиа-строка: иконка фиксированного размера и текст, который занимает остальное и переносится внутри своей колонки.

Гарантию дает flex: none. Flex-элементы по умолчанию сжимаются, поэтому если убрать его у круга и заодно убрать flex: 1 у текста, абзац сожмет круг примерно до 23px в ширину: получится овал. Чтобы выровнять по центру один элемент в блоке, flexbox нужны две строки (justify-content: center; align-items: center); на странице выравнивание div по центру это сравнивается с другими способами.

order и доступность

Свойство order и направления -reverse меняют то, где элементы отображаются, а не их место в HTML. Программы чтения с экрана и клавиша Tab по-прежнему следуют порядку HTML, поэтому пользователь клавиатуры может перепрыгнуть с первой ссылки на экране на последнюю. Используйте их только для оформления; когда порядок что-то значит, меняйте HTML.

Flexbox или grid

Flexbox работает в одном направлении за раз: элементы в строке берут размер от содержимого, а вторая строка (при переносе) не выравнивается с первой. Grid работает в двух: вы задаете колонки и строки, и элементы встают в них. Навигация, панель инструментов или строка формы это flexbox; галерея или страница с боковой панелью это grid.

Частые ошибки

  • display: flex у элемента, а не у родителя. display: flex получает контейнер; его дочерние элементы это flex-элементы.
  • Ожидание, что align-items сдвинет элементы по вертикали без высоты. Если контейнер высотой только с самый высокий элемент, двигать некуда. Задайте контейнеру высоту; иначе свойство работает, просто ему нечего делать.
  • Текст вылезает, а не сжимается. У flex-элементов min-width: auto. Добавьте min-width: 0 элементу, который должен сжиматься.
  • flex: 1, а ширины разные. Элементы с flex: 1 делят пространство поровну, но элемент с содержимым, которое не помещается (длинный URL, изображение), не сожмется меньше него. min-width: 0 решает и это.
  • Margin между элементами. Используйте gap у контейнера; он ставится только между элементами.
  • Лишняя вложенность flex. Flex-элементами являются только прямые дочерние элементы. Внуки подчиняются обычной раскладке, если их собственный родитель тоже не display: flex.

Часто задаваемые вопросы

Что делает display: flex?

Превращает элемент во flex-контейнер. Его прямые дочерние элементы становятся flex-элементами и по умолчанию выстраиваются в строку, бок о бок, растянутые до одинаковой высоты, а свойства вроде justify-content, align-items и gap управляют тем, как они делят пространство.

Что означает flex: 1?

flex: 1 это сокращение для flex: 1 1 0%: элемент может расти (flex-grow: 1), может сжиматься (flex-shrink: 1) и начинает с нулевого размера (flex-basis: 0%). Элементы, у которых у всех flex: 1, делят свободное пространство поровну, поэтому получаются одинаковой ширины, если их содержимое помещается.

Чем justify-content отличается от align-items?

justify-content размещает элементы вдоль главной оси (по горизонтали в строке), а align-items вдоль поперечной (по вертикали в строке). При flex-direction: column оси меняются местами, и justify-content становится вертикальным.

Что выбрать: flexbox или grid?

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

Почему flex-элемент вылезает за контейнер?

У flex-элемента по умолчанию min-width: auto, поэтому он не сжимается уже самого длинного слова или самого широкого дочернего элемента. Задайте элементу min-width: 0 (или overflow: hidden), чтобы он мог сжиматься, например чтобы заработал text-overflow: ellipsis.

Работает ли flexbox со строчными элементами вроде span?

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

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ