Почему отступ расширяет гибкий элемент?

В приведенном ниже фрагменте, первый ряд имеет два элемента div с flex-grow: 1, Как и ожидалось, каждый div занимает 50% экрана.

При добавлении отступа к левому элементу div это уже не так. Может кто-нибудь объяснить почему?

body > div {
  height: 50px;
  display: flex;
}
body > div > div {
  flex: 1;
  box-sizing: border-box;
}
#a {
  background-color: red;
}
#b {
  background-color: green;
}
#c {
  padding: 10px;
  background-color: blue;
}
#d {
  background-color: yellow;
}
<div>
  <div id="a"></div>
  <div id="b"></div>
</div>
<div>
  <div id="c"></div>
  <div id="d"></div>
</div>

6 ответов

Расчеты определены в спецификации.

Размер гибкого элемента с подкладкой и flex-grow определяется расчетами в спецификации flexbox.

Эти расчеты аналогичны размеру гибких элементов с отступами и flex-shrink,

Честно говоря, математика довольно техническая и не самая легкая вещь в мире для понимания.

Но если вы хотите попасть в это, вот подробности:


Примеры

Ниже приведены примеры, которые, надеюсь, сделают поведение более понятным.

ПРИМЕЧАНИЕ: имейте в виду, что flex-grow не является инструментом для непосредственного определения длины гибкого элемента. Это инструмент для распределения пространства в контейнере среди гибких элементов. flex-basis Свойство устанавливает начальный основной размер гибкого элемента. Если flex-grow используется с flex-basisпроблема в вопросе решена (см. пример № 4 ниже).

Пример № 1

В блок-контейнере, где у вас есть box-sizing: border-box поля в вашем коде будут отображаться равномерно независимо от заполнения.

body > div {
  height: 50px;
  /* display: flex; */
  font-size: 0; /* remove inline block whitespace */
}
body > div > div {
  /* flex: 1; */
  box-sizing: border-box;
  height: 50px;
  display: inline-block;
  width: 50%;
}
#a {
  background-color: red;
}
#b {
  background-color: green;
}
#c {
  padding: 10px;
  background-color: blue;
}
#d {
  background-color: yellow;
<div>
  <div id="a"></div>
  <div id="b"></div>
</div>
<div>
  <div id="c"></div>
  <div id="d"></div>
</div>

jsFiddle demo


Пример № 2

В гибком контейнере, где у вас есть box-sizing: border-box и width или же flex-basis используется для расчета длины, поля будут отображаться равномерно, независимо от заполнения.

body > div {
  height: 50px;
  display: flex;
  }

body > div > div {
  flex-basis: 50%;
  /* width: 50%; this works, as well */
  box-sizing: border-box;
}

#a {
  background-color: red;
}
#b {
  background-color: green;
}
#c {
  padding: 10px;
  background-color: blue;
}
#d {
  background-color: yellow;
<div>
  <div id="a"></div>
  <div id="b"></div>
</div>
<div>
  <div id="c"></div>
  <div id="d"></div>
</div>

jsFiddle demo


Пример № 3

В гибком контейнере, где у вас есть box-sizing: border-box а также flex-grow окажется, что box-sizing не работает...

body > div {
  height: 50px;
  display: flex;
  }

body > div > div {
  flex: 1;
  /* flex-basis: 50%; */
  /* width: 50%; this works, as well */
  box-sizing: border-box;
}

#a {
  background-color: red;
}
#b {
  background-color: green;
}
#c {
  padding: 10px;
  background-color: blue;
}
#d {
  background-color: yellow;
<div>
  <div id="a"></div>
  <div id="b"></div>
</div>
<div>
  <div id="c"></div>
  <div id="d"></div>
</div>

jsFiddle demo

но это не совсем правильно...


Пример № 4

flex-grow расширяет ширину гибкого элемента на основе доступного пространства в гибком контейнере. Другими словами, он игнорирует отступы ( и границы).

Однако, если вы просто укажите flex-grow вместе с flex-basis, border-box буду работать:

flex: 1 1 50%; /* flex-grow, flex-shrink, flex-basis */

body > div {
  height: 50px;
  display: flex;
  }

body > div > div {
  flex: 1 1 50%; /* flex-grow, flex-shrink, flex-basis */
  /* flex-basis: 50%; */
  /* width: 50%; this works, as well */
  box-sizing: border-box;
}

#a {
  background-color: red;
}
#b {
  background-color: green;
}
#c {
  padding: 10px;
  background-color: blue;
}
#d {
  background-color: yellow;
<div>
  <div id="a"></div>
  <div id="b"></div>
</div>
<div>
  <div id="c"></div>
  <div id="d"></div>
</div>

jsFiddle demo

Это правильное поведение, насколько я знаю.

flex:1 это, конечно, сокращение для:

flex-grow:1;
flex-shrink:1;
flex-basis:0

Это позволяет div при необходимости расти, что в данном случае и происходит. Он не будет автоматически поддерживать flex-элементы одинакового размера, если они на самом деле разные.

Tldr: Это ошибка. , Ссылка2

Альтернативное решение последнего примера Майкла Бенджамина:

Подать заявление flex-basis: 20px /*2 X padding of sibling*/ к желтому div#d

Как видите, оба flex-basis: 0 а также flex-basis: padding_left + padding_rightэквивалентны. Мало того, что любое значение <будет считаться эквивалентным flex-basis знак равно padding_left + padding_right. Что касается того, почему происходит такое поведение, я думаю, что это какая-то несогласованность / ошибка, Ссылка1предложенная здесь w3.org (снова Ссылка1) . Другими словами box-sizing: border-box игнорируется.

Это не ошибка, и поведение четко описано в Спецификации (ясно, но не очевидно).

Здесь речь идет о размере гибкой базы . Ты можешь читать:

Определите базовый размер гибкости и гипотетический основной размер каждого элемента:

Обратите внимание на гипотетический основной размер, который здесь является важной частью.

Каждый элемент имеет flex:1 так flex-basis:0 что означает размер гибкого основания, равный 0

A. Если у предмета есть определенная используемая гибкая основа, это размер гибкой основы.

Теперь продолжим до конца и прочитаем следующее:

При определении базового размера гибкого элемента минимальный и максимальный основные размеры элемента игнорируются.

До сих пор все в порядке. При нахождении базового размера гибкости мы игнорируем все.

Давай продолжим:

Гипотетическая Основной размер гибкого размера база элемента зажимается в соответствии с его использованного минимального и максимального размеров основных (и напольных покрытий размер коробки контента в нуле).

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

Теперь, если вы проверите остальную часть алгоритма flexbox, вы заметите, что гипотетический основной размер - это тот, который используется, что дает нам логический результат увеличения элемента с заполнением.

На этом этапе размер гибкого элемента - это его внешний гипотетический основной размер.

Суммируйте внешние гипотетические основные размеры всех элементов в строке.

так далее

Тривиально, если убрать flex-grow

Изменение свойства box-sizing на border-box в CSS включает отступы и границы в общую ширину и высоту элемента, не влияя на его размер при добавлении отступов или границ.

Обычной практикой является применение размеров коробки: border-box; глобально для всех элементов вашего CSS:

      * {
    box-sizing: border-box;
  }

Это происходит потому, что ваш **padding** больше, чем **flex-basis**Это буквально все. Если вы просто измените это, это будет исправлено.

Другие вопросы по тегам