简体   繁体   中英

How flexbox calculates flex-item's width if no flex-basis or width are set?

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 div s (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 eg 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM