Is there a difference between flex-Basis, flex-Grow and width? What is the recommendation for using them in a Flex container?

Asked

Viewed 1,399 times

4

I have a technical question about using the property flex-basis, flex-grow and width. Note that in the image below I got the same result using the 3 properties.

Then I was in doubt, if the 3 properties do the same thing I should consider to choose between one and the other?

Is there really some technical difference between one and the other, or can I use any of them?

inserir a descrição da imagem aqui

This is the code of the image above:

html, body {
    margin: 0;
    padding: 0;
}
.container {
    display: flex;
    width: 100%;
}
.box {
    box-sizing: border-box;
    border: 1px solid #000;
    height: 20px;
}
.container.b .box {
    flex-basis: 50%;
}
.container.w .box {
    width: 50%;
}
.container.f .box {
    flex-grow: 1;
}

    
    
<p>pai flex e filho com flex-basis</p>
<div class="container b">
    <div class="box"></div>
    <div class="box"></div>
</div>
<p>pai flex e filho com width</p>
<div class="container w">
    <div class="box"></div>
    <div class="box"></div>
</div>
<p>pai flex e filho com flex-grow</p>
<div class="container f">
    <div class="box"></div>
    <div class="box"></div>
</div>

  • 1

    An explanation with several examples: https://origamid.com/projetos/flexbox-guia-completo/

  • This guide is really good!

2 answers

3

He obtained the same by an innocent coincidence, that is, in this particular situation resulted in the same thing, being two child elements and using 50%. Not always - in fact almost never - will have that sort in development.

  • width sets the width of the widget, no matter the rest;
  • flex-basis defines the initial element reference before to distribute space;
  • flex-grow defines how the parent element space will be distributed among the children;

We must remember that by default, flex will have the value 0 1 auto, what configures flex-grow like 0, flex-shrink as 1 and flex-basis as auto.

Width

Thus, using width in the child elements with the father flex will have a peculiar behavior due to the fact that being flex the space will be distributed among the children enlarging them according to their rules or shortening them if it occurs overflow in the parent element. It turns out to put width: 50% in two elements children you mask the behavior of flex, because naturally it will occupy the entire width of the parent element without overflow. However, try to put more child elements or a width greater than 50%:

Flex parent element with children over 50%

.pai {
  display: flex;
  background: lightgray;
}

.filhos {
  width: 80%;
  border: 1px solid black;
}
<div class="pai">
  <div class="filhos">short</div>
  <div class="filhos">looooooooooooooong</div>
</div>

What happens is that the property width: 80% will be ignored due to overflow occurring in the parent element and therefore the 80% will no longer be followed, keeping the basic rule defined by flex.

Flex parent element with more than two children

.pai {
  display: flex;
  background: lightgray;
}

.filhos {
  width: 50%;
  border: 1px solid black;
}
<div class="pai">
  <div class="filhos">short</div>
  <div class="filhos">looooooooooooooong</div>
  <div class="filhos">short</div>
</div>

Similarly, when there are more than two elements with 50% width again the overflow in the parent element would occur, causing the elements to reduce to approximately 33% of the total width (to 3 children).

That is, the width does not do what it seems to do, only produced the result expected by coincidence of having used the correct values.

Flex-Grow

To property flex-grow determines how the free space available in the parent element will be distributed to the child elements. You used flex-grow: 1, which determines that all child elements will grow equally. The coincidence that occurred in this case was that both elements have exactly the same content: none. Possessing the same content the elements will grow identically, but if one element has a different content width than the other, this does not occur. Let’s take an example:

Child elements with flex-Grow:1 and distinct content

.pai {
  display: flex;
  background: lightgray;
}

.filhos {
  flex-grow: 1;
  border: 1px solid black;
}
<div class="pai">
  <div class="filhos">short</div>
  <div class="filhos">looooooooooooooong</div>
  <div class="filhos">short</div>
</div>

The second child has a different content than the other two. Not only different but bigger. We further determine that the free space of the parent element should be divided equally for the child elements - and this does not mean that the children will have the same width at the end. If I want to divide R $ 30,00 equally between 3 people, I will give R $ 10,00 each. If one of the three people already initially has more money than the others, she will naturally have more money after I give the R $ 10,00. The same goes for the child elements. Inspect the result of the above example and you will see that the second element will be larger than the other two.

What defines the reference width is precisely flex-basis. As we commented initially, by default flex-basis will have the value auto, which shall take into account the value of width, which by default will also have the value auto. Thus, the elements grow considering the initial width.

Flex-Basis

To property flex-basis will determine what the reference will be for an element to grow within an element flex. By default the value will be auto, which, depending on the element, will consider the minimum width of the element according to its content, however you can determine a specific width as reference and all elements will be resized from it.

Child elements with flex-Basis: 50%

.pai {
  display: flex;
  background: lightgray;
}

.filhos {
  flex-basis: 50%;
  border: 1px solid black;
}
<div class="pai">
  <div class="filhos">short</div>
  <div class="filhos">looooooooooooooong</div>
  <div class="filhos">short</div>
</div>

What will happen in this example is that, other than just using the flex-grow, the reference width shall be 50% of the parent element. In this way, the three child elements will start from the same reference width and when resized by the flex will have the same final width. When inspecting the result you will see that the three elements have the same width. The coincidence was to have only two child elements, starting from the same reference width, being resized to the same final value.

In conclusion, the three properties do not do the same thing. A width determines the width of the element, regardless of how it will resize; and flex-grow determines how the element will be resized considering the empty space in the parent element and flex-basis determines which reference width before resizing the element with flex-grow.

What I must consider to choose between one and the other?

You do not consider between one or the other, they are complementary to each other and use the ones you need to get the desired result.

  • I need elements that occupy half the parent element: width: 50%, without flex;
  • I need elements that occupy the entire width of the parent element growing equally: flex-grow: 1;
  • I need elements that grow from the same value: flex-basis: 1;

For your example, if you need the elements to have at all times 50% of the width of the parent element, use the width: 50% and forget the flex. If you want them grow until they occupy the entire parent element, use flex-grow: 1. If you need them to have the same width at the end, use flex-basis to define the same reference.

  • Thanks Anderson this helps a lot to clear up the idea!

2


flex-Basis

Sets the initial width of the element. The width of the element is flexible and can be increased if there is no line break, but also the width can be reduced if another element a force. In the example below the .box2 of the first .container there is no line break (because of the &nbsp;) and its content, for being very wide, forces the width of the .box1 be less than defined in flex-basis of 50%.

Example:

.container{
   display: flex;
}

.box{
   border: 1px solid black;
}

.box1{
   flex-basis: 50%;
}

.box2{
   flex-basis: 20%;
}
<div class="container">
   <div class="box box1">
      box1 - mínimo 50% do container, com quebra de linha
   </div>
   <div class="box box2">
      box2&nbsp;-&nbsp;mínimo&nbsp;20%&nbsp;do&nbsp;container,&nbsp;sem&nbsp;quebra&nbsp;de&nbsp;linha
   </div>
</div>

<div class="container">
   <div class="box box1">
      box1 - mínimo 50% do container, com quebra de linha
   </div>
   <div class="box box2">
      box2
   </div>
</div>

flex-Grow

Sets the width of the element relative to the other elements of the same container. If there is only 1 element, it will occupy the whole width, as there is no one to compare it with.

The value of this property is numerical, that is, it does not have a unit of measure (px, %, vw etc.). CSS will sum up all values of flex-grow of the elements and divide the container width between them proportionally to their value.

Example:

.container{
   display: flex;
   min-height: 20px;
}

.box{
   border: 1px solid black;
}

.box1{
   flex-grow: 1;
}

.box2{
   flex-grow: 4;
}

.box3{
   flex-grow: 5;
}
<div class="container">
   <div class="box box1">
   </div>
   <div class="box box2">
   </div>
   <div class="box box3">
   </div>
</div>

<div class="container">
   <div class="box box1">
      box1
   </div>
   <div class="box box2">
   </div>
   <div class="box box3">
   </div>
</div>

See that in the first container the .box1 and .box2 occupy exactly half of the container, because adding up the values of the 3 empty boxes (1 + 4 + 5 = 10), thus 1 + 4 = 5, half of the total of 10.

Also note that in the second container there is text in the .box1, and the space occupied by the text is considered by flex-grow. As a result, there is a forced reduction in .box3 proportional to the width occupied by the text of .box1.

width

Sets a fixed width to the element. Even if there is no line break, the width is not flexible and if the content exceeds the width of the element, it does not expand.

Example:

.container{
   display: flex;
}

.box{
   border: 1px solid black;
}

.box1{
   width: 10%;
}
<div class="container">
   <div class="box box1">
      Texto&nbsp;sem&nbsp;quebra&nbsp;de&nbsp;linha
   </div>
</div>

<div class="container">
   <div class="box box1">
      Texto com quebra de linha
   </div>
</div>


The technical differences are as above, so you should use the one that is best convenient. What you might consider to use one of them, besides your need, is the compatibility issue, especially the properties flex-basis and flex-grow, which are more modern specifications. See the tables reported by the website Can I Use (both have the same table and observations):

flex-Basis and flex-Grow

  • Very good explanation Uncle!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.