Освоение перевода элементов гибкой компоновки
Flexbox был разработан как инструмент одномерной компоновки — он обрабатывает размещение элементов в виде строки или столбца — но не одновременно. Однако можно переносить элементы гибкой компоновки на новые строки, создавая новые строки, если flex-direction равно row и новые столбцы, если flex-direction равно column. Это руководство объясняет перенос гибкой компоновки, для чего он предназначен, и в каких ситуациях требуется CSS сетка, а не гибкая компоновка.
Перенос элементов
Начальное значение свойства flex-wrap равно nowrap. Это означает, что если набор элементов гибкой компоновки слишком широк для своего контейнера гибкой компоновки, они будут переполнять его. Чтобы перенести их на новые строки, когда они становятся слишком широкими, добавьте свойство flex-wrap со значением wrap, или используйте сокращенное свойство flex-flow со значениями row wrap или column wrap. Тогда элементы будут переноситься на новые строки, когда они переполнят свой контейнер.
В этом примере есть десять элементов гибкой компоновки с flex-basis равным 160px, которые могут увеличиваться и уменьшаться. Как только места недостаточно для размещения ещё одного элемента шириной 160 пикселей в строке, создаётся новая строка гибкой компоновки. Новые строки создаются по мере необходимости, пока все элементы не будут размещены. Поскольку элементы могут увеличиваться, они будут расширяться, чтобы полностью заполнить каждую строку. Если в последней строке находится только один элемент, он будет растянут, чтобы заполнить всю строку.
<div class="box"> <div>One</div> <div>Two</div> <div>Three</div> <div>Four</div> <div>Five</div> <div>Six</div> <div>Seven</div> <div>Eight</div> <div>Nine</div> <div>Ten</div> </div>
.box {
width: 500px;
border: 2px dotted rgb(96 139 168);
display: flex;
flex-wrap: wrap;
}
.box > * {
border: 2px solid rgb(96 139 168);
border-radius: 5px;
background-color: rgb(96 139 168 / 0.2);
flex: 1 1 160px;
}
То же самое происходит со столбцами гибкой компоновки. Чтобы переносить элементы и создавать новые столбцы, контейнер должен иметь высоту. В случае столбцов элементы растягиваются по вертикали, чтобы полностью заполнить каждый столбец.
<div class="box"> <div>One</div> <div>Two</div> <div>Three</div> <div>Four</div> <div>Five</div> <div>Six</div> <div>Seven</div> <div>Eight</div> <div>Nine</div> <div>Ten</div> </div>
.box {
border: 2px dotted rgb(96 139 168);
height: 300px;
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.box > * {
border: 2px solid rgb(96 139 168);
border-radius: 5px;
background-color: rgb(96 139 168 / 0.2);
flex: 1 1 80px;
}
Перенос и flex-direction
Перенос работает так, как вы ожидаете, при сочетании с flex-direction. Если flex-direction установлено в row-reverse, то элементы будут начинаться с крайнего правого края контейнера и выстраиваться в обратном порядке строк.
<div class="box"> <div>One</div> <div>Two</div> <div>Three</div> <div>Four</div> <div>Five</div> <div>Six</div> <div>Seven</div> <div>Eight</div> <div>Nine</div> <div>Ten</div> </div>
.box {
border: 2px dotted rgb(96 139 168);
display: flex;
flex-wrap: wrap;
flex-direction: row-reverse;
width: 500px;
}
.box > * {
border: 2px solid rgb(96 139 168);
border-radius: 5px;
background-color: rgb(96 139 168 / 0.2);
flex: 1 1 160px;
}
Обратите внимание, что обратный порядок происходит только в строчном направлении. Мы начинаем справа, затем переходим ко второй строке и снова начинаем справа. Мы не переворачиваем в обоих направлениях, начиная с нижней части контейнера!
Объяснение одномерной компоновки
Как мы видели из примеров выше, если нашим элементам разрешено увеличиваться и уменьшаться, то когда в последней строке или столбце меньше элементов, эти элементы увеличиваются, чтобы заполнить доступное пространство.
В Flexbox нет функций, позволяющих элементам в одной строке выравниваться с элементами в строке выше — каждая строка гибкой компоновки действует как новый контейнер гибкой компоновки. Она обрабатывает распределение пространства по основной оси. Если есть только один элемент, и этому элементу разрешено увеличиваться, он заполнит ось точно так же, как если бы у вас был один контейнер гибкой компоновки. Если вам нужна компоновка в двух измерениях, вероятно, вам нужна сетка.
Этот пример демонстрирует разницу, используя CSS сетку для создания компоновки с как можно большим количеством столбцов шириной не менее 160px, которые поместятся, распределяя дополнительное пространство между всеми столбцами. Мы используем тот же HTML, что и в примере строки с переносными элементами гибкой компоновки выше, но устанавливаем display: grid на нем. Вместо сокращенного flex, которое не действует вне flexbox, мы устанавливаем минимальную ширину элемента и возможность увеличения напрямую на контейнере с помощью grid-template-columns. В CSS сетке последний элемент остается в своей ячейке сетки; элементы сетки не растягиваются, когда их меньше в последней строке.
<div class="box"> <div>One</div> <div>Two</div> <div>Three</div> <div>Four</div> <div>Five</div> <div>Six</div> <div>Seven</div> <div>Eight</div> <div>Nine</div> <div>Ten</div> </div>
.box {
border: 2px dotted rgb(96 139 168);
display: grid;
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
width: 500px;
}
.box > * {
border: 2px solid rgb(96 139 168);
border-radius: 5px;
background-color: rgb(96 139 168 / 0.2);
}
Это различие между одномерной и двухмерной компоновками. В одномерном методе компоновки, таком как flexbox, мы контролируем только строку или столбец. В двухмерной компоновке сетки мы контролируем оба одновременно. Если вам нужно распределение пространства строка за строкой, используйте Flexbox. Если нет, используйте CSS сетку.
Как работают системы сетки на основе гибкой компоновки?
Компоновки на основе гибкой компоновки можно заставить выстраиваться как системы сетки, но это не предназначение flexbox. Если вы назначаете ширину в процентах элементам гибкой компоновки — используя flex-basis или добавив ширину самому элементу и оставив значение flex-basis равным auto, — вы можете создать впечатление двухмерной компоновки.
В этом примере flex-grow и flex-shrink установлены в 0, чтобы сделать неизменяемые элементы гибкой компоновки. Гибкость контролируется с помощью процентов.
<div class="box"> <div>One</div> <div>Two</div> <div>Three</div> <div>Four</div> <div>Five</div> <div>Six</div> <div>Seven</div> <div>Eight</div> <div>Nine</div> <div>Ten</div> </div>
* {
box-sizing: border-box;
}
.box {
width: 500px;
border: 2px dotted rgb(96 139 168);
display: flex;
flex-wrap: wrap;
}
.box > * {
border: 2px solid rgb(96 139 168);
border-radius: 5px;
background-color: rgb(96 139 168 / 0.2);
flex: 0 0 33.3333%;
}
Эта техника позволяет выстраивать элементы гибкой компоновки по поперечной оси. Однако, когда вы обнаруживаете, что добавляете ширину элементам гибкой компоновки таким образом или добавляете пустые элементы гибкой компоновки для заполнения пространства, это хороший признак, что для этого компонента следует перейти к CSS сетке.
Создание отступов между элементами
Чтобы создать промежутки или отступы между элементами гибкой компоновки, используйте свойство gap непосредственно на контейнере гибкой компоновки для создания фиксированного пространства между соседними элементами гибкой компоновки. Свойство gap является сокращением для row-gap и column-gap. Эти свойства задают размер отступов между строками и столбцами в сетке, flex и многоколоночных макетах.
Свойство gap — не единственное, что может добавить пространство между элементами. Поля, отступы, justify-content, и align-content также могут увеличить размер отступа, влияя на фактический размер промежутка.
Чтобы увидеть разницу между свойством gap и margin на обеих осях, попробуйте изменить значение gap в контейнере .box и добавить значение margin к правилу .box > * в стиле ниже. Нажмите кнопку "Сброс", чтобы вернуть предыдущие значения.
<div class="wrapper">
<div class="box">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
<div>Six</div>
<div>Seven</div>
<div>Eight</div>
<div>Nine</div>
<div>Ten</div>
</div>
</div>
.wrapper {
border: 2px dotted rgb(96 139 168);
width: 500px;
}
.box {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.box > * {
flex: 1 1 160px;
border: 2px solid rgb(96 139 168);
border-radius: 5px;
background-color: rgb(96 139 168 / 0.2);
}
Свернутые элементы
Спецификация flexbox описывает, что произойдет, если элемент flex свернут путем установки visibility: collapse для данного элемента. См. документацию MDN для свойства visibility. Спецификация описывает поведение следующим образом:
"Указание visibility:collapse для элемента flex приводит к тому, что он становится свернутым элементом flex, производя эффект, похожий на visibility:collapse для table-row или table-column: свернутый элемент flex удаляется из рендеринга полностью, но оставляет "стойку", которая сохраняет стабильность размера перекрестной оси строки flex. Таким образом, если у контейнера flex есть только одна строка flex, динамическое сворачивание или разворачивание элементов может изменить основной размер контейнера flex, но гарантированно не повлияет на его размер по перекрестной оси и не приведет к колебаниям остальной части макета страницы. Однако перенос строк flex пересчитывается после сворачивания, поэтому размер по перекрестной оси контейнера flex с несколькими строками может или не может измениться." - Свернутые элементы
Это поведение полезно, если вы хотите нацеливаться на элементы flex с помощью JavaScript для отображения и скрытия содержимого, например. Пример в спецификации демонстрирует такую схему.
В следующем примере в реальном времени у меня есть контейнер flex, который не переносится. Третий элемент содержит больше содержимого, чем другие, но при этом установлен visibility: collapse; поэтому контейнер flex сохраняет стойку высоты, необходимой для отображения этого элемента. Если вы удалите visibility: collapse из CSS или измените значение на visible, вы увидите, что элемент отобразится, и пространство будет перераспределено между несокращенными элементами; высота контейнера flex не должна измениться.
Примечание: Используйте Firefox для нижеприведенных двух примеров, так как Chrome и Safari обрабатывают collapse как hidden.
<div class="box"> <div>One</div> <div>Two</div> <div class="hide">Three <br />has <br />extra <br />text</div> </div>
.box {
border: 2px dotted rgb(96 139 168);
display: flex;
width: 600px;
}
.box > * {
flex: 1 1 200px;
border: 2px solid rgb(96 139 168);
border-radius: 5px;
background-color: rgb(96 139 168 / 0.2);
}
.hide {
visibility: collapse;
}
Однако при работе с контейнерами flex с несколькими строками необходимо понимать, что перенос строк выполняется после сворачивания. Поэтому браузеру необходимо пересчитать поведение переноса строк, чтобы учесть новое пространство, которое свернутый элемент освободил в направлении строки.
Это означает, что элементы могут оказаться на другой строке, чем та, с которой они начинали. В случае показа и скрытия элемента это может привести к тому, что элементы окажутся в другой строке.
В следующем примере в реальном времени я создал такое поведение. Вы можете увидеть, как растяжение изменяет строку в зависимости от расположения свернутого элемента. Если вы добавите больше содержимого во второй элемент, он перейдет на другую строку, как только станет достаточно длинным. Тогда верхняя строка станет такой же высокой, как одна строка текста.
<div class="box"> <div>One</div> <div>Add more text to this box to make it grow</div> <div class="hide">Three <br />has <br />extra <br />text</div> <div>Four</div> <div>Five</div> <div>Six</div> <div>Seven</div> <div>Eight</div> <div>Nine</div> <div>Ten</div> </div>
.box {
border: 2px dotted rgb(96 139 168);
width: 500px;
display: flex;
flex-wrap: wrap;
}
.box > * {
padding: 10px;
border: 2px solid rgb(96 139 168);
border-radius: 5px;
background-color: rgb(96 139 168 / 0.2);
flex: 1 1 auto;
}
.hide {
visibility: collapse;
}
Если это вызывает проблемы с макетом, может потребоваться переосмыслить структуру, например, поместить каждую строку в отдельный контейнер flex, чтобы строки не смещались.
Использование visibility: hidden и display: none
В предыдущем примере в реальном времени попробуйте использовать visibility: hidden или display: none вместо visibility: collapse. Используя visibility: hidden, элемент делается невидимым, но ящик сохраняется в структуре форматирования, поэтому он все равно ведет себя так, как будто он является частью макета. При использовании display: none, элемент полностью удаляется из структуры форматирования. Он не только невидим, но и структура также удаляется. Это означает, что счетчики его игнорируют, а такие вещи, как переходы, не выполняются.
© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_flexible_box_layout/Mastering_wrapping_of_flex_items