如果未设置flex-basis或width,flexbox如何计算flex-item的宽度?

时间:2019-06-13 12:30:55

标签: html css flexbox

我想了解在未设置flex-basiswidthmin-widthmax-width属性的显式值的情况下flexbox如何计算最终flex-item的宽度。换句话说,flexbox如何仅根据内容来计算flex-item的宽度?

以下是示例代码(可在codepen上获得):

.container {
  display: flex;
  width: 600px;
}

.container div {
  outline: 1px dotted black;
}
<div class="container">
  <div>Lorem ipsum dolor sit amet consectetur adipisicing elit. Fuga aspernatur suscipit aliquam beatae vitae harum, eius expedita quidem incidunt velit!</div>
  <div>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Error ad natus dolores harum, ex fuga voluptates dignissimos possimus saepe officia.</div>
</div>

在此示例中,两个div(弹性项目)的计算宽度是相同的:300px(我在“检查元素”调试工具中看到了此宽度)。

现在,如果我在第一个div(forked codepen available here)的文本中再添加10个字符,我会看到第一个div的宽度为311.719px,而第二个div的宽度为288.281px

因此,似乎更多的内容为弹性项目提供了更大的宽度,但是这种基于内容的计算究竟如何工作?如果内容不仅是文本,还包括一些替换的内容(例如图像),那该怎么办?

此外,我通常应该练习显式设置flex-basiswidth属性,以避免基于内容的元素大小不确定性吗?换句话说,什么是用例不显式设置flex-item的宽度,而将其留给flexbox根据其内容来确定呢?

1 个答案:

答案 0 :(得分:4)

对于这种特殊情况,您需要考虑flex-shrink设置的默认收缩效果,该效果的默认值为1。最初,您的元素将如下所示溢出:

$('div').each(function() {
 console.log($(this).width());
})
.container {
  display: flex;
  width: 600px;
}

.container div {
  outline: 1px dotted black;
  flex-shrink:0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
  <div>Lorem ipsum dolor sit amet consectetur adipisicing elit. Fuga aspernatur suscipit aliquam beatae vitae harum, eius expedita quidem incidunt velit! 123456789</div>
  <div>Lorem ipsum dolor sit amet consectetur adipisicing elit. Fuga aspernatur suscipit aliquam beatae vitae harum, eius expedita quidem incidunt velit!</div>
</div>

如果您检查元素,则第一个元素为1011.3px,第二个元素为935.3px,因此我们的总溢出量为1011.3px + 935.3px - 600px = 1346.6px。这两个元素的溢出都会减少,因此它们可以放入flex容器中。我们还应该考虑到元素不会以相同的方式收缩,因为它们的初始宽度不同。最大的将收缩更多。然后,我们将得到1011.3/935.3 = 1.08的因数,公式将为:

x + y = 1346.6 where y = 1.08*x

所以x = 647pxy = 699.6px

我们将以1011.3px - 699.6px = 311.7px935.3px - 673.3px = 288.3px结尾:

$('div').each(function() {
 console.log($(this).width());
})
.container {
  display: flex;
  width: 600px;
}

.container div {
  outline: 1px dotted black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
  <div>Lorem ipsum dolor sit amet consectetur adipisicing elit. Fuga aspernatur suscipit aliquam beatae vitae harum, eius expedita quidem incidunt velit! 123456789</div>
  <div>Lorem ipsum dolor sit amet consectetur adipisicing elit. Fuga aspernatur suscipit aliquam beatae vitae harum, eius expedita quidem incidunt velit!</div>
</div>


  

flex-shrink属性指定了flex收缩因子,该因子决定了在分配负自由空间时,flex项目相对于flex容器中其余flex项目将收缩多少。 ref

     

注意:分配负空间时,弯曲收缩系数是乘以弯曲基础尺寸。这会与物品能够收缩的程度成正比地分配负空间,以便例如在大件物品明显减少之前,小件物品不会缩小为零。 ref

完整算法的正式规范:

https://www.w3.org/TR/css-flexbox-1/#resolve-flexible-lengths


请注意,由于默认情况下为an element cannot shrink past its content size,因此存在min-width约束可能会影响最终计算。

这里与上面的代码相同,其中有一些&nbsp;,并且您会注意到计算是不同的,因为第一个元素的min-width约束与第一个句子的长度相等&nbsp;

$('div').each(function() {
 console.log($(this).width());
})
.container {
  display: flex;
  width: 600px;
}

.container div {
  outline: 1px dotted black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
  <div>Lorem&nbsp;ipsum&nbsp;dolor&nbsp;sit&nbsp;amet&nbsp;consectetur&nbsp;adipisicing elit. Fuga aspernatur suscipit aliquam beatae vitae harum, eius expedita quidem incidunt velit! 123456789</div>
  <div>Lorem ipsum dolor sit amet consectetur adipisicing elit. Fuga aspernatur suscipit aliquam beatae vitae harum, eius expedita quidem incidunt velit!</div>
</div>

如果通过添加min-width:0来消除此约束,则会得到以前的值和一些溢出:

$('div').each(function() {
 console.log($(this).width());
})
.container {
  display: flex;
  width: 600px;
}

.container div {
  outline: 1px dotted black;
  min-width:0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
  <div>Lorem&nbsp;ipsum&nbsp;dolor&nbsp;sit&nbsp;amet&nbsp;consectetur&nbsp;adipisicing elit. Fuga aspernatur suscipit aliquam beatae vitae harum, eius expedita quidem incidunt velit! 123456789</div>
  <div>Lorem ipsum dolor sit amet consectetur adipisicing elit. Fuga aspernatur suscipit aliquam beatae vitae harum, eius expedita quidem incidunt velit!</div>
</div>


  

什么时候内容不仅是文本,还包括替换的内容(例如图像)?

采用相同的逻辑,内容的类型并不重要,重要的是元素的大小和取决于内容的min-width约束。

  

此外,我通常应该练习显式设置flex-basis或width属性,以避免基于内容的元素大小不确定吗?

我会说是的。您应该完全控制布局,不要让内容由您自己决定。