дополнительное пространство при центрировании элементов с помощью flexbox - PullRequest
0 голосов
/ 02 ноября 2018

Я использую align-items и justify-content для центрирования элементов, мой HTML-код:

<div class="flex-container">
    <div class="item-1">div</div>
    <div class="item-2">w=250px</div>
    <div class="item-3">h=250px</div>
    <div class="item-4">w/h=300px</div>
    <div class="item-5">w=350px</div>
    <div class="item-6">w=350px</div>
</div>

мой код CSS выглядит примерно так:

.flex-container {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    align-content: center;
}

(я пропускаю неважный код CSS).

поэтому результат будет таким:

enter image description here

но если я уменьшу окно браузера, оно будет выглядеть так: enter image description here

Я не понимаю, почему между двумя строками так много места (я знаю, что с помощью align-content: center; можно исправить, но я хочу знать, как эти избыточные места вообще существуют)

* {
  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: 800px;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
}

.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;
  /* font-size: 1.8rem; */
}

.item-3 {
  background: #ff9640;
  color: white;
  padding: 10px;
  border: 5px solid black;
  margin: 10px;
  height: 250px;
}

.item-4 {
  background: #f5c096;
  color: white;
  padding: 10px;
  border: 5px solid black;
  margin: 10px;
  width: 300px;
  height: 300px;
}

.item-5 {
  background: #d3c0b1;
  color: white;
  padding: 10px;
  border: 5px solid black;
  margin: 10px;
  width: 350px;
}

.item-6 {
  background: #d3c0b1;
  color: white;
  padding: 10px;
  border: 5px solid black;
  margin: 10px;
  width: 350px;
}
<div class="flex-container">
  <div class="item-1">div</div>
  <div class="item-2">w=250px</div>
  <div class="item-3">h=250px</div>
  <div class="item-4">w/h=300px</div>
  <div class="item-5">w=350px</div>
  <div class="item-6">w=350px</div>
</div>

и если я уменьшу окно браузера больше, то такого избыточного пространства не будет:

enter image description here

Ответы [ 2 ]

0 голосов
/ 03 ноября 2018

align-content

Обратите внимание, что align-content: stretch также находится в игре здесь.

Свойство align-content распределяет свободное пространство между гибкими линиями. Это значение по умолчанию stretch.

Поэтому, когда ваши элементы переносятся в две строки, align-content: stretch распределяет свободное пространство поровну между строк.


align-items

Удалить align-items: center из контейнера. Затем вы заметите, что при переносе элементов между строками (или «строками» в данном случае нет зазора). демо

Высота строк задается align-content, высотой элементов и содержимым элементов.

enter image description here


align-content и align-items работают вместе

Восстановить align-items: center. Теперь, когда элементы обертываются, между строками виден разрыв.

enter image description here

Это связано с тем, что align-items: center размещает элементы в вертикальном центре линии на основе высоты строк, установленной align-content: stretch, высоты элементов и содержимого элемента.

Здесь устанавливаются высоты линий (с align-content: stretch и align-items: stretch):

enter image description here

... и продолжить здесь (с align-content: stretch и align-items: center):

enter image description here

align-items не влияет на высоту гибкой линии. Эта работа сопровождается align-content.

Однако, изменяя значение align-content (на flex-start, flex-end, space-between, center и т. Д.), Вы упаковываете гибкие линии, выжимая свободное пространство и, следовательно, удаляя пробелы.

enter image description here


Почему первый ряд выше второго ряда с align-content: stretch?

Контейнер установлен на height: 800px.

Есть два предмета с определенной высотой:

  • .item-3 { height: 250px }
  • .item-4 { height: 300px }

Когда .item-5 и .item-6 образуют второй ряд, свободное пространство в контейнере в простейшей форме составляет 500px (800px - 300px).

Таким образом, в контейнере с двумя строками и align-content: stretch 250px распределяется по высоте каждой строки.

  • первая строка 300px (определенная высота) плюс 250px (свободное пространство)
  • второй ряд 250px (свободное место)

Вот почему первый ряд выше.

Просто обратите внимание, что приведенное выше вычисление свободного пространства немного отличается от фактического макета. Это потому, что в элементах есть текст, который занимает свободное место. Вы можете учесть высоту текста, чтобы получить точные цифры, или вообще удалить текст, чтобы увидеть приведенные выше расчеты.


Подробнее:

0 голосов
/ 03 ноября 2018

Чтобы было проще, я уменьшу код, чтобы мы могли лучше понять его поведение.

Давайте рассмотрим этот исходный код:

* {
  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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...