首页 > 解决方案 > 如果没有设置 flex-basis 或 width ,flexbox 如何计算 flex-item 的宽度?

问题描述

我想了解当没有为 、 或属性设置显式值时,flexbox 如何计算最终弹性flex-basis项目的宽度width。换句话说,flexbox 如何仅根据内容计算 flex-item 的宽度?min-widthmax-width

这是一个示例代码(可在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在此示例中,两个s(弹性项目)的计算宽度是相同的:(300px我使用“检查元素”调试工具看到)。

现在,如果我在第一个 div 中的文本中再添加 10 个字符(此处提供分叉的 codepen),我会看到第一个 div 的宽度为 ,311.719px而第二个 div 的宽度为288.281px.

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

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

标签: htmlcssflexbox

解决方案


对于这种特殊情况,您需要考虑默认的收缩效果集,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. 这两个元素的溢出将被减少,因此它们可以放入弹性容器中。我们还应该考虑元素不会以相同的方式收缩,因为它们没有相同的初始宽度。最大的会缩小更多。然后我们将有一个因子,1011.3/935.3 = 1.08公式将是:

x + y = 1346.6 where y = 1.08*x

所以x = 647pxy = 699.6px

我们将以1011.3px - 699.6px = 311.7pxand结束935.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 项将收缩多少。参考

注意:在分配负空间时,flex 收缩因子乘以 flex 基本大小。这会根据项目能够缩小的程度按比例分配负空间,例如,在较大的项目明显缩小之前,小项目不会缩小到零。参考

完整算法的官方规范:

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


请注意,存在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 属性以避免基于内容的元素大小的不确定性吗?

我会说是的。您应该完全控制您的布局,不要让内容为您做出决定。


推荐阅读