Как устроен Flexbox
Две оси, и всё крутится вокруг них
display: flex включает раскладку, у которой есть главная ось и поперечная. flex-direction решает, куда смотрит главная: row — вдоль строки, column — вниз. Поперечная всегда перпендикулярна ей. Все остальные свойства контейнера просто говорят, что делать вдоль одной из этих осей.
justify-content — это главная ось
justify-content распределяет элементы вдоль главной оси. При row это горизонталь, при column — вертикаль, и именно здесь чаще всего путаются: «выровнять по центру» на колонке делает не justify-content, а align-items.
space-between прижимает первый и последний элементы к краям, space-around даёт каждому одинаковые поля с обеих сторон, поэтому крайние отступы выглядят вдвое меньше внутренних, а space-evenly делает все промежутки одинаковыми.
align-items — это поперечная ось
Значение по умолчанию — stretch: элементы растягиваются на всю высоту ряда. Именно поэтому карточки в ряду получаются одинаковой высоты без всякого height: 100%. Как только вы поставите center или flex-start, каждый элемент снова будет высотой со своё содержимое.
wrap решает, будет ли второй ряд
nowrap — значение по умолчанию в CSS, и оно означает «в один ряд любой ценой»: элементы сжимаются ниже своей ширины. wrap разрешает перенос, и тогда ширина элемента начинает что-то значить.
gap читается с рядов
gap: 16px 24px — это 16 между рядами и 24 между элементами в ряду, именно в таком порядке. Если числа одинаковые, пишут одно. По внешним краям контейнера промежутка нет никогда.
Частые вопросы о Flexbox
Flexbox или Grid?
Flexbox — когда элементы стоят вдоль одной оси и сами распределяют место: панель кнопок, шапка, ряд тегов. Grid — когда раскладка описана в двух направлениях сразу, строками и колонками. Галерея карточек одинакового размера чаще grid, ряд разных по ширине элементов — flex.
Почему элементы сжимаются, а не переносятся?
Потому что стоит nowrap. Это значение по умолчанию, и оно разрешает браузеру уменьшать элементы ниже заданной ширины. Лечит flex-wrap: wrap, а чтобы элемент точно не сжимался — flex-shrink: 0.
Как сделать элементы одинаковой ширины?
flex: 1 на детях. Это сокращение от flex-grow: 1; flex-shrink: 1; flex-basis: 0, и именно нулевой flex-basis делает ширины равными — при flex-basis: auto они поделят лишь свободное место, а не весь ряд.
Как центрировать элемент по обеим осям?
justify-content: center вместе с align-items: center. Одно свойство центрирует по главной оси, другое — по поперечной, поэтому нужны оба.
Меняет ли row-reverse порядок для экранного диктора?
Нет. row-reverse и wrap-reverse меняют лишь то, что видно на экране; порядок в разметке, порядок фокуса и порядок чтения остаются прежними. Если элементы действительно должны идти в другом порядке, их надо переставить в HTML.