Как flex-wrap работает с align-self, align-items и align-content?
align-self
В следующем коде align-self
работает с flex-wrap: nowrap
,
flex-container {
display: flex;
flex-wrap: nowrap;
align-content: flex-start;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
flex-item:last-child {
align-self: flex-end;
background-color: crimson;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
Но когда контейнер переключен на flex-wrap: wrap
, align-self
собственность терпит неудачу.
flex-container {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
flex-item:last-child {
align-self: flex-end;
background-color: crimson;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
align-items
Точно так же почему align-items
работа здесь (обертывание отключено):
flex-container {
display: flex;
flex-wrap: nowrap;
align-items: flex-end;
align-content: flex-start;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
... но не здесь (перенос включен):
flex-container {
display: flex;
flex-wrap: wrap;
align-items: flex-end;
align-content: flex-start;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
align-content
С flex-wrap: nowrap
, align-content
свойство не будет вертикально центрировать элементы Flex здесь:
flex-container {
display: flex;
flex-wrap: nowrap;
align-content: center;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
Но тогда, как ни странно, если обтекание включено и align-content
опущен, контейнер создает широкие промежутки между строками:
flex-container {
display: flex;
flex-wrap: wrap;
/* align-content: center; */
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
А также align-self
снова работает
flex-container {
display: flex;
flex-wrap: wrap;
/* align-content: center; */
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
flex-item:nth-child(even) {
align-self: flex-end;
background-color: crimson;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
Как
flex-wrap
работать сalign-self
,align-items
а такжеalign-content?
2 ответа
Короткий ответ
Хотя flex-wrap
Свойство кажется довольно простым - оно контролирует возможность переноса элементов flex - оно на самом деле оказывает широкое влияние на весь макет flexbox.
flex-wrap
Свойство определяет тип гибкого контейнера, который вы будете использовать.
flex-wrap: nowrap
создает однострочный гибкий контейнерflex-wrap: wrap
а такжеwrap-reverse
создать многострочный гибкий контейнер
align-items
а также align-self
свойства работают как в одно-, так и в многострочных контейнерах. Тем не менее, они могут иметь эффект только при наличии свободного места на поперечной оси гибкой линии.
align-content
свойство работает только в многострочных контейнерах. Это игнорируется в однострочных контейнерах.
объяснение
Спецификация flexbox предоставляет четыре свойства ключевых слов для выравнивания элементов flex:
align-items
align-self
align-content
justify-content
Чтобы понять функции этих свойств, важно сначала понять структуру гибкого контейнера.
Часть 1: Понимание главной и поперечной осей гибкого контейнера
Оси X и Y
Гибкий контейнер работает в двух направлениях: ось x (горизонтальная) и ось y (вертикальная).
Источник: Википедия
Дочерние элементы гибкого контейнера, известные как "гибкие элементы", могут быть выровнены в любом направлении.
Это гибкое выравнивание на самом фундаментальном уровне.
Главная и поперечная оси
Наложение осей X и Y в гибком макете является главной и поперечной осями.
По умолчанию главная ось является горизонтальной (ось X), а поперечная ось является вертикальной (ось Y). Это начальная настройка, определенная спецификацией flexbox.
Источник: W3C
Однако, в отличие от осей x и y, которые являются фиксированными, главная и поперечная оси могут переключать направления.
flex-direction
Имущество
На изображении выше главная ось горизонтальная, а поперечная ось вертикальная. Как упоминалось ранее, это начальная настройка гибкого контейнера.
Тем не менее, эти направления могут быть легко переключены с помощью flex-direction
имущество. Это свойство контролирует направление главной оси; он определяет, выравниваются ли элементы Flex по вертикали или по горизонтали.
Из спецификации:
5.1. Направление гибкого потока:
flex-direction
имущество
flex-direction
Свойство указывает, как флекс-элементы размещаются в флекс-контейнере, устанавливая направление главной оси флекс-контейнера. Это определяет направление, в котором располагаются гибкие элементы.
Есть четыре значения для flex-direction
имущество:
/* main axis is horizontal, cross axis is vertical */
flex-direction: row; /* default */
flex-direction: row-reverse;
/* main axis is vertical, cross axis is horizontal */
flex-direction: column;
flex-direction: column-reverse;
Поперечная ось всегда перпендикулярна главной оси.
Часть 2: Flex Lines
В контейнере гибкие элементы существуют в строке, известной как "гибкая линия".
Гибкая линия - это строка или столбец, в зависимости от flex-direction
,
Контейнер может иметь одну или несколько строк, в зависимости от flex-wrap
,
Однолинейный гибкий контейнер
flex-wrap: nowrap
устанавливает однострочный гибкий контейнер, в котором гибкие элементы вынуждены оставаться в одной строке (даже если они переполняют контейнер).
Изображение выше имеет одну линию сгиба.
flex-container {
display: flex;
flex-direction: column;
flex-wrap: nowrap; /* <-- allows single-line flex container */
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
width: 50px;
margin: 5px;
background-color: lightgreen;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
Multi-Line Flex Container
flex-wrap: wrap
или же wrap-reverse
устанавливает многострочный flex-контейнер, в котором flex-элементы могут создавать новые строки.
Изображение выше имеет три линии сгиба.
flex-container {
display: flex;
flex-direction: column;
flex-wrap: wrap; /* <-- allows multi-line flex container */
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
width: 50px;
margin: 5px;
background-color: lightgreen;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
Изображение выше имеет три линии сгиба.
flex-container {
display: flex;
flex-direction: row;
flex-wrap: wrap; /* <-- allows multi-line flex container */
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
Часть 3: Свойства выравнивания ключевых слов
Свойства назначены главной и поперечной (не X и Y) осям
В то время как flex-direction
Свойство контролирует направление, в котором размечаются гибкие элементы, есть четыре свойства, которые управляют выравниванием и позиционированием. Это:
align-items
align-self
align-content
justify-content
Каждое из этих свойств постоянно назначается оси.
justify-content
свойство работает только по главной оси.
Три align-*
свойства работают только в поперечной оси.
Распространенной ошибкой является предположение, что эти свойства зафиксированы на осях x и y. Например, justify-content
всегда горизонтально, и align-items
всегда вертикально
Однако когда flex-direction
переключается на column
, главная ось становится осью Y, и justify-content
работает вертикально.
Тема этого поста - выравнивание по осям. Для объяснения выравнивания главной оси и justify-content
собственности, см. этот пост:
Определения
Спецификация flexbox предоставляет три ключевых свойства для выравнивания по оси:
align-items
align-self
align-content
align-items
/ align-self
align-items
свойство выравнивает элементы flex вдоль оси сгиба линии flex. Это относится к гибким контейнерам.
align-self
свойство используется для переопределения align-items
на отдельных флекс. Это относится к гибким предметам.
Вот определение из спецификации:
8.3. Выравнивание по оси
align-items
а такжеalign-self
свойстваЭлементы Flex могут быть выровнены по поперечной оси текущей строки контейнера Flex, аналогично
justify-content
но в перпендикулярном направлении.align-items
устанавливает выравнивание по умолчанию для всех элементов гибкого контейнера.align-self
позволяет этому выравниванию по умолчанию быть переопределенным для отдельных элементов flex.
Есть шесть возможных значений align-items
/ align-self
:
flex-start
flex-end
center
baseline
stretch
auto
(align-self
только)
(Для описания каждого значения нажмите на заголовок определения спецификации выше.)
Начальная стоимость align-items
является stretch
Это означает, что гибкие элементы будут расширять всю доступную длину поперечной оси контейнера.
Начальная стоимость align-self
является auto
это означает, что он наследует значение align-items
,
Ниже приведена иллюстрация влияния каждого значения в контейнере направления строки.
Источник: W3C
align-content
Это свойство немного сложнее, чем align-items
а также align-self
,
Вот определение из спецификации:
8.4. Упаковочные линии Flex:
align-content
имущество
align-content
свойство выравнивает линии флекс-контейнера внутри флекс-контейнера, когда на поперечной оси есть дополнительное пространство, аналогично тому, какjustify-content
выравнивает отдельные элементы в пределах главной оси. Обратите внимание, что это свойство не влияет на однострочный гибкий контейнер.
В отличие от align-items
а также align-self
, которые перемещают гибкие элементы в пределах своей линии, align-content
перемещает гибкие линии внутри контейнера.
Есть шесть возможных значений align-content
:
flex-start
flex-end
center
space-between
space-around
stretch
(Для описания каждого значения нажмите на заголовок определения спецификации выше.)
Ниже приведена иллюстрация влияния каждого значения в контейнере направления строки.
Источник: W3C
Почему align-content
работать только в многолинейных гибких контейнерах?
В гибком контейнере с одной линией поперечный размер линии равен поперечному размеру контейнера. Это означает, что между линией и контейнером нет свободного места. В следствии, align-content
не может иметь никакого эффекта.
Вот соответствующий раздел из спецификации:
Только многолинейные гибкие контейнеры когда-либо имеют свободное пространство на поперечной оси для выравнивания линий, потому что в однострочном гибком контейнере подошва автоматически растягивается, чтобы заполнить пространство.
Часть 4. Объясненные примеры
В примере № 1 align-self
работает с flex-wrap: nowrap
потому что гибкие элементы существуют в однострочном контейнере. Следовательно, есть одна гибкая линия, и она соответствует высоте контейнера.
flex-container {
display: flex;
flex-wrap: nowrap;
align-content: flex-start;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
flex-item:last-child {
align-self: flex-end;
background-color: crimson;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
В примере № 2 align-self
происходит сбой, потому что он существует в многострочном контейнере (flex-wrap: wrap
) и align-content
установлен в flex-start
, Это означает, что гибкие линии плотно упакованы в начале поперечной оси, не оставляя свободного места для align-self
работать.
flex-container {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
flex-item:last-child {
align-self: flex-end;
background-color: crimson;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
Объяснение для примера № 3 такое же, как для примера № 1.
flex-container {
display: flex;
flex-wrap: nowrap;
align-items: flex-end;
align-content: flex-start;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
Объяснение для примера № 4 такое же, как для примера № 2.
flex-container {
display: flex;
flex-wrap: wrap;
align-items: flex-end;
align-content: flex-start;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
Пример № 5 - это однострочный контейнер. Таким образом, размер поперечной линии гибкой линии равен поперечному размеру контейнера, не оставляя дополнительного пространства между ними. Следовательно, align-content
, который выравнивает линии сгиба, когда есть дополнительное пространство на поперечной оси, не имеет никакого эффекта.
flex-container {
display: flex;
flex-wrap: nowrap;
align-content: center;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
Начальная настройка для align-content
является stretch
, Это означает, что если не указано другое значение, контейнер будет равномерно распределять доступное пространство по гибким линиям. (Аналогичный эффект создается на главной оси, когда все гибкие элементы получают flex: 1
.)
Такое распределение пространства между строками может вызвать большие промежутки между строками / столбцами. Меньше строк приводят к более широким промежуткам. Чем больше строк, тем меньше пропуски, так как каждая строка получает меньшую долю пространства.
Чтобы решить эту проблему, переключитесь с align-content: stretch
в align-content: flex-start
, Это объединяет строки (см. Примеры № 2 и № 4 выше). Конечно, это также устраняет любое свободное место в линии, и align-items
а также align-self
больше не может работать.
Вот похожий пост: Уберите пробелы (пробелы) между несколькими строками flex-элементов при их переносе
flex-container {
display: flex;
flex-wrap: wrap;
/* align-content: center; */
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
Как объяснено в предыдущих примерах, с align-content: stretch
, может быть дополнительное пространство в гибких линиях, что позволяет align-items
а также align-self
работать. Любое другое значение для align-content
будет упаковывать линии, исключая дополнительное пространство и делая align-items
а также align-self
бесполезный.
flex-container {
display: flex;
flex-wrap: wrap;
/* align-content: center; */
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
flex-item:nth-child(even) {
align-self: flex-end;
background-color: crimson;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
Прежде всего, align-content бесполезен, если нет переноса:
Свойство align-content выравнивает линии flex-контейнера внутри flex-контейнера, когда на поперечной оси имеется дополнительное пространство, аналогично тому, как justify-content выравнивает отдельные элементы на главной оси. Обратите внимание, что это свойство не влияет на однострочный гибкий контейнер.
Кроме того, в вашем втором случае, align-self не терпит неудачу. Это бесполезно, потому что внутренние линии были упакованы. Давайте создадим пространство, чтобы стиль мог работать:
flex-container {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
flex-item:last-child {
align-self: flex-end;
background-color: crimson;
}
flex-item:nth-child(5) {
height: 90px; /* added */
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
Аналогично, в вашем 4-м примере стиль работает, если вы задали условия, в которых его можно увидеть
flex-container {
display: flex;
flex-wrap: wrap;
align-items: flex-end;
align-content: flex-start;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
flex-item:nth-child(2),flex-item:nth-child(5) {
height: 90px; /* added */
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
Наконец, когда вы комментируете align-content, он возвращается к растяжению, поэтому линии увеличивают размер, чтобы заполнить контейнер
растянуть линии растянуть, чтобы занять оставшееся пространство. Если оставшееся свободное пространство отрицательно, это значение идентично flex-start. В противном случае свободное пространство будет разделено поровну между всеми линиями, увеличивая их поперечный размер.