跳到主要内容

项目

2023年01月13日
柏拉文
越努力,越幸运

一、认识


容器 的所有子元素自动成为容器成员,称为 Flex 项目(flex item,简称项目项目默认沿主轴排列。单个项目占据的主轴空间叫做main size,占据的交叉轴空间叫做cross size

二、属性


2.1 order

作用: order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0

可选值: integer

应用场景:

  • 应用场景一、调整项目排列顺序

    场景背景: 如图所示, Ant Design 中的 X 是位于左边的, 这时交互图上 X 位于右边

    Preview

    场景解决方案: 通过 order 属性将 x 调整到最右边

    实时编辑器
    function TestOrder(props) {
        const containerStyle = {
            width: '200px',
            height: '40px',
            display: 'flex',
            alignItems: "center",
            justifyContent: "flex-start",
        }
        const itemSpanStyle = {
            order: 10,
            padding: '0 12px',
        }
        return (
            <div style={ containerStyle }>
                <span style={ itemSpanStyle }>X</span>
                <div> Basic Drawer</div>
            </div>
        );
    }
    
    结果
    Loading...

2.2 flex-grow

作用: 规定了 flex-grow 项在 flex 容器中分配剩余空间的相对比例, 即 flex-grow属性定义项目的放大比例

提示
  1. 剩余空间父容器空间width各个项目的basis/width总和

  2. 如果所有项目的flex-grow属性都为1,则它们将等分剩余空间。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。

可选值: number 类型, 负值无效。 默认为 0 (如果值为 0 , 即便有剩余空间, 也不会为其分配; 换句话说, 值为 0 , 即便有剩余空间, 也不放大)

规则:

  • 如果只有一个 flex 元素设置了 flex-grow 属性值:

    • 如果flex-grow值小于1: 则分配给它的是总剩余空间和这个比例的计算值。例如一个 0.5 的元素能分到一半的剩余空间

    • 如果flex-grow值大于1: 则独享所有剩余空间

  • 如果有多个 flex 元素设置了 flex-grow 属性值

    • 如果 flex-grow 值总和小于1: 则分配给元素的是总剩余空间和当前元素设置的 flex-grow 比例的计算值。例如一个 0.1 和一个 0.2 的元素,只能分别分到 1/102/10 的剩余空间,剩下的剩余空间并不会分配给它们。项目所占空间计算公式如下:

      1. 剩余空间为: 容器宽度 - 项目宽度总和

      2. 剩余空间每份大小为: 剩余空间 / (各个项目 flex-grow 总和) / 10

      3. 每个项目分配的空间为: 项目自身宽度 + (剩余空间每份大小 * 项目自身 flex-grow)

    • 如果 flex-grow 值总和大于1: 则所有剩余空间被利用,分配比例就是 flex-grow 属性值的比例。项目所占空间计算公式如下:

      1. 剩余空间为: 容器宽度 - 项目宽度总和

      2. 剩余空间每份大小为: 剩余空间 / (各个项目 flex-grow 总和)

      3. 每个项目分配的空间为: 项目自身宽度 + (剩余空间每份大小 * 项目自身 flex-grow)

应用场景:

  • 场景一、给项目占据指定剩余空间

    场景背景: 现有一个容器, 宽度为 300px, 有三个项目 abc , 占据容器的空间分别为: 121

    场景解决方案: 根据 flex-grow 来指定项目占据剩余空间

    实时编辑器
    function Test(props) {
      const containerStyle = {
        width: '300px',
        height: '100px',
        display: 'flex',
        backgroundColor: "red"
      }
      const itemAStyle = {
        flexGrow: 1,
        backgroundColor: "yellow"
      }
      const itemBStyle = {
        flexGrow: 2,
        backgroundColor: "blue"
      }
      const itemCStyle = {
        flexGrow: 1,
        backgroundColor: "green"
      }
      return (
         <div style={ containerStyle }>
           <div style={ itemAStyle }></div>
           <div style={ itemBStyle }></div>
           <div style={ itemCStyle }></div>
         </div>
      );
    }
    
    结果
    Loading...
  • 场景二、对于给项目占据指定剩余空间场景的思考

    场景背景: 根据给项目占据指定剩余空间场景,我们知道了根据 flex-grow 来指定项目占据剩余空间, 那么如果我们指定其中一个项目宽度了呢? 会发生什么现象?

    场景探究:

    实时编辑器
    function Test(props) {
      const containerStyle = {
        width: '300px',
        height: '100px',
        display: 'flex',
        backgroundColor: "red"
      }
      const itemAStyle = {
        flexGrow: 1,
        width: "100px",
        backgroundColor: "yellow"
      }
      const itemBStyle = {
        flexGrow: 2,
        backgroundColor: "blue"
      }
      const itemCStyle = {
        flexGrow: 1,
        backgroundColor: "green"
      }
      return (
         <div style={ containerStyle }>
           <div style={ itemAStyle }></div>
           <div style={ itemBStyle }></div>
           <div style={ itemCStyle }></div>
         </div>
      );
    }
    
    结果
    Loading...
  • 场景三、通过 flex-direction: column + flex-grow: 0.5 实现垂直居中

    场景背景: 如何实现垂直居中呢?

    场景解决: 通过 flex-direction: column + flex-grow: 0.5 实现垂直居中

    实时编辑器
    function Test(props) {
        const containerStyle = {
            width: '100px',
            height: '100px',
            display: 'flex',
            backgroundColor: "red",
            flexDirection: "column"
        }
        const itemStyle = {
            flexGrow: "0.5"
        }
        const centerItemStyle = {
            width: '80px',
            height: "80px",
            backgroundColor: "green",
        }
    
        return (
            <div style={ containerStyle }>
                <div style={ itemStyle }></div>
                <div style={ centerItemStyle }></div>
            </div>
        );
    }
    
    结果
    Loading...

2.3 flex-shrink

作用: 指定了 flex 元素的收缩规则, flex 元素仅在默认宽度之和大于容器的时候才会发生收缩, 其收缩的大小是依据 flex-shrink 的值

可选值: number 负值无效, 默认值为1(值为 1 时, 如果空间不足,该项目将缩小)

描述: 如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。负值对该属性无效。

规则:

  • 如果只有一个 flex 元素设置了 flex-shrink:

    • flex-shrink值小于1: 则收缩的尺寸不完全,会有一部分内容溢出 flex 容器

    • flex-shrink值大于等于1: 则收缩完全,正好填满 flex 容器

  • 如果多个 flex 元素设置了 flex-shrink:

    • flex-shrink值的总和小于1: 则收缩的尺寸不完全,每个元素收缩尺寸占“完全收缩的尺寸”的比例就是设置的 flex-shrink 的值

    • flex-shrink值的总和大于1: 则收缩完全,每个元素收缩尺寸的比例和 flex-shrink 值的比例一样。项目所占空间计算公式如下:

      1. 溢出空间为: 各个项目空间总和 - 容器空间

      2. 每个项目的压缩率为: (各个项目自身空间 * 各个项目 flex-shrink) /((各个项目自身空间 * 各个项目 flex-shrink) 总和)

      3. 每个项目分配的空间为: 各个项目自身空间 - 各个项目压缩率 * 溢出空间

应用场景:

  • 场景一、给项目指定收缩空间:

    项目背景: 现有一个容器, 宽度为 300px, 有三个项目 abc , 项目宽度如下, 那么收缩后, 各个项目的宽度是怎么样的呢?

    项目探究:

    实时编辑器
    function Test(props) {
        const containerStyle = {
            width: '300px',
            height: '100px',
            display: 'flex',
            backgroundColor: "red"
        }
        const itemAStyle = {
            flexShrink: 1,
            width: "200px",
            backgroundColor: "yellow"
        }
        const itemBStyle = {
            flexShrink: 2,
            width: "100px",
            backgroundColor: "blue"
        }
        const itemCStyle = {
            flexShrink: 1,
            width: "200px",
            backgroundColor: "green"
        }
        return (
            <div style={ containerStyle }>
                <div style={ itemAStyle }></div>
                <div style={ itemBStyle }></div>
                <div style={ itemCStyle }></div>
            </div>
        );
    }
    
    结果
    Loading...

2.4 flex-basis

作用: flex-basis 指定了 flex 元素在主轴方向上的初始大小。如果不使用 box-sizing 改变盒模型的话,那么这个属性就决定了 flex 元素的内容盒(content-box)的尺寸。当一个元素同时被设置了 flex-basis (除值为 auto 外) 和 width (或者在 flex-direction: column 情况下设置了height) , flex-basis 具有更高的优先级

提示
  1. flex-basis指明的是主轴方向的初始大小, 当flex-direction: column时, flex-basis代表的是height;当flex-direction:row时,flex-basis代表的是width

  2. 如果项目设置了flex-basis或者width, 那么在规划空间之前,他们会先跟父容器预约这么多的空间,然后剩下的才是归入到剩余空间, 然后父容器再把剩余空间分配给设置了 flex-grow 的容器。

可选值: 默认为 auto

  • <width>: 负值是不被允许的,

    • 0px / 0: 项目不会占据容器控件, 项目最终宽度为 0px。如果项目中有内容, 则由内容撑开。

    • 1px / 1:

    • 30%: 项目会占据容器的 30%

  • 关键词

    • auto: 默认为auto, 即由项目的width属性决定,如果项目没有width,那么由项目内容决定

    • fill:

    • max-content:

    • min-content:

    • fit-content:

  • 自动尺寸:

    • content: 基于 flex 的元素的内容自动调整大小。由于最初规范中没有包括这个值,在一些早期的浏览器实现的 flex 布局中, content 值无效可以利用设置 (widthheight) 为 auto 达到同样的效果
  • 全局数值:

    • unset:

    • inherit:

    • initial:

优先级: max-width/min-width > flex-basis(属性值不为 auto) > width > box

应用场景:

  • 场景一、探究 flex-basic: 0 时的情况

    实时编辑器
    function Test(props) {
        const containerStyle = {
            width: '300px',
            height: '100px',
            display: 'flex',
            backgroundColor: "red"
        }
        const itemAStyle = {
            flexBasis: 0,
            width: "200px",
            backgroundColor: "yellow"
        }
        return (
            <div style={ containerStyle }>
                <div style={ itemAStyle }></div>
            </div>
        );
    }
    
    结果
    Loading...

2.5 flex

作用: flex属性是flex-grow, flex-shrinkflex-basis的简写,默认值为0 1 auto。后两个属性可选

可选值:

  • 单值可选值:

    • 无单位值: 一个无单位数它会被当作flex:<number> 1 0 。即<flex-shrink>的值被假定为1,然后<flex-basis> 的值被假定为0。

      • flex: 2: 相当于 flex: 2 1 0
    • 有单位值: 一个有效的宽度(width)值: 它会被当作 <flex-basis> 的值。

    • 关键字值:

      • flex: auto : 相当于 flex: 1 1 auto , 元素会根据自身的宽度与高度来确定尺寸,但是会伸长并吸收 flex 容器中额外的自由空间,也会缩短自身来适应 flex 容器。

      • flex: none : 相当于 flex: 0 0 auto , 元素会根据自身宽高来设置尺寸。它是完全非弹性的:既不会缩短,也不会伸长来适应 flex 容器。

      • flex: initial : 相当于 flex: 0 1 auto , 元素会根据自身宽高设置尺寸。它会缩短自身以适应 flex 容器,但不会伸长并吸收 flex 容器中的额外自由空间来适应 flex 容器 。

  • 双值可选值: 第一个值必须为一个无单位数,并且它会被当作 <flex-grow> 的值。第二个值必须为以下之一:

    • 无单位值: 它会被当作 <flex-shrink> 的值
    • 有单位值: 它会被当作 <flex-basis> 的值
  • 三值可选值:

    • 第一个值必须为一个无单位数,并且它会被当作 <flex-grow> 的值
    • 第二个值必须为一个无单位数,并且它会被当作 <flex-shrink> 的值。
    • 第三个值必须为一个有效的宽度值,并且它会被当作 <flex-basis> 的值。

应用场景

  • 场景一、两栏布局

    场景背景: 实现一个左宽为200px, 右宽自适应的两栏布局

    场景解决: 通过项目 flex: 1 实现(flex: 1 === flex: 1 1 0)

    实时编辑器
    function Test(props) {
        const containerStyle = {
                width: '100%',
                height: '300px',
                backgroundColor: 'red',
                display: 'flex',
            }
            const leftStyle = {
                flex: "none", // flex: none === flex: 0 0 auto  不会缩短,也不会伸长
                width: "200px",
                backgroundColor: "yellow"
            }
            const rightStyle = {
                flex: 1,  // flex: 1 === flex: 1 1 0 即会缩短,也会伸长
                backgroundColor: "blue"
            }
    
            return (
                <div style={ containerStyle }>
                    <div style={ leftStyle }></div>
                    <div style={ rightStyle }></div>
                </div>
            );
    }
    
    结果
    Loading...
  • 场景二、三栏布局

    场景背景: 实现一个左宽为200px, 右宽自适应的两栏布局

    场景解决: 通过项目 flex: 1 实现(flex: 1 === flex: 1 1 0)

    实时编辑器
    function Test(props) {
        const containerStyle = {
                width: '100%',
                height: '300px',
                backgroundColor: 'red',
                display: 'flex',
            }
            const leftStyle = {
                flex: "none", // flex: none === flex: 0 0 auto  不会缩短,也不会伸长
                width: "200px",
                backgroundColor: "blue"
            }
            const centerStyle = {
                flex: 1, // flex: 1 === flex: 1 1 0 即会缩短,也会伸长
                backgroundColor: "yellow"
            }
            const rightStyle = {
                flex: "none", // flex: none === flex: 0 0 auto  不会缩短,也不会伸长
                width: "200px",
                backgroundColor: "blue"
            }
    
            return (
                <div style={ containerStyle }>
                    <div style={ leftStyle }></div>
                    <div style={ centerStyle }></div>
                    <div style={ rightStyle }></div>
                </div>
            );
    }
    
    结果
    Loading...
  • 场景三、两栏布局(上下)

    场景背景: 实现一个左宽为200px, 右宽自适应的两栏布局

    场景解决: 通过项目 flex: 1 实现(flex: 1 === flex: 1 1 0)

    实时编辑器
    function Test(props) {
        const containerStyle = {
                width: '100%',
                height: '600px',
                backgroundColor: 'red',
                display: 'flex',
                flexDirection: "column"
            }
            const leftStyle = {
                flex: "none", // flex: none === flex: 0 0 auto  不会缩短,也不会伸长
                height: "100px",
                backgroundColor: "yellow"
            }
            const rightStyle = {
                flex: 1,  // flex: 1 === flex: 1 1 0 即会缩短,也会伸长
                backgroundColor: "blue"
            }
    
            return (
                <div style={ containerStyle }>
                    <div style={ leftStyle }></div>
                    <div style={ rightStyle }></div>
                </div>
            );
    }
    
    结果
    Loading...
  • 场景四、三栏布局(上下)

    场景背景: 实现一个左宽为200px, 右宽自适应的两栏布局

    场景解决: 通过项目 flex: 1 实现(flex: 1 === flex: 1 1 0)

    实时编辑器
    function Test(props) {
        const containerStyle = {
                width: '100%',
                height: '800px',
                backgroundColor: 'red',
                display: 'flex',
                flexDirection: "column"
            }
            const leftStyle = {
                flex: "none", // flex: none === flex: 0 0 auto  不会缩短,也不会伸长
                height: "200px",
                backgroundColor: "blue"
            }
            const centerStyle = {
                flex: 1, // flex: 1 === flex: 1 1 0 即会缩短,也会伸长
                backgroundColor: "yellow"
            }
            const rightStyle = {
                flex: "none", // flex: none === flex: 0 0 auto  不会缩短,也不会伸长
                height: "200px",
                backgroundColor: "blue"
            }
    
            return (
                <div style={ containerStyle }>
                    <div style={ leftStyle }></div>
                    <div style={ centerStyle }></div>
                    <div style={ rightStyle }></div>
                </div>
            );
    }
    
    结果
    Loading...

2.6 align-self

作用: align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch

可选值:

  • auto

  • flex-start: 交叉轴的起点对齐

  • flex-end: 交叉轴的终点对齐

  • center: 交叉轴的中点对齐

  • baseline: 项目的第一行文字的基线对齐

  • stretch(默认值): 如果项目未设置高度或设为auto,将占满整个容器的高度。