如果未设置flex-basis或width,flexbox如何计算flex-item的宽度? [英] How flexbox calculates flex-item's width if no flex-basis or width are set?

查看:35
本文介绍了如果未设置flex-basis或width,flexbox如何计算flex-item的宽度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想了解在未为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中的文本中再添加10个字符(分叉的代码笔在此处可用),我看到第一个div的宽度为311.719px,而第二个div的宽度为288.281px.

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

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

解决方案

对于这种特殊情况,您需要考虑由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项目会收缩多少. 参考

注意:分配负空间时,柔韧性收缩因子是乘以柔韧性基本尺寸.这样会与物品能够收缩的程度成比例地分配负空间,例如在大件物品明显减少之前,小件物品不会缩小为零. 参考

完整算法的正式规范:

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

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

I want to understand how flexbox calculates final flex-item's width when no explicit value is set for flex-basis, width, min-width or max-width properties are set. In other words, how flexbox calculates flex-item's width based solely on content?

Here is an example code (available on 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>

In this example computed width of both divs (flex-items) is the same: 300px (which I see with "inspect element" debug tools).

Now if I add 10 more characters to the text in the first div (forked codepen available here), I see that first div has width of 311.719px while the second div's width is 288.281px.

So it seems that more content gives more width to the flex-item, but how does this content based calculation exactly works? What about when content is not just text but also some replaced content such as images?

Also, should I generally practice to explicitly set flex-basis or width properties to avoid uncertainties of element size that is based on content? In other words, what are use-cases to not set explicitly flex-item's width and leave it off for flexbox to determine it based on its content?

解决方案

For this particular case you need to conisder the default shrink effect set by flex-shrink which has a default value of 1. Initially your element will overflow like below:

$('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>

If you inspect the elements you will have 1011.3px for the first element and 935.3px for the second one so we have a total overflow of 1011.3px + 935.3px - 600px = 1346.6px. This overflow will be reduced from both elements so they can fit inside the flex container. We should also consider that the elements will not shrink the same way since they don't have the same initial width. The biggest one will shrink more. We will then have a factor of 1011.3/935.3 = 1.08 and the formula will be:

x + y = 1346.6 where y = 1.08*x

So x = 647px and y = 699.6px

We will end with 1011.3px - 699.6px = 311.7px and 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>


The flex-shrink property specifies the flex shrink factor, which determines how much the flex item will shrink relative to the rest of the flex items in the flex container when negative free space is distributed. ref

Note: The flex shrink factor is multiplied by the flex base size when distributing negative space. This distributes negative space in proportion to how much the item is able to shrink, so that e.g. a small item won’t shrink to zero before a larger item has been noticeably reduced. ref

Official Specificiation for the complete algorithm:

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


Be aware that there is the min-width constraint that may affect the final calculation since by default an element cannot shrink past its content size.

Here is the same code as above with some &nbsp; and you will notice that the calculation is different because the first element is having a min-width contraint equal to the length of the first sentence where we have the &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>

If you remove this constraint by adding min-width:0 you will get the previous values and some overflow:

$('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>


What about when content is not just text but also some replaced content such as images?

Same logic apply, it doesn't really matter the type of content, all what matter is the size of the element and the min-width contraint that depend on the content.

Also, should I generally practice to explicitly set flex-basis or width properties to avoid uncertainties of element size that is based on content?

I would say yes. You should have full control over your layout and don't leave the content take the decision for you.

这篇关于如果未设置flex-basis或width,flexbox如何计算flex-item的宽度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆