Чтобы было проще, я уменьшу код, чтобы мы могли лучше понять его поведение.
Давайте рассмотрим этот исходный код:
* {
box-sizing: border-box;
font-size: 1.5rem;
}
html {
background: #b3b3b3;
padding: 5px;
}
body {
background: #b3b3b3;
padding: 5px;
margin: 0;
}
.flex-container {
background: white;
padding: 10px;
border: 5px solid black;
height: 400px;
display: flex;
flex-direction: row;
flex-wrap:wrap;
}
.item-1 {
background: #ff7300;
color: white;
padding: 10px;
border: 5px solid black;
margin: 10px;
}
.item-2 {
background: #ff9640;
color: white;
padding: 10px;
border: 5px solid black;
margin: 10px;
width: 250px;
}
.item-3 {
background: #ff9640;
color: white;
padding: 10px;
border: 5px solid black;
margin: 10px;
height: 150px;
}
<div class="flex-container">
<div class="item-1">div</div>
<div class="item-2">w=250px</div>
<div class="item-3">h=150px</div>
</div>
Контейнер имеет фиксированную высоту, и только один элемент имеет фиксированную высоту, а другой будет растянут для заполнения родительской высоты, поскольку по умолчанию align-items
равно stretch
.
Теперь давайте уменьшим ширину контейнера, чтобы сделать третий элемент во втором ряду:
* {
box-sizing: border-box;
font-size: 1.5rem;
}
html {
background: #b3b3b3;
padding: 5px;
}
body {
background: #b3b3b3;
padding: 5px;
margin: 0;
}
.flex-container {
background: white;
padding: 10px;
border: 5px solid black;
height: 400px;
display: flex;
flex-direction: row;
flex-wrap:wrap;
width:500px;
}
.item-1 {
background: #ff7300;
color: white;
padding: 10px;
border: 5px solid black;
margin: 10px;
}
.item-2 {
background: #ff9640;
color: white;
padding: 10px;
border: 5px solid black;
margin: 10px;
width: 250px;
}
.item-3 {
background: #ff9640;
color: white;
padding: 10px;
border: 5px solid black;
margin: 10px;
height: 150px;
}
<div class="flex-container">
<div class="item-1">div</div>
<div class="item-2">w=250px</div>
<div class="item-3">h=150px</div>
</div>
Здесь мы имеем сложное поведение, в котором мы имеем многострочный гибкий контейнер, где item1
и item2
принадлежат первой строке, а item3
- второй. Я не могу очень хорошо объяснить, как определяется высота каждой линии (сложная часть). После этого каждый изгибаемый элемент будет растягиваться, чтобы заполнить высоту его линии, если только он не имеет фиксированной высоты, такой как item3
или мы не изменим выравнивание.
Теперь, если мы изменим align-items
на что-то отличное от stretch
, у нас будет разрыв:
* {
box-sizing: border-box;
font-size: 1.5rem;
}
html {
background: #b3b3b3;
padding: 5px;
}
body {
background: #b3b3b3;
padding: 5px;
margin: 0;
}
.flex-container {
background: white;
padding: 10px;
border: 5px solid black;
height: 400px;
display: flex;
flex-direction: row;
flex-wrap:wrap;
width:500px;
align-items:flex-start;
}
.item-1 {
background: #ff7300;
color: white;
padding: 10px;
border: 5px solid black;
margin: 10px;
}
.item-2 {
background: #ff9640;
color: white;
padding: 10px;
border: 5px solid black;
margin: 10px;
width: 250px;
}
.item-3 {
background: #ff9640;
color: white;
padding: 10px;
border: 5px solid black;
margin: 10px;
height: 150px;
}
<div class="flex-container">
<div class="item-1">div</div>
<div class="item-2">w=250px</div>
<div class="item-3">h=150px</div>
</div>
Если мы сравним приведенный выше код с предыдущим, мы увидим, что item3
сохранил свое место и изменились только высота item1
и item2
. Это объясняет, что align-items
будет выравнивать элементы внутри своих строк, которые были ранее определены из-за переноса.
Другими словами, когда у нас есть многострочный flex-контейнер, мы сначала определяем линии (учитывая высоту контейнера, высоту элементов и другие свойства flexbox), затем мы выравниваем элементы внутри их линии, и имеющийся зазор равен из-за того, как выполняется выравнивание.
Вот лучший пример, чтобы показать разные случаи:
.flex-container {
background: white;
padding: 10px;
border: 5px solid black;
height: 200px;
display: inline-flex;
vertical-align:top;
flex-direction: row;
flex-wrap:wrap;
width:100px;
}
.item-1 {
background: #ff7300;
color: white;
border: 1px solid black;
margin: 2px;
}
.item-2 {
background: #ff9640;
color: white;
border: 1px solid black;
margin: 2px;
width: 70px;
}
.item-3 {
background: #ff9640;
color: white;
border: 1px solid black;
margin: 2px;
height: 50px;
}
<div class="flex-container">
<div class="item-1">A</div>
<div class="item-2">B</div>
<div class="item-3">C</div>
</div>
<div class="flex-container" style="align-items:flex-start;">
<div class="item-1">A</div>
<div class="item-2">B</div>
<div class="item-3">C</div>
</div>
<div class="flex-container" style="align-items:center;">
<div class="item-1">A</div>
<div class="item-2">B</div>
<div class="item-3">C</div>
</div>
<div class="flex-container" style="align-items:flex-end;">
<div class="item-1">A</div>
<div class="item-2">B</div>
<div class="item-3">C</div>
</div>
<div class="flex-container" style="align-items:flex-end;">
<div class="item-1">A</div>
<div class="item-2">B</div>
<div class="item-3" style="margin-bottom:auto;">C</div>
</div>
<div class="flex-container">
<div class="item-1" style="margin-top:auto;">A</div>
<div class="item-2">B</div>
<div class="item-3" >C</div>
</div>
Мы можем четко заметить, что у нас одинаковые линии по всему контейнеру, и меняется только выравнивание, что создает различные пропуски.
Если нет элемента с фиксированной высотой, строки будут иметь одинаковую высоту, поэтому контейнер будет разделен поровну.
.flex-container {
background: white;
padding: 10px;
border: 5px solid black;
height: 200px;
display: inline-flex;
vertical-align:top;
flex-direction: row;
flex-wrap:wrap;
width:100px;
}
.item-1 {
background: #ff7300;
color: white;
border: 1px solid black;
margin: 2px;
}
.item-2 {
background: #ff9640;
color: white;
border: 1px solid black;
margin: 2px;
width: 70px;
}
.item-3 {
background: #ff9640;
color: white;
border: 1px solid black;
margin: 2px;
}
<div class="flex-container">
<div class="item-1">A</div>
<div class="item-2">B</div>
<div class="item-3">C</div>
</div>
<div class="flex-container" style="align-items:flex-start;">
<div class="item-1">A</div>
<div class="item-2">B</div>
<div class="item-3">C</div>
</div>
<div class="flex-container" style="align-items:center;">
<div class="item-1">A</div>
<div class="item-2">B</div>
<div class="item-3">C</div>
</div>
<div class="flex-container" style="align-items:flex-end;">
<div class="item-1">A</div>
<div class="item-2">B</div>
<div class="item-3">C</div>
</div>
<div class="flex-container" style="align-items:flex-end;">
<div class="item-1">A</div>
<div class="item-2">B</div>
<div class="item-3" style="margin-bottom:auto;">C</div>
</div>
<div class="flex-container">
<div class="item-1" style="margin-top:auto;">A</div>
<div class="item-2">B</div>
<div class="item-3" >C</div>
</div>
Изменяя align-content
, мы изменим способ создания линий, прежде чем рассматривать align-items
для выравнивания элементов внутри их линий:
.flex-container {
background: white;
padding: 10px;
border: 5px solid black;
height: 200px;
display: inline-flex;
vertical-align:top;
flex-direction: row;
flex-wrap:wrap;
width:100px;
}
.item-1 {
background: #ff7300;
color: white;
border: 1px solid black;
margin: 2px;
}
.item-2 {
background: #ff9640;
color: white;
border: 1px solid black;
margin: 2px;
width: 70px;
}
.item-3 {
background: #ff9640;
color: white;
border: 1px solid black;
margin: 2px;
height:50px;
}
<div class="flex-container">
<div class="item-1">A</div>
<div class="item-2">B</div>
<div class="item-3">C</div>
</div>
<div class="flex-container" style="align-content:flex-start;">
<div class="item-1">A</div>
<div class="item-2">B</div>
<div class="item-3">C</div>
</div>
<div class="flex-container" style="align-content:center;">
<div class="item-1">A</div>
<div class="item-2">B</div>
<div class="item-3">C</div>
</div>
<div class="flex-container" style="align-content:flex-end;">
<div class="item-1">A</div>
<div class="item-2">B</div>
<div class="item-3">C</div>
</div>
Чтобы понять сложную часть этого ответа (как определяются строки), вы можете обратиться к спецификации: https://www.w3.org/TR/css-flexbox-1/#layout-algorithm