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

前端 未结 1 335
忘掉有多难
忘掉有多难 2021-01-27 01:14

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

相关标签:
1条回答
  • 2021-01-27 01:41

    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.

    0 讨论(0)
提交回复
热议问题