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