flex-wrap: одна строка или сколько нужно
По умолчанию flex-контейнер держит все элементы в одной строке (flex-wrap: nowrap) и сжимает их, чтобы они поместились. flex-wrap: wrap позволяет им сохранить размер и перейти на следующую строку:
Каждый элемент просит 100px, их пять в блоке шириной 340px. Пяти элементам и четырем промежуткам по 8px нужно 532px, поэтому без переноса каждый элемент сжимается примерно до 62px: flex-элементы по умолчанию сжимаются. С wrap они остаются по 100px: три помещаются в первой строке, а два других переходят во вторую.
Значения flex-wrap
| Значение | Что происходит |
|---|---|
nowrap (по умолчанию) | Одна строка. Элементы сжимаются, а когда сжиматься дальше не могут, вылезают за контейнер |
wrap | Элементы, которые не помещаются, начинают новую строку ниже |
wrap-reverse | То же, но новые строки складываются вверх: первая строка оказывается внизу |
Посмотрите, как элементы переносятся
Двигайте ползунок, чтобы менять ширину контейнера. Счетчик показывает число строк и сколько элементов в каждой:
При 400px в строку помещаются четыре элемента по 90px и три промежутка по 8px (384px), и получается 4 + 2. Потяните к 620px, и все шесть поместятся в одну строку; потяните к 120px, и каждый элемент получит свою строку.
flex-direction: строка или колонка
flex-direction задает направление, в котором идут элементы, то есть главную ось:
| Значение | Элементы идут | Первый элемент |
|---|---|---|
row (по умолчанию) | бок о бок, в направлении письма | в начале строки |
row-reverse | бок о бок, в обратном порядке | в конце строки |
column | стопкой, сверху вниз | сверху |
column-reverse | стопкой, снизу вверх | снизу |
В двух блоках row элементы растягиваются на всю высоту блока, потому что align-items: stretch работает поперек строки. В блоках column они по той же причине растягиваются на всю ширину. Оси повернулись, и вместе с ними повернулось каждое свойство выравнивания (подробно это показано на странице про justify-content).
flex-flow: оба свойства в одной строке
flex-flow это сокращение для flex-direction, а затем flex-wrap:
.cards { flex-flow: row wrap; } /* flex-direction: row; flex-wrap: wrap; */
.stack { flex-flow: column nowrap; } /* flex-direction: column; flex-wrap: nowrap; */
Адаптивные карточки через wrap без медиазапросов
Дайте каждому элементу начальный размер через flex: 1 1 180px и разрешите перенос. Каждый элемент растет, заполняя свою строку, а когда в строку не помещается еще один элемент на 180px, следующий переносится:
В превью шириной около 800px в первую строку помещаются три карточки (около 253px каждая), а последние две делят вторую строку, где каждая вырастает примерно до 386px. Так работает flexbox: каждая строка делит свое пространство сама, поэтому карточки в короткой последней строке оказываются шире верхних. Если последняя карточка должна быть той же ширины, что и остальные, используйте grid с repeat(auto-fill, minmax(180px, 1fr)) (смотрите страницу про CSS Grid).
align-content: промежутки между строками
Когда контейнер переносит элементы и выше своих строк, align-content решает, где будут строки. Он принимает те же значения, что justify-content, плюс stretch:
В первом блоке обе строки стоят сверху. Во втором первая строка сверху, вторая снизу, а вся свободная высота между ними.
Обратный порядок и доступность
row-reverse, column-reverse и wrap-reverse меняют только то, где элементы рисуются. Программы чтения с экрана и клавиша Tab по-прежнему следуют порядку HTML, поэтому пользователь клавиатуры проходит элементы в направлении, обратном тому, что видит. Разворачивайте только ради визуального эффекта; когда порядок что-то значит, меняйте его в HTML.
Частые ошибки
- Элементы сжимаются, а не переносятся. Элементы с
flex: 1начинают сflex-basis0 и втискиваются в одну строку. Дайте им настоящую основу, напримерflex: 1 1 200px. flex-wrapу элементов. Ему место у flex-контейнера.align-itemsдля промежутков между перенесенными строками. Оно выравнивает элементы внутри каждой строки; сами строки двигаетalign-content.- Одинокий последний элемент растянут на всю строку. Это
flex-growв строке с одним элементом. Используйте grid, если все карточки должны быть одинаковой ширины. - Ожидание, что
flex-direction: columnзаполнит высоту. Колонка высотой только с содержимое, если не задать ейheight, поэтомуjustify-contentнегде работать.
Часто задаваемые вопросы
Что делает flex-wrap: wrap?
Позволяет flex-элементам переходить на новую строку, когда они не помещаются в одну. При nowrap по умолчанию элементы остаются в одной строке и сжимаются или вылезают за контейнер, если сжиматься дальше не могут.
Почему не работает flex-wrap?
Перенос происходит, только когда начальные размеры элементов в сумме больше контейнера. Элементы с flex: 1 начинают с flex-basis 0, поэтому никогда не переносятся; дайте им настоящий начальный размер (flex: 1 1 200px или width: 200px). Также проверьте, что flex-wrap задан flex-контейнеру, а не элементам.
Чем отличаются flex-direction row и column?
row (по умолчанию) ставит элементы бок о бок в направлении письма, а column складывает их сверху вниз. Вместе с ним поворачивается главная ось, поэтому в колонке justify-content работает по вертикали, а align-items по горизонтали.
Что такое flex-flow?
Сокращение для flex-direction и flex-wrap в одном объявлении: flex-flow: row wrap; то же самое, что flex-direction: row; flex-wrap: wrap;.
Чем align-items отличается от align-content?
align-items размещает элементы внутри их строки. align-content размещает сами строки внутри контейнера, поэтому он важен, только когда у контейнера flex-wrap: wrap и он выше своих строк.