Одна ось и контейнер
Flexbox раскладывает детей вдоль одной оси. display: flex превращает элемент во flex-контейнер, а его прямых детей во flex-элементы. Внуки остаются в обычном потоке.
- Главная ось задаётся
flex-direction:row(по умолчанию, слева направо в ltr),row-reverse,column,column-reverse. - Поперечная ось перпендикулярна главной.
Почти все путаницы с flex лечатся вопросом «какая у меня сейчас главная ось».
Выравнивание
.bar {
display: flex;
justify-content: space-between; /* по главной оси */
align-items: center; /* по поперечной оси, в каждой строке */
gap: 12px; /* промежутки между элементами */
}
justify-content:flex-start,center,flex-end,space-between(крайние прижаты к краям),space-around(по половине промежутка по краям),space-evenly(все промежутки равны).align-items:stretch(по умолчанию: элементы без явного размера растягиваются на высоту строки),flex-start,center,flex-end,baseline.align-selfу элемента переопределяетalign-itemsдля него одного.align-contentраспределяет строки при переносе. В однострочном контейнере (nowrap) не действует.justify-selfво flexbox не работает. Сдвинуть один элемент по главной оси можно черезmargin-left: auto(илиmargin-inline-start: auto): auto-margin забирает всё свободное место.
.nav { display: flex; }
.nav .logout { margin-left: auto; } /* прижата вправо, остальные слева */
Центрирование по обеим осям:
.center { display: flex; justify-content: center; align-items: center; }
flex: grow, shrink, basis
У каждого элемента три параметра:
flex-basis: стартовый размер по главной оси до распределения места.autoзначит «бери width/height, а если их нет, размер содержимого».flex-grow: какую долю свободного места забрать. По умолчанию 0.flex-shrink: насколько сжиматься при нехватке места. По умолчанию 1. Сжатие взвешено по basis: большие элементы теряют больше пикселей.
Короткая запись:
| Запись | Значит |
|---|---|
flex: initial (по умолчанию) | 0 1 auto |
flex: 1 | 1 1 0% |
flex: auto | 1 1 auto |
flex: none | 0 0 auto |
Разница между flex: 1 и flex: auto: при 1 basis нулевой, и всё место делится строго поровну, поэтому колонки одинаковые. При auto сначала каждый получает размер по содержимому, а поровну делится только остаток.
.a { flex: 1; } /* три элемента с flex: 1 и flex: 2 */
.b { flex: 2; } /* делят место 1 : 2 */
Почему элемент не сжимается
У flex-элемента min-width: auto по умолчанию (в направлении row): он не сожмётся меньше своего содержимого. Длинное слово или <pre> распирает колонку и вызывает горизонтальный скролл. Лечение: min-width: 0 (или overflow: hidden) на элементе. Для column то же с min-height.
.sidebar { flex: 0 0 240px; }
.content { flex: 1; min-width: 0; } /* теперь текст с ellipsis обрежется */
Перенос
flex-wrap: wrap разрешает перенос на новые строки. Без него элементы сжимаются в одну строку. flex-flow: row wrap это короткая запись направления и переноса. Каждая строка раскладывается независимо, поэтому последняя неполная строка в сетке карточек ведёт себя иначе, чем верхние. Для ровной сетки лучше Grid.
order и доступность
order меняет визуальный порядок, но не порядок в DOM. Tab и скринридер идут по DOM, поэтому order и *-reverse для смысловой перестановки использовать не стоит.
Flex или Grid
- Flex: одномерная раскладка, размер идёт от содержимого: панель кнопок, шапка, строка «иконка + текст».
- Grid: двумерная раскладка, размеры задаёт контейнер: сетка карточек, макет страницы.
Частые ошибки
- Путать
justify-contentиalign-itemsприflex-direction: column. - Ждать работы
align-contentв однострочном контейнере. - Забыть
min-width: 0и получить вылезающий текст. - Считать, что
flex: 1иflex-grow: 1одно и то же (basis разный).
Что спросят на собесе
- Что делают
flex-grow,flex-shrink,flex-basisи что значитflex: 1. - Чем
justify-contentотличается отalign-itemsиalign-content. - Как отцентрировать блок по обеим осям.
- Почему flex-элемент не сжимается и как это исправить.
- Когда выбрать Flexbox, а когда Grid.