How to control the proportion of Flex child elements on the main axis

How to control the proportion of Flex child elements on the main axis

background

Flex layout achieves alignment and space allocation more effectively. Recently, I have been learning about the size calculation rules of flex child elements, mainly the calculation rules of flex-grow and flex-shrink .

1. Basic Concepts

1.1 Main axis

The starting point and direction of the flex element layout are defined, and the flex child elements are placed one by one on the main axis.

The main axis has four directions, specified by flex-direction :

  • row

Horizontal direction, from left to right, default

  • row-reverse

Horizontal direction, from right to left

  • column

Vertical direction, from top to bottom

  • column-reverse

Vertical direction, from bottom to top

1.2 Main axis size

It is the size of the flex container content rectangle (excluding padding, border, and margin areas) in the main axis direction.

1.3 Cross axis

The cross axis is the direction of the main axis hammer and is mainly used for the alignment of flex elements.

1.4 Cross axis size

It is the size of the flex container content rectangle (excluding padding, border, and margin areas) in the Cross axis direction.

1.5 flex box model

An element with display set flex or inline-flex is also called a flex container.

1. A flex container contains not only flex items, but also empty space.

2. CSS involved flex-directionflex-wrapflex-flow

  • flex-direction
  • flex-wrap
  • flex-flow

Short for flex-direction and flex-wrap.

  • justify-content

Controls the alignment of the flex container content (flex items and empty space) along the main axis. Pay attention to the distinction between align-items.

  • align-content

Controls the alignment of the lines in a multi-line flex container.

  • align-items

Controls the alignment of the flex container content (flex items and empty space) in the cross axis direction.

Tip:

1. These CSS properties are all related:

First, specify the main axis direction of the flex container (flex-direction). If the flex child element exceeds the main axis size, it involves whether to wrap (flex-wrap). If the main axis size is not exceeded, then it involves inline alignment (justify-content). If there are multiple lines, each line must also be aligned directly (align-content).

2. It may be easy to confuse justify-content, align-content, and align-items.

Remember that content refers to the flex items and empty space, and items refers to the flex items. This is the usefulness of these three attributes.

1.6 flex items

1. Syntax

The child elements of the flex box do not include out-of-flow child elements (absolute, fixed elements), but do include float elements.

Adjacent margins of flex sub-elements will not be merged.

When a float element is used as a flex child element, the float property is invalid (because it participates in flex layout, not flow layout).

2. Involving CSS properties

  • flex-basis

Specifies the size of the flex container that the flex element occupies in the main axis direction. The default is auto, that is, the size of the flex element is used as the size it occupies (the main axis is the width of the flex element with row value, and the main axis is the height of the flex element with column value). Whether there is free space is calculated based on this attribute.

Note: The size occupied by a flex element is related to flex-basis and has no direct relationship with the width and height of the element.

  • flex-grow

Specifies the elastic growth factor of each flex element, that is, the proportional share of the positive free space occupied. A value of 0 (default) means no empty space is occupied

  • flex-shrink

Specifies the elastic shrinkage factor of each flex element, that is, the proportional share of negative free space allocated. However, the element cannot shrink infinitely to 0, nor can it be smaller than the minimum size of the element (such as min-width or min-height).

  • flex

flex-grow flex-shrink flex-basis abbreviation

  • align-self

Adjust the alignment on the cross axis. This property is only valid when the cross axis is not fully occupied.

  • order

Specify the order

2. Calculating free space and flex-basis

The proportion of flex child elements on the main axis depends on these three CSS properties:

  • flex-basis
  • flex-grow
  • flex-shrink

in:
The flex-basis + flex-grow combination controls the extension
The flex-basis + flex-shrink combination controls the shrinkage, so to determine the proportion of the flex child elements on the main axis, you must first determine which combination to use.

2.1 Rules

flex-basis property specifies the initial size of the flex child element before any space allocation occurs. More precisely, flex-basis property refers to the size of the flex child element box model (box-sizing), so it is similar to the value logic of the flex child element width (height). If box-sizing=content, then flex-basis does not include padding and border areas.

2.2 Calculation of remaining free space

Free space calculation
The size of the content rectangle of the flex container in the main axis direction

Before calculating the free space of the flex container, the expected self-use space must first count the size occupied by the flex child elements. Note that this refers to the size of the margin area of ​​the flex child elements, and the margins of adjacent flex child elements will not be merged.

Remaining free space calculation = Free space calculation - Expected self-use space

Positive free space: The remaining free space with positive values ​​uses the flex-basis + flex-grow combination.

Negative free space The remaining free space with negative and positive values ​​uses the flex-basis + flex-shrink combination.

3. Learn more about flex-grow

3.1 Rules

If there is positive free space, flex-basis + flex-grow combination is used to calculate the proportion of the flex child on the main axis. If the positive free space is compared to a cake, flex-grow represents the amount of cake you want to get:

  • flex-grow: 0.2 means you want to get 20% of the cake;
  • flex-grow: 1 means you want to get 100% of the whole cake (a bit too much, not considering other brothers);
  • flex-grow: 2 means you want to get 200% of the cake (this is a blatant robbery, the attitude is very clear).

But after all, there is only one cake, and the flex container tries to meet the requirements of the felx child elements, using a simple way to divide the cake in proportion:

  • flex-grow of the flex child elements is accumulated to get the total, referred to as SUM_flex_grow;
  • If SUM_flex_grow=0, no elastic growth occurs, and the process ends;
  • The size of the flex child element growth =正自由空間尺寸* flex_grow / Max(SUM_flex_grow, 1) .

3.2 Demo1: Divide the cake according to proportion

function demo1() {
    return (
        <>
            <div className="flex">
                <div className="item" style={{flexBasis: 100, flexGrow: 1, marginRight: 10}}>One</div>
                <div className="item" style={{flexBasis: 150, flexGrow: 2, }}>Two</div>
            </div>
            <style jsx>{`
                .flex {
                    display: flex;
                    width: 600px;
                    outline: 1px dashed red;
                }
                .item {
                    padding: 10px;
                    border: 10px solid #666666;
                }
            `}</style>
        </>
    )
} 

Analysis:

Calculate remaining free space

  • flex container main axis size = 600px
  • Desired size of element one = 100px(flex-basis) + 20px(padding-left/right) + 20px(border-left/right) + 10px(margin-right) = 150px
  • Desired size of element two = 150px(flex-basis) + 20px(padding-left/right) + 20px(border-left/right) = 190px
  • Remaining free space = 600px - 150px - 190px = 260px, i.e. there is positive remaining space.

Calculate the growth size of each flex child element

  • SUM_flex_grow = 1 + 2 = 3, which is greater than 1. One cake is not enough to share, so it can only be divided according to proportion.
  • The actual growth size of element one = 260px * 1 / Max(1, 1 + 2) = 260px * 1 / (1 + 2) = 86.67px
  • The actual growth size of element two = 260px * 2 / Max(1, 1 + 2) = 260px * 2 / (1 + 2) = 173.33px

3.3 Demo2: SUM(flex-grow) < 1

function demo3() {
    return (
        <>
            <div className="flex">
                <div className="item" style={{flexBasis: 100, flexGrow: 0.2, marginRight: 10}}>One</div>
                <div className="item" style={{flexBasis: 150, flexGrow: 0.3, }}>Two</div>
            </div>
            <style jsx>{`
                .flex {
                    display: flex;
                    width: 600px;
                    outline: 1px dashed red;
                }
                .item {
                    padding: 10px;
                    border: 10px solid #666666;
                }
            `}</style>
        </>
    )
} 

Analysis:

Calculate remaining free space

  • flex container main axis size = 600px
  • Desired size of element one = 100px(flex-basis) + 20px(padding-left/right) + 20px(border-left/right) + 10px(margin-right) = 150px
  • Desired size of element two = 150px(flex-basis) + 20px(padding-left/right) + 20px(border-left/right) = 190px
  • Remaining free space = 600px - 150px - 190px = 260px, i.e. there is positive remaining space.

Calculate the growth size of each flex child element

  • SUM_flex_grow = 0.2 + 0.3 = 0.5, which is less than 1. One cake can meet everyone's needs and is directly distributed to each flex child element.
  • The actual growth size of element one = 260px * 0.2 / Max(1, 0.5) = 260px * 0.2 = 52px
  • The actual growth size of element two = 260px * 0.3 / Max(1, 0.5) = 260px * 0.3 = 78px

Notice:

If SUM(flex-grow) is less than 1, the remaining space is not fully allocated to each flex child element.

3.3 Demo3 conflicts with max-width

Note in this example:

  • elementone, two, three box-sizing=border-box
  • Element one's max-width=150px
function demo4() {
    return (
        <>
            <div className="flex">
                <div className="item" style={{flexBasis: 100, flexGrow: 1, marginRight: 10, maxWidth: 150}}>One</div>
                <div className="item" style={{flexBasis: 150, flexGrow: 2 }}>Two</div>
                <div className="item" style={{flexBasis: 100, flexGrow: 3 }}>Three</div>
            </div>
            <style jsx>{`
                .flex {
                    display: flex;
                    width: 800px;
                    outline: 1px dashed red;
                }
                .item {
                    padding: 10px;
                    border: 10px solid #666666;
                    box-sizing: border-box;
                }
            `}</style>
        </>
    )
} 

Analysis:

Calculate remaining free space

flex container main axis size = 800px

Desired size of element one = 100px(flex-basis) + 10px(margin-right) = 110px
box-sizing=border-box

Desired size of element two = 150px (flex-basis) = 150px
box-sizing=border-box

Desired size of element three = 150px (flex-basis) = 150px
box-sizing=border-box

Remaining free space = 800px - 110px - 150px - 150px = 390px, i.e. there is positive remaining space.

Calculate the growth size of each flex child element

  • SUM_flex_grow = 1 + 2 + 3 = 6, which is greater than 1. One cake is not enough to share, so it can only be divided according to proportion. .
  • The growth size of element one = 390px * 1 / Max(1, 6) = 390px * 1/6 = 65px

In this way, the size of element one is 100px + 65px = 165px, which is greater than the maximum value specified by max-width=150px , so the final size of element one is 150px. That is, element one cannot finish the allocated cake, so it returns the uneaten cake and lets other brothers get more (first raise a question: how to distribute these uneaten cakes?).

Element two and element three are reallocated to leave free space, which means returning to step 1 and recalculating.

  • Flex container main axis size = 800px - size occupied by element one (150px - 10px) = 640px
  • Remaining space = 640px - 150px - 150px = 340px
  • SUM_flex_grow = 2 + 3 = 5
  • The growth size of element two = 340px * 2 / Max(1, 5) = 340px * 2 / 5 = 136px
  • The growth size of element three = 340px * 3 / Max(1, 5) = 340px * 3 / 5 = 204px

3.4 Summary:

  • Calculating the remaining free space is always the first step;
  • Growth is an absolute value, that is, the flex child element will increase by an absolute value (this is different from flex-shrink);
  • When max- attribute conflict occurs, the cake that element one cannot finish will be put into the total cake and redistributed by the subsequent flex child elements.

4. Learn more about flex-shrink

4.1 Rules

If there is negative free space, flex-basis + flex-shrink combination is used to calculate the proportion of the flex child element on the main axis. flex-shrink value expresses the desire of each flex child to contribute:

  • flex-shrink: 0.2 means that you want to share 20% of the negative free space;
  • flex-shrink: 1 means that you want to share 100% of the negative free space (enough for one brother, other brothers do not need to share);
  • flex-shrink: 2 means that you want to distribute 200% of the negative free space (the attitude of distribution is very clear).

The flex container was moved to tears, but in order to take care of the feelings of each flex child element, a "more reasonable" allocation rule was adopted:

  • Calculate the product of the content rectangle of the flex child element on the main axis and flex-shrink, denoted as A;
  • Accumulate the product value of step 1, recorded as SUM_A;
  • Apportioned negative free space valid_negative_free_space = negative_free_space * Min(1, SUM(flex-shrink))
  • The shrinkage value of each flex item = valid_negative_free_space * A / SUM_A .

The calculation rules are more complicated than the above ones, and it is not a simple division of negative-free-space. The amount of shrinkage depends not only on flex-shrink, but also on flex-basis. This is just to make it "more reasonable", that is, under the same flex-shrink conditions, the smaller the flex-basis, the slower the flex element shrinks (just like paying taxes, the higher the income, the more you pay).

Note: If the sum of flex-shrink is less than 1, it means that part of the negative free space is distributed (that is, some sizes are not shrunk).

4.2 Demo1: “Reduce the gap between the rich and the poor”

function demo5() {
    return (
        <>
            <div className="flex">
                <div className="item" style={{flexBasis: 100, flexGrow: 1, marginRight: 10}}>One</div>
                <div className="item" style={{flexBasis: 150, flexGrow: 2, flexShrink: 2 }}>Two</div>
            </div>
            <style jsx>{`
                .flex {
                    display: flex;
                    width: 300px;
                    outline: 1px dashed red;
                }
                .item {
                    padding: 10px;
                    border: 10px solid #666666;
                }
            `}</style>
        </>
    )
} 

Analysis (too long is similar to the flex-grow process):

Calculate remaining free space

  • flex container main axis size = 300px
  • Desired size of element one = 100px(flex-basis) + 20px(padding-left/right) + 20px(border-left/right) + 10px(margin-right) = 150px
  • Desired size of element two = 150px(flex-basis) + 20px(padding-left/right) + 20px(border-left/right) = 190px
  • Remaining free space = 300px - 150px - 190px = -40px, i.e. there is negative remaining space.
  • The negative remaining space to be distributed = -40px * Min(1, 1 + 2) = -40px

Calculate the shrink size of each flex sub-element

  • SUM_A = 100px * 1 + 150px * 2 = 400px
  • The actual shrunk size of element one = 40px * 100px * 1 / 400px = 10px, that is, the final width = 100px - 10px = 90px
  • The actual shrunk size of element two = 40px * 150px * 2 / 400px = 30px, that is, the final width = 150px - 30px = 120px

4.2 Demo: SUM(flex-shrink) < 1

function demo8() {
    return (
        <>
            <div className="flex">
                <div className="item" style={{flexBasis: 100, flexShrink: 0.2, marginRight: 10}}>One</div>
                <div className="item" style={{flexBasis: 150, flexShrink: 0.3 }}>Two</div>
            </div>
            <style jsx>{`
                .flex {
                    display: flex;
                    width: 300px;
                    outline: 1px dashed red;
                }
                .item {
                    padding: 10px;
                    border: 10px solid #666666;
                }
            `}</style>
        </>
    )
} 

The flex item extends beyond the flex container.

Analysis:

Calculate remaining free space

  • flex container main axis size = 300px
  • Desired size of element one = 100px(flex-basis) + 20px(padding-left/right) + 20px(border-left/right) + 10px(margin-right) = 150px
  • Desired size of element two = 150px(flex-basis) + 20px(padding-left/right) + 20px(border-left/right) = 190px
  • Remaining free space = 300px - 150px - 190px = -40px, i.e. there is negative remaining space.
  • Effective negative remaining space = -40px * Min(1, 0.2 + 0.3) = -40px * 0.5 = -20px

Calculate the shrink size of each flex sub-element

  • SUM_A = 100px * 0.2 + 150px * 0.3 = 65px
  • The actual shrunk size of element one = 20px * 100px * 0.2 / 65px = 6.15px, that is, the final width = 100px - 6.15px = 93.85px
  • The actual shrunk size of element two = 20px * 150px * 0.3 / 65px = 13.85px, that is, the final width = 150px - 13.85px = 136.15px

4.4 Demo3: box-sizing = border-box

Note: element one, two box-sizing= border-box

function demo6() {
    return (
        <>
            <div className="flex">
                <div className="item" style={{flexBasis: 100, flexGrow: 1, marginRight: 10}}>One</div>
                <div className="item" style={{flexBasis: 150, flexGrow: 2, flexShrink: 2 }}>Two</div>
            </div>
            <style jsx>{`
                .flex {
                    display: flex;
                    width: 200px;
                    outline: 1px dashed red;
                }
                .item {
                    padding: 10px;
                    border: 10px solid #666666;
                    box-sizing: border-box;
                }
            `}</style>
        </>
    )
} 

Analysis:

Calculate remaining free space

  • flex container main axis size = 200px
  • Desired size of element one = 100px(flex-basis) + 10px(margin-right) = 110px
  • Desired size of element two = 150px (flex-basis) = 150px
  • Remaining free space = 200px - 110px - 150px = -60px, i.e. there is negative remaining space.
  • The negative remaining space to be distributed = -60px * Min(1, 1 + 2) = -60px

Calculate the shrink size of each flex sub-element

  • SUM_A = 60px * 1 + 110px * 2 = 280px
  • Note: At this time, flex-basis is not directly multiplied by flex-shrink. Essentially, the content rectangle width of the flex child element is multiplied by flex-shrink.
  • The actual contracted size of element one = 60px * 60px * 1 / 280px = 12.86px, that is, the final width = 60px - 12.86px = 47.14px (excluding padding and border)
  • The actual growth size of element two = 60px * 110px * 2 / 280px = 47.14px, that is, the final width = 110px - 47.14px = 62.86px (excluding padding and border)

4.5 Demo5 conflicts with min-width

Note in this example:

Element one has min-width=60px

function demo7() {
    return (
        <>
            <div className="flex">
                <div className="item" style={{flexBasis: 100, flexShrink: 2, marginRight: 10, minWidth: 60}}>One</div>
                <div className="item" style={{flexBasis: 150, flexShrink: 2 }}>Two</div>
                <div className="item" style={{flexBasis: 100, flexShrink: 1 }}>Three</div>
            </div>
            <style jsx>{`
                .flex {
                    display: flex;
                    width: 300px;
                    outline: 1px dashed red;
                }
                .item {
                    padding: 10px;
                    border: 10px solid #666666;
                }
            `}</style>
        </>
    )
}

Analysis:

Calculate remaining free space

  • flex container main axis size = 300px
  • Desired size of element one = 100px(flex-basis) + 20px(padding-left/right) + 20px(border-left/right) + 10px(margin-right) = 150px
  • The desired size of element two = 150px (flex-basis) + 20px (padding-left/right) + 20px (border-left/right) = 190px
  • The desired size of element three = 100px (flex-basis) + 20px (padding-left/right) + 20px (border-left/right) = 140px
  • Remaining free space = 300px - 150px - 190px - 140px = -180px, i.e. there is negative remaining space.
  • The negative remaining space to be distributed = -180px * Min(1, 1 + 2 + 2) = -180px

Calculate the shrink size of each flex sub-element

  • SUM_A = 100px * 2 + 150px * 2 + 100px * 1 = 400px
  • The actual shrunk size of element one = 180px (the absolute value of the negative remaining space) 100px 2 / 700px = 51.43px,
  • In this way, the size of element one is at most 100px - 51.43px = 48.57px, which is less than its min-width=60px, that is, the final width is 60px. That is, the tax burden assigned to element one needs to be shared by other brothers.

Element two and element three are reallocated to leave free space, which means returning to step 1 and recalculating.

  • flex container main axis size = 300px - size occupied by element one (60px + 20px + 20px + 10px) = 190px
  • Remaining space = 190px - 190px - 140px = -140px, that is, elements two and three need to be reduced by 140px in total.
  • SUM_A = 150px * 2 + 100px * 1 = 400px
  • The shrunk size of element two = 140px * 150 * 2 / 400px = 105px, that is, the final width = 150px - 105px = 45px
  • The shrunk size of element three = 140px * 100 / 400px = 35px, i.e. the final width = 100px - 35px = 65px

4.6 Summary

  • The shrinking rules are a little more complicated, and there are reasons for this, mainly to prevent small elements from shrinking too quickly and becoming negative widths.
  • When a flex element is elastically expanded or contracted, only the content rectangle is elastically expanded or contracted. Its margin, border, and padding are not elastically expanded or contracted, so they are not included in the elastic expansion calculation formula (such as the elastic contraction formula).
  • When a min-property conflict occurs, that is, when the element can no longer shrink, the remaining space is redistributed by the following flex child elements. Except when a min-attribute specifies a minimum size, every element has a minimum size.

refer to

css-tricks: A Complete Guide to Flexbox
specification
Understanding flexbox

The above is the full content of this article. I hope it will be helpful for everyone’s study. I also hope that everyone will support 123WORDPRESS.COM.

<<:  Implement a simple data response system

>>:  Web designers should optimize web pages from three aspects

Recommend

Do you know how to use the flash wmode attribute in web pages?

When doing web development, you may encounter the...

How to choose the right index in MySQL

Let’s take a look at a chestnut first EXPLAIN sel...

How to fix abnormal startup of mysql5.7.21

A colleague reported that a MySQL instance could ...

Mysql classic high-level/command line operation (quick) (recommended)

Since I need to learn how to build servers and da...

CSS and HTML and front-end technology layer diagram

The relationship between Javascript and DOM is ve...

Detailed explanation of the available environment variables in Docker Compose

Several parts of Compose deal with environment va...

Should nullable fields in MySQL be set to NULL or NOT NULL?

People who often use MySQL may encounter the foll...

What to do if you forget your mysql password

Forgot your MySQL password twice? At first I did ...

Web page experience: Web page color matching

<br />The color of a web page is one of the ...

CSS3 creates web animation to achieve bouncing ball effect

Basic preparation For this implementation, we nee...

Classification of web page color properties

Classification of color properties Any color can ...

Example of using Docker to build an ELK log system

The following installations all use the ~/ direct...

Analysis of the difference between bold <b> and <strong>

All of us webmasters know that when optimizing a ...

The most complete package.json analysis

Table of contents 1. Overview 2. Name field 3. Ve...