Ответ 1
Flexbox определяет это как
Для каждого незамерзающего элемента на линии умножьте коэффициент гибкости по его внутреннему гибкому базовому размеру, и обратите внимание на это как на масштабированный flex коэффициент сжатия. Найти соотношение элементов масштабированный flex shrink фактор на сумму масштабированных коэффициентов сжатия flex всего незамороженные предметы на линии. Задайте элементы основного размера для его размер flex base минус часть абсолютного значения оставшееся свободное пространство пропорционально отношению.
Упрощение, замороженные элементы гибкости - это те, которые больше не могут или не нужно сгибать. Я не буду принимать никаких ограничений min-width
и ненулевых коэффициентов усадки flex. Таким образом, все элементы flex изначально разморожены, и все они замерзают после одной итерации гибкого цикла.
Размер внутренней гибкой основы зависит от значения box-sizing
, определенного CSS2UI как
content-box
: Указанная ширина и высота (и соответствующие свойства min/max) применяются к ширине и высоте соответственно поле содержимого элемента. Прокладка и граница элемента выложены и выведены за пределы указанной ширины и высоты.
border-box
: Значения длины и процента для ширины и высоты (и соответствующих свойств min/max) этого элемента определяют поле границы элемента. То есть, любое заполнение или граница, указанные на элемент выложен и нарисован внутри указанногоwidth
иheight
. Ширина и высота содержимого вычисляются по формуле вычитая границы и ширину заполнения соответствующих сторон из заданные свойства ширины и высоты. [...] Используемые значения, как например, через getComputedStyle(), также ссылаются на поле границы.
В основном это означает, что размеры (ширины, основания изгиба) имеют внутренний внешний вариант. Внутренний размер включает только контент, внешний также включает прокладки и ширину границы. Длина, указанная в таблице стилей, будет использоваться как внутренний размер в случае box-sizing: content-box
, или как внешний в случае box-sizing: border-box
. Другой может быть рассчитан путем добавления или вычитания ширины границы и заполнения.
Пренебрегая множеством деталей, алгоритм будет похож на
let sumScaledShrinkFactors = 0,
remainingFreeSpace = flexContainer.innerMainSize;
for (let item of flexItems) {
remainingFreeSpace -= item.outerFlexBasis;
item.scaledShrinkFactor = item.innerFlexBasis * item.flexShrinkFactor;
sumScaledShrinkFactors += item.scaledShrinkFactor;
}
for (let item of flexItems) {
let ratio = item.scaledShrinkFactor / sumScaledShrinkFactors;
item.innerWidth = item.innerFlexBasis + ratio * remainingFreeSpace;
}
Без paddings, это, как вы объясните
(width)
innerW │ padd │ outerW
───────┼──────┼───────
300px * (1 + 2 / 1000px * -200px) = 180px │ 0px │ 180px
200px * (1 + 1 / 1000px * -200px) = 160px │ 0px │ 160px
100px * (1 + 2 / 1000px * -200px) = 60px │ 0px │ 60px
───────┼──────┼───────
400px │ 0px │ 400px
С горизонтальными прокладками 10px
доступное пространство уменьшается на 3 * 2 * 10px = 60px
, поэтому теперь оно -260px
.
(width)
innerW │ padd │ outerW
───────┼──────┼───────
300px * (1 + 2 / 1000px * -260px) = 144px │ 20px │ 164px
200px * (1 + 1 / 1000px * -260px) = 148px │ 20px │ 168px
100px * (1 + 2 / 1000px * -260px) = 48px │ 20px │ 68px
───────┼──────┼───────
340px │ 60px │ 400px
Когда вы используете box-sizing: border-box
, указанные основания flex являются внешними, поэтому выкладки вычитаются из них для вычисления внутренних, которые 280px
, 180px
, 80px
. Тогда сумма масштабированных коэффициентов усадки flex становится 2*280px + 180px + 2*80px = 900px
. Доступное пространство похоже на случай без прокладки, потому что внешние основания гибки одинаковы. Обратите внимание, что width
, полученный с помощью getComputedStyle
, теперь будет внешним, поэтому paddings добавляются обратно в конец.
(width)
innerW │ padd │ outerW
────────┼──────┼────────
280px * (1 + 2 / 900px * -200px) ≈ 155.6px │ 20px │ 175.6px
180px * (1 + 1 / 900px * -200px) = 140.0px │ 20px │ 160.0px
80px * (1 + 2 / 900px * -200px) ≈ 44.4px │ 20px │ 64.4px
────────┼──────┼────────
340.0px │ 60px │ 400.0px