Что делает 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-wrap | row 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: 1 | 1 1 0% | Начинает с нуля и берет равную долю пространства |
flex: auto | 1 1 auto | Размер по содержимому плюс доля оставшегося пространства |
flex: none | 0 0 auto | Ровно по содержимому или ширине, не растет и не сжимается |
flex: 2 | 2 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 как блоки.