background
Often in some business scenarios, we need to achieve the effect that the child elements occupy the space of the parent element equally. So far, the most I’ve used is flex: 1. It wasn’t until ONE day I wanted to use Flex-Grow: 1 to achieve the same effect, but the browser gave me a different performance that I realized I had left out the key word free space. I’ve always thought about space allocation based on the width of the Flex Container, simply equating Flex: 1 with Flex-grow: 1. This article is a summary of my relearning of Flexbox, focusing on flex, flex-basis, Flex-grow, and Flex-shrink attributes.
In Firefox you can see some size data for the flexbox layout nodes, but Chrome doesn’t seem to be able to, so all the code in this article is reviewed in Firefox, which is 65.0.2 for me.
Flexbox basic concept
Some of the basics have been explained in detail in other articles, so this article is just a brief description.
-
First, set the display: The Flex element becomes a Flex Container, creating a Flex Formatting Context (FFC), and the element itself is represented as a block-level element. Accordingly, elements with Inline-Flex are represented as inline elements.
-
The elements inside the Flex Container become Flex Items, including the inner plain text (which is wrapped in an anonymous block-level box). The absolute positioning element is not a Flex item because it does not participate in the Flex layout.
-
Finally, when you do a Flex layout, Flex takes effect, either fully filling the Flex Item into the available space of the Flex Container, or shrinking the Flex Item to prevent overflow. Once all Flex items have been sized, they are arranged and laid out according to properties such as context-content, align-self, and so on.
flex-basis
flex-basis
Will replaceflex itemWidth /height in the main axis direction, and in theBefore allocating free spaceInitialize theflex itemSpindle size.
Accept the same values as width or height, such as value, percentage, auto, min-content, and max-content, as well as content.
-
auto
If auto is specified, the value of the current Flex item’s axis size attribute (width/height) is used. If auto is specified, content is used, which is determined by the flex item’s content size. For example:
<div style="display: flex; width: 200px; border: 1px dotted #333;"> <div id="first" style="background: #eee; width: 80px; flex-basis: auto;"> short text </div> <div id="second" style="background: #ccc; flex-basis: auto;"> very looooooooong text </div> </div> Copy the code
Using Firefox (supported
content
, butmin-content
和max-content
Is invalid value) when examining the node, you can see: Because it’s setwidth: 80px
, sodiv#first
The base size is 80px, whilediv#second
Is the width ofauto
, so its base size is based on its content, the content size. -
Content (poor compatibility)
When specified as content, the size is based on the content size of the Flex item. Equivalent to using width: max-content. Chrome does not support this value, Firefox can use this value.
flex-grow
In short,flex-grow
Refers to the currentflex itemAvailable from theflex containerWhat percentage of the positive free space will be allocated.
There is a keyword positive free space, which I misunderstood as the whole Content box of Flex Container.
For example, flex-grow: 1 means 100% positive free space, flex-grow: 0.5 means 50%, and so on. Therefore, when the sum of all flex-grow items is less than 1, the flex items are not allocated 100% positive free space, so there will be space left. When the sum of all flex-grow is greater than 1, the scale is recalculated based on 100%; after all, no more than 100% space can be allocated.
flex-shrink
Definitions in MDN:
The Flex-shrink attribute specifies the shrink rule for flex elements. Flex elements shrink only when the sum of the default widths is greater than the container, depending on the flex-shrink value.
You can use negative free space to express the amount of space that is spilled. Unlike Flex-grow, if flex-grow: 1 is specified, it is not simply understood that the Flex item wants to be allocated 100% negative free space. Here 1 corresponds to a weight, and the exact calculation is described in how to calculate elasticity.
Among the shrink rules is the concept of content-based minimum size, which literally translates to the minimum size of the content. It limits how much a Flex Item can shrink and does not shrink a Flex Item to a smaller size. Its value can be a defined main axis property value (width/height) or min-content. And this concept will be used in how we calculate elasticity.
flex
Flex: 0 1 auto is its initial value. That is, by default, flex items can be shrunk but not stretched in the main axis dimension, and are sized by width/height.
Flex: 1 1 0 (flex:
How to calculate the elasticity
<div style="display: flex; width: 200px; border: 1px dotted #333;">
<div id="first" style="background: #eee;">
short text
</div>
<div id="second" style="background: #ccc; width: 280px;">
very looooooooong text
</div>
</div>
Copy the code
Take the code above as an example:
-
determineMain AxistheAvailable space, that is,flex container 的 content boxMay be a definite size or may need to be calculated.
The free space in this example is 200px.
-
According to the
flex-basis
Identify eachflex item 的Flex Base Size.Since div#first’s flex-basis and width are both auto, its base size is its content size, which is 59.93px as you can see from the Firefox review node. Div# second is set to width: 280px, so 280px is its base size.
Also, max-min constraints (min-wdith and max-width in this example) are ignored in this step. If I give div#first a min-width: 100px, its base size will still be 59.93px. When these constraints take effect will be seen in the next steps.
-
** Calculate the sum of the main size of the Flex item to determine whether to use flex-grow or flex-shrink.
In the example, you can see that the sum is 339.93px, which is larger than the size of the Flex Container, so you can be sure that Flex-shrink works.
-
Determine the size of positive free space or negative free space.
First, you need to calculate the sum of flex-shrink in the example, which gives you a value of 2. Negative free space is 339.93px — 200px = 139.93px because it is greater than 1.
-
For eachflex itemdistributionfree spaceTo determine the size after modification.
Because what works in this case is
flex-shrink
Property, so eachflex itemThe final size of is the base size minus what it is allocated tonegative free space. So, each of themflex itemHow much should be allocated?In this formula, you can see the base size andflex-shrink
Is multiplied by the values of, that is, aboveflex-shrinkThe weight of. This formula can be easily applied:div#first
: (339.93-200) * 59.93 / (59.93 + 280) = 24.67pxdiv#second
: (339.93-200) * 280 / (59.93 + 280) = 115.26px
So finally the width of div#first is 35.27px and div#second is 164.73px. In this case, this is the final size, which you can see in the Firefox censor node.
However, if will
div#second
Adjust the width to1000px
And then there’s this next step, which we can seeflex-shrinkReferred to in thecontent-based minimum sizeThe maximum and minimum constraints in Step 2 also take effect. -
According to themin/max-width(min/max-height)orcontent-based minimum sizecorrectionflex itemThe size of the.
We set the width of div#second to 1000px and apply the formula above:
div#first
: (1059.93-200) * 59.93 / (59.93 + 1000) = 48.62pxdiv#second
: (1059.93-200) * 1000 / (59.93 + 1000) = 811.31px
If you didn’t write this down, you might think
div#first
The final size is 59.93-48.62,div#second
It’s 1000-811.31. We can check it in Firefox:div#first
The content size and elasticity are exactly what we expected, and the final size is 31.97px. Here it iscontent-based minimum sizeIn effect, it usesdiv#first
的min-content
As its value.If we set a certain theta
width
, the content-based minimum size is actually takenwidth
和min-content
The minimum value between, for examplewidth: 10px
, thendiv#first
The final size is 10px.I just want the final size of div#first to be 59.93-48.62 = 11.31px. How do I do that? Add min-width: 5px to div#first so that its final size is 11.31px.
If flex-grow works, how is it calculated
Take this code as an example:
<div style="display: flex; width: 300px; border: 1px dotted #333;">
<div style="background: #eee; flex-grow: 2;">
short text
</div>
<div style="background: #ccc; flex-grow: 1;">
very looooooooong text
</div>
</div>
Copy the code
- First, the free space for the spindle is 300px.
- eachflex itemThe base dimensions are their content dimensions, which are 59.93px and 152.82px respectively.
- flex itemThe sum of the spindle dimensions is 212.75px, so
flex-grow
To take effect. - determinepositive free spaceThe size is 87.25px.
- To calculateflex itemAssigned to thepositive free space, 87.25 * 2 / (2 + 1) = 58.17px and 87.25 * 1 / (2 + 1) = 29.08px respectively. Make sure the final dimensions are 118.1px and 181.9px.
The last
This summary basically covers the business scenarios I’ve encountered so far, and there may be more scenarios to tweak my understanding of Flexbox in the future. The W3C has a very detailed and complex introduction of the Flex layout algorithm, and this article has made some adjustments and simplification. If you want to learn more, go to the W3C for some introductions.