The introduction

Recently I wanted to change the layout of my blog’s home page to add a few sidebars, so I took a look at some common layouts, such as the “flying wings layout” and the “Holy Grail layout”, which is an adaptive three-column layout with two sides fixed in the middle. However, I have always used Flex layout before. Is Flex layout also possible? I searched online and the code is as follows:

<html lang="en">
  <body>
    <div style="display: flex;">
      <div class="a"></div>
      <div class="b"></div>
      <div class="c"></div>
    </div>
  </body>

  <style>
    .a {
      background-color: thistle;
      width: 20%;
    }
    .b {
      background-color: tomato;
      flex: 1;
    }
    .c {
      background-color: violet;
      width: 100px;
    }
    .a..b..c {
      height: 100px;
    }
  </style>
</html>
Copy the code

This is very simple and much more elegant than the previous two layouts, but what puzzles me is flex: 1 in line 17, which is described in Teacher Ruan Yifeng’s blog

The flex attribute is short for flex-grow, flex-shrink, and flex-basis. The default value is 0 1 Auto.

Google search results also say that flex property is shorthand, so why flex: 1 can implement the middle part of the adaptive, this principle of black box has always puzzled me, flex exactly how to work, let’s investigate in detail. (See Teacher Ruan Yifeng’s blog post on the meaning of these attributes)

Syntax for flex properties

The first confusion is that the Flex attribute stands for flex-grow, flex-shrink, and Flex-basis. So why flex:1 followed by a number? The syntax of FLEX is the same as the syntax of CSS

none | [ <‘flex-grow’> <‘flex-shrink’>? || <‘flex-basis’> ]

Feel eyes seem to have spent, this how to understand, don’t worry we one by one analysis, | this symbol exclusive, can or the former for the latter, so that there are two types of grammar

flex: none;
flex: [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
Copy the code

Square brackets [] are followed to indicate ranges, which means flex attributes are followed by three numbers, such as:

{
  flex:1 1 100px
}
/ * is * /
{
  flex-grow:1
  flex-shrink:1
  flex-basis:100px
}
Copy the code

Look at symbols | | said means “or”, to the flex: [< > ‘flex – basis’] or for flex: [< >’ flex – turns’ < ‘flex – the shrink >], also can coexist. The symbol? “Shrink” means 0 or 1, which means flex-shrink is optional, and there are several combinations of these.

flex: [ <'flex-basis'> ]
flex: [ <'flex-grow'>]
flex: [ <'flex-grow'> <'flex-shrink'>]
flex: [ <'flex-grow'> <'flex-basis'> ]
flex: [ <'flex-grow'> <'flex-shrink'><'flex-basis'> ]
Copy the code

You can see that the Flex property is followed by a value in rows 1 and 2, and flex-basis is measured in units of length, so flex:1 equals flex-grow :1, so that the element fills the remaining space. This question seems to have been answered in terms of completing the “twin wing layout”, but the three values of the Flex property are far from straightforward.

Drill down into flex property values

A brief introduction to these three properties

  • flex-grow
    • Specifies the allocation rule when the container has more space. The default value is0Spare space is not allocated.
  • flex-shrink
    • Specifies the allocation rule for when the container runs out of space. The default value is1Lack of space to allocate.
  • flex-basis
    • Specifies a fixed number of allocations. The default isauto. For example, the Settings will be ignored at the same timewidthorheightProperties.

Flex-grow evaluates rules

For a single element

  • 0 = flex-grow
    • If there is some space left unallocated, that is, the length will not change, width is set to the same width, which is also the default state
  • 1 >= flex-grow
    • If there is any space left, it is allocated. In the case of only one element, the effect is that the element is full
  • 0 < flex-grow < 1
    • This is a rare case, and flex-grow / 1, where the element allocates space to allocatable space, is an intuitive example

The demo code is as follows:

<html>
  <body>
    <div class="flex">
      <div class="a"></div>
    </div>
  </body>
  <style>
    .flex {
      display: flex;
      background-color: violet;
    }
    .a {
      background-color: thistle;
      width: 100px;
      flex-grow: 0.1;
      height: 100px;
    }
  </style>
</html>

Copy the code

The original width of element A was 100px, then manually set the Flex width to 500px and check the actual width of element A at 140px

Allocated space (140-100 =40) = allocated space (500-100=400px) * flex-grow (0.1) so the actual width of the element = its length (100) + allocated space (40) = 140px

Multiple elements

There are also three cases where 0 is easy to understand and I’m not going to introduce it

Is greater than 1

  • At this point, the remaining space is allocated proportionally according to the value of flex-grow
<html lang="en">
  <body>
    <div class="flex">
      <div class="a"></div>
      <div class="b"></div>
      <div class="c"></div>
    </div>
  </body>

  <style>
    .flex {
      display: flex;
      background-color: violet;
    }
    .a {
      background-color: thistle;
      width: 100px;
      flex-grow: 1;
    }
    .b {
      background-color: tomato;
      width: 100px;
      flex: 2;
    }
    .c {
      background-color: violet;
      width: 100px;
      flex: 3;
    }
    .a..b..c {
      height: 100px;
    }
  </style>
</html>
Copy the code

As you manually set the Flex element width to 500px, let’s take a look at the actual widths of the three elements

A Actual width = (500-300=200) * (1/1 +2+3) + set width (100) = 33.33 + 100 =133.33

When the flex-grow values of all elements add up to less than 1

  • The actual allocated space is equal to the sum of the allocated space * flex-grow
<html lang="en">
  <body>
    <div class="flex">
      <div class="a">a</div>
      <div class="b">b</div>
      <div class="c">c</div>
    </div>
  </body>

  <style>
    .flex {
      display: flex;
      background-color: violet;
    }
    .a {
      background-color: thistle;
      width: 100px;
      flex-grow: 0.1;
    }
    .b {
      background-color: tomato;
      width: 100px;
      flex-grow: 0.2;
    }
    .c {
      background-color: aqua;
      width: 100px;
      flex-grow: 0.3;
    }
    .a..b..c {
      height: 100px;
    }
  </style>
</html>

Copy the code

You can see that the elements don’t take up space. Look at the actual width

A Actual width = actual allocated space * (0.1/0.1 +0.2+0.3) + Set width (100) = 20 + 100 =120

Sum of actual allocated space = allocated space * flex-grow

In this example, the actual allocated space is 200 * (0.1+0.2+0.3) =120.

The flex-grow elements all have values less than 0 but add up to more than 1

In fact, if you think about it, and the sum is greater than 1, you fill up the distributable space, and then you allocate it proportionally

The flex-grow element can be greater than or less than 1

It’s actually the same conclusion, once you’ve filled up the space that you can allocate, then you divide it proportionally

conclusion

If the sum of all flex-grow values is greater than 1, the remaining space will be allocated proportionally. If the sum of all flex-grow values is less than 1, the remaining space will be allocated proportionally. It doesn’t take up all the remaining space.

The flex-shrink calculation rule

The default value of the flex-shrink attribute is 1, which means that each element shrinks in the same size as the parent element. The default value is 1, which means that each element shrinks in the same size as the parent element. If the elements are of equal width:

<html lang="en">
  <body>
    <div class="flex">
      <div class="a">a</div>
      <div class="b">b</div>
      <div class="c">c</div>
    </div>
  </body>

  <style>
    .flex {
      display: flex;
      background-color: violet;
    }
    .a {
      background-color: thistle;
      width: 200px;
      flex-shrink: 1;
    }
    .b {
      background-color: tomato;
      width: 200px;
      flex-shrink: 2;
    }
    .c {
      background-color: aqua;
      width: 200px;
      flex-shrink: 3;
    }
    .a..b..c {
      height: 100px;
    }
  </style>
</html>

Copy the code

Manually set the Flex element width to 400px to look at the actual widths of the three child elements

It’s easy to calculate

Shrinkage length of element C = actual length (200) – excess length (600-400) * (3/1+2+3) = 100

The calculation is exactly the same as flex-grow, but what happens when the elements are of different lengths?

<html lang="en">
  <body>
    <div class="flex">
      <div class="a">a</div>
      <div class="b">b</div>
      <div class="c">c</div>
    </div>
  </body>

  <style>
    .flex {
      display: flex;
      background-color: violet;
    }
    .a {
      background-color: thistle;
      width: 100px;
      flex-shrink: 1;
    }
    .b {
      background-color: tomato;
      width: 200px;
      flex-shrink: 2;
    }
    .c {
      background-color: aqua;
      width: 300px;
      flex-shrink: 3;
    }
    .a..b..c {
      height: 100px;
    }
  </style>
</html>
Copy the code

A = 14.28 B = 57.14 C = 128.58 It can be seen that the shrink length is not proportional to the respective flex-shrink value of the element. The detailed calculation method is not found in the W3 documentation and MDN. The shrink length of a Flex-grow element depends not only on the flex-grow value but also on the size of the element itself, as shown in the following formula:

Shrink length = (element width * flex-shrink)/(100 * 1+200 * 2+300 * 3) * required shrink width

Shrink length =100 * 1/ (100 * 1+200 * 2+300 * 3) * (600-400) = 14.28 = 100-85.72 Waiting for! Forget the flex-grow case where the sum of flex-grow is less than 1.

<html lang="en">
  <body>
    <div class="flex">
      <div class="a">a</div>
      <div class="b">b</div>
      <div class="c">c</div>
    </div>
  </body>

  <style>
    .flex {
      display: flex;
      background-color: violet;
    }
    .a {
      background-color: thistle;
      width: 100px;
      flex-shrink: 0.1;
    }
    .b {
      background-color: tomato;
      width: 200px;
      flex-shrink: 0.2;
    }
    .c {
      background-color: aqua;
      width: 300px;
      flex-shrink: 0.3;
    }
    .a..b..c {
      height: 100px;
    }
  </style>
</html>

Copy the code

As you can see, the sum of the three elements is greater than the length of the Flex elements, which means that there is no “complete” shrinkage of each element

Actual total shrink length = sum of required shrink length * flex-shrink

In this case, the actual shrinkage length = 200 * 0.6 = 120 = 600-480 (total length after shrinkage), which is consistent with the actual, the actual shrinkage length of each element is the same as the method mentioned above.

Summary of calculation methods

Although the above calculation formula looks complicated, it is actually relatively simple after understanding it, as summarized by Zhihu @ Xie Ran:

If the sum of flex-grow/shrink of all elements is greater than or equal to 1, then all child elements must be adjusted to the size of the parent element (regardless of Max /min-width/height), whereas if the sum of flex-grow/shrink is less than 1, The ratio of the sum of all flex-grow/shrink elements to 1 is only grown or shrink. The weight of each element in grow is the flex-grow value of the element; The weight of each element in shrink is the flex-shrink multiplied by width.

conclusion

When it comes to Flex layout, who can not say a few words, as if the world is using Flex layout, but do you really know, I actually started to contact CSS when using Flex layout, vertical center what play special 6, but in these days I have a real understanding of Flex properties. It also made me realize that ignorance is a bad habit in the tech world. It’s easy to just write flex:1 to achieve a three-column layout, but when the requirements change, it’s impossible. Only by truly understanding the underlying principles can we achieve what we want in our hearts. Another point is that the source of your information largely determines the accuracy and authenticity of your information. The official website documents are always the most correct and perfect. Try to find the answer from the source of information. Strong as Ruan Yifeng teacher’s Flex tutorial for flex attribute description is not clear enough, Google will always be better than Baidu. This is the end of our in-depth digging. You may find that there is still flex-basis, because it is also a property with many details, but the details are different from those of the two that need to be calculated. It is worth writing a separate article to introduce it, and we will talk about it in detail in the next article.

Refer to the article

  • MDN flex
  • CSS Flexible Box Layout Module Level 1
  • flex-grow is weird. Or is it?
  • Flex -grow and flex-shrink
  • CSS Flex properties for an in-depth understanding of links