• 19 【移动Web开发之flex布局】


    34.移动Web开发之flex布局

    34.1 flex布局体验

    34.1.1 传统布局与flex布局

    【传统布局】

    • 兼容性好

    • 布局繁琐

    • 局限性,不能在移动端很好的布局

    【flex布局】

    • 操作方便,布局极为简单,移动端应用很广泛
    • PC 端浏览器支持情况较差
    • IE11 或更低版本不支持或仅部分支持

    建议:

    1. 如果是 PC 端页面布局,我们还是建议使用传统布局
    2. 如果是移动端或者不考虑兼容性问题的 PC 端页面布局,推荐使用 flex 弹性布局

    34.1.2 初体验

    弹性盒

    flex(弹性盒、伸缩盒)

    • css中的又一种布局手段,它主要用来代替浮动来完成页面的布局

    • flex可以使元素具有弹性,让元素可以跟随页面的大小的改变而改变

    弹性容器

    要使用弹性盒,必须先将一个元素设置为弹性容器

    我们通过display 来设置弹性容器

    • display:flex 设置为块级弹性容器

    • display:inline-flex 设置为行内的弹性容器

    弹性元素

    • 弹性容器的子元素是弹性元素(弹性项)

    • 弹性元素可以同时是弹性容器

        <style>
            div {
                display: flex;
                width: 80%;
                height: 300px;
                background-color: pink;
            }
    
            div span {
                /* 弹性布局中:行内盒子的宽高可直接设置了,这也是优于百分比布局的地方之一 */
                /* 免去了浮动的设置,以及对父盒子清除浮动的麻烦 */
                width: 150px;
                height: 100px;
                background-color: black;
                margin-right: 5px;
            }
        style>
        <div>
            <span>1span>
            <span>2span>
            <span>3span>
        div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    等间距分布

            div {
                width: 80%;
                justify-content: space-around;
            }
    
    • 1
    • 2
    • 3
    • 4

    平均分为三等分

            div {
                display: flex;
                width: 80%;
                justify-content: space-around;
            }
    
            div span {
                /* 弹性布局中:行内盒子的宽高可直接设置了 */
                /* width: 150px; */
                flex: 1;
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    34.2 flex布局原理

    flex 是 flexible Box 的缩写,意为 “弹性布局”,用来为盒状模型提供最大的灵活性任何一个容器都可以指定为 flex 布局

    • 当我们为父盒子设为 flex 布局以后,子元素的 float(浮动功能)、clear(清除浮动功能)和 vertical-align(垂直居中功能)属性将失效。
    • 伸缩布局 = 弹性布局 = 伸缩盒布局 = 弹性盒布局 = flex 布局

    采用 flex 布局的元素,称为 flex 容器(flex container),简称 “容器”。它的所有子元素自动成为容器成员,称为 flex 项目(flex item),简称 “项目”。

    • 上面的体验中 div 就是 flex 父容器
    • 上面的体验中 span 就是子容器 flex 项目
    • 子容器可以横向排列也可以纵向排列

    【子容器横向排列时的图示】

    【总结 flex 布局原理】

    就是通过给父盒子添加 flex 属性,来控制子盒子的位置和排列方式。

    34.3 常见弹性容器属性

    以下由 6 个属性是对父元素设置的

    • flex-direction:设置主轴的方向
    • justify-content:设置主轴上的子元素排列方式
    • flex-wrap:设置子元素是否换行
    • flex-flow:复合属性,相当于同时设置了 flex-direction 和 flex-wrap
    • align-content:设置侧轴上的子元素的排列方式(多行)
    • align-items:设置侧轴上的子元素排列方式(单行)

    34.4 flex-direction设置主轴的方向

    flex-direction 指定容器中弹性元素的排列方式

    (1)主轴与侧轴

    在 flex 布局中,是分为主轴和侧轴两个方向,同样的叫法有:行 和 列、x轴 和 y轴

    • 默认主轴方向就是 x轴 方向,水平向右
    • 默认侧轴方向就是 y轴 方向,水平向下

    (2)属性值

    flex-direction 属性决定主轴的方向(即:项目的排列方向)

    注意:主轴和侧轴是会变化的,就看 flex-direction 设置谁为主轴,剩下的就是侧轴。而我们的子元素是跟着主轴来排列的。

    • row默认值,弹性元素在容器中水平排列(自左向右)

    • row-reverse 弹性元素在容器中反向水平排列(自右向左)

    • column 弹性元素纵向排列(自上向下)

    • column-reverse 弹性元素反向纵向排列(自下向上)

    【案例】

        <style>
            div {
                /* 给父级添加flex属性 */
                display: flex;
                width: 800px;
                height: 300px;
                background-color: pink;
                /* 默认的主轴是 x 轴,那么 y 轴就是侧轴喽 */
                /* 我们的元素是跟着主轴来排列的 */
                flex-direction: row;
                /* 简单了解翻转即可 */
                /* flex-direction: row-reverse; */
                /* 我们可以把我们的主轴设置为 y 轴 那么 x 轴就成了侧轴 */
                /* flex-direction: column; */
            }
    
            div span {
                width: 150px;
                height: 100px;
                background-color: purple;
            }
        style>
        <div>
            <span>1span>
            <span>2span>
            <span>3span>
        div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

                flex-direction: row-reverse;
    
    • 1

                flex-direction: column;
    
    • 1

    34.5 justify-content设置主轴上的子元素排列方式

    justify-content 属性定义了项目在主轴上的对齐方式

    注意:使用这个属性之前一定要确定好主轴是哪个!

    属性值说明
    flex-start元素沿着主轴起边排列,如果主轴是 x轴,则从左到右(默认值)
    flex-end元素沿着主轴终边排列
    center在主轴居中对齐(如果主轴是 x轴 则 水平居中)
    space-around空白分布到元素两侧
    space-between先两边贴边再平方剩余空间(重要)
    space-evenly空白分布到元素的单侧

    【案例】

    flex-start 元素沿着主轴起边排列

        <style>
            div {
                display: flex;
                width: 800px;
                height: 300px;
                background-color: pink;
                /* 默认的主轴是 x轴 row */
                flex-direction: row;
                /* justify-content: 是设置主轴上子元素的排列方式 */
                /* 从头部开始,如果主轴是 x轴,则从左到右(默认值) */
                justify-content: flex-start;
                /* 从尾部开始排列 */
                /* justify-content: flex-end; */
                /* 让我们子元素居中对齐 */
                /* justify-content: center; */
                /* 平分剩余空间 */
                /* justify-content: space-around; */
                /* 先两边贴边,在分配剩余的空间 */
                /* justify-content: space-between; */
            }
    
            div span {
                width: 150px;
                height: 100px;
                background-color: gray;
            }
        style>
        <div>
            <span>1span>
            <span>2span>
            <span>3span>
            <span>4span>
        div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    flex-end 元素沿着主轴终边排列

    center 元素居中排列

    image-20220812122252100

    space-around 空白分布到元素两侧

    space-between 先两边贴边再平方剩余空间

    补充

    space-evenly 空白分布到元素的单侧

    image-20220812105356829

    注意:以上例子并不能根据浏览器窗口大小自动调整子项之间的间距,因为父盒子的宽度是固定死 800px 的,假如我们把父盒子宽度设为 80%,那么就可以有效果了。

    div {width: 800px;}

    div {width: 80%;}

    div {width: 80%;}

    div span {width: 80%;}

    【以上到下为主轴的案例】

             /* 我们现在的主轴是 y轴 */
             flex-direction: column;
            /* justify-content: 是设置主轴上子元素的排列方式 */
            /* 从头部开始,则从上到下(默认值) */
            justify-content: flex-start;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    image-20220812122358520

                /* 我们现在的主轴是 y轴 */
                flex-direction: column;
                /* justify-content: 是设置主轴上子元素的排列方式 */
                /* 从下开始排列 */
                justify-content: flex-end;
    
    • 1
    • 2
    • 3
    • 4
    • 5

                /* 我们现在的主轴是 y轴 */
                flex-direction: column;
                /* justify-content: 是设置主轴上子元素的排列方式 */
                /* 让我们子元素垂直居中对齐 */
                justify-content: center;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    盒子自动垂直居中的困扰终于解决啦!!!

                /* 我们现在的主轴是 y轴 */
                flex-direction: column;
                /* justify-content: 是设置主轴上子元素的排列方式 */
                /* 平分剩余空间 */
                justify-content: space-around;
    
    • 1
    • 2
    • 3
    • 4
    • 5

                /* 我们现在的主轴是 y轴 */
                flex-direction: column;
                /* justify-content: 是设置主轴上子元素的排列方式 */
                /* 先上下两边贴边,在分配剩余的空间 */
                justify-content: space-between;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    34.6 flex-wrap设置子元素是否换行

    flex-wrap 设置弹性元素是否在弹性容器中自动换行

    属性值说明
    nowrap默认值,元素不会自动换行
    wrap元素沿着辅轴方向自动换行

    【案例】

        <style>
            div {
                display: flex;
                width: 600px;
                height: 400px;
                background-color: pink;
                /* flex布局中,默认的子元素是不换行的, 如果装不开,会缩小子元素的宽度,放到父元素里面  */
                /* flex-wrap: nowrap; */
                /* 自动换行 */
                /* flex-wrap: wrap; */
            }
    
            div span {
                width: 150px;
                height: 100px;
                background-color: gray;
                color: #fff;
                margin: 10px;
            }
        style>
    
        <div>
            <span>1span>
            <span>2span>
            <span>3span>
            <span>4span>
            <span>5span>
            <span>6span>
        div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    image-20220119004923437
                flex-wrap: wrap;
    
    • 1

    34.7 flex-flow复合属性

    flex-flow 属性是 flex-direction 和 flex-wrap 属性的复合属性

    flex-flow: row wrap;

    【案例】

        <style>
            div {
                display: flex;
                width: 600px;
                height: 300px;
                background-color: pink;
                /* flex-direction: column;
                flex-wrap: wrap; */
                /* 把设置主轴方向和是否换行(换列)简写 */
                flex-flow: column wrap;
            }
    
            div span {
                width: 150px;
                height: 100px;
                background-color: gray;
            }
        style>
        <div>
            <span>1span>
            <span>2span>
            <span>3span>
            <span>4span>
            <span>5span>
        div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    34.8 align-items设置侧轴上的子元素排列方式(单行)

    该属性是控制子项在侧轴(默认是 y轴)上的排列方式,在子项为单项(单行)的时候使用。

    属性值说明
    flex-start从上到下
    flex-end从下到上
    center挤在一起居中
    stretch拉伸(默认值)注:前提是子盒子没有指定高度,否则没有效果!

    【案例】

    flex-start 元素不会拉伸,沿着辅轴起边对齐

        <style>
            div {
                display: flex;
                width: 800px;
                height: 400px;
                background-color: pink;
                /* 默认的主轴是 x轴 row */
                flex-direction: row;
                justify-content: center;
                /* 设置侧轴:从上到下 */
                align-items: flex-start;
            }
    
            div span {
                width: 150px;
                height: 100px;
                background-color: gray;
                color: #fff;
                margin: 10px;
            }
        style>
    
        <div>
            <span>1span>
            <span>2span>
            <span>3span>
        div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    flex-end 沿着辅轴的终边对齐

    center 居中对齐

        <style>
            div {
                display: flex;
                width: 800px;
                height: 400px;
                background-color: pink;
                /* 默认的主轴是 x轴 row */
                flex-direction: row;
                justify-content: center;
                /* 设置侧轴:拉伸(默认) */
                align-items: stretch;
            }
    
            div span {
                width: 150px;
                /* 拉伸的前提是没有指定高度 */
                /* height: 100px; */
                background-color: gray;
                color: #fff;
                margin: 10px;
            }
        style>
        <div>
            <span>1span>
            <span>2span>
            <span>3span>
        div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    align-items 只能统一对侧轴上的子元素排列方式,假如有多行子元素,要分别对不同的行设置不同的排列方式,那么此种方式就无法做了。

    34.9 align-content 设置侧轴上的子元素的排列方式(多行)

    设置子项在侧轴上的排列方式并且只能用于子项出现 换行 的情况(多行),在单行下是没有效果的。

    属性值说明
    flex-start在侧轴的头部开始排列
    flex-end在侧轴的尾部开始排列
    center在侧轴中间显示
    space-around子项在侧轴平方剩余空间
    space-between子项在侧轴先分布在两头,再平分剩余空间
    stretch行拉伸以占据剩余空间(默认值)

    【案例】

        <style>
            div {
                display: flex;
                width: 800px;
                height: 400px;
                background-color: pink;
                /* 换行 */
                flex-wrap: wrap;
                /* 因为有了换行,此时我们侧轴上控制子元素的对齐方式我们用 align-content */
                align-content: flex-start;
                /* align-content: center; */
                /* align-content: space-around; */
                /* align-content: space-between; */
                /* align-content: stretch; */
            }
    
            div span {
                width: 150px;
                height: 100px;
                background-color: gray;
                color: #fff;
                margin: 10px;
            }
        style>
        <div>
            <span>1span>
            <span>2span>
            <span>3span>
            <span>4span>
            <span>5span>
            <span>6span>
            <span>7span>
            <span>8span>
        div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

                align-content: center;
    
    • 1

                align-content: space-around;
    
    • 1

                align-content: space-between;
    
    • 1

        <style>
            div {
                display: flex;
                width: 800px;
                height: 400px;
                /* 换行 */
                flex-wrap: wrap;
                /* 因为有了换行,此时我们侧轴上控制子元素的对齐方式我们用 align-content */
                align-content: stretch;
            }
    
            div span {
                width: 150px;
                height: 100px;
                margin: 10px;
            }
        style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    弹性居中

    justify-content: center;
    align-items: center;
    
    • 1
    • 2

    利用弹性盒对元素进行水平垂直双方向居中

    image-20220812111500820

    34.10 align-content和align-items区别

    • align-items 适用于单行情况下,只有上对齐、下对齐、居中和拉伸
    • align-content 适应于换行(多行)的情况下(单行情况下无效),可以设置上对齐、下对齐、居中、拉伸以及平均分配剩余空间等属性值
    • 总结就是单行找 align-items 多行找 align-content

    34.11 常见弹性元素属性

    • flex-grow 指定弹性元素的伸展系数,默认值为0
    • flex-shrink 指定弹性元素的收缩系数,默认值为1
    • flex-basis 指定的是元素在主轴上的基础长度
    • flex flex-grow、flex-shrink、flex-basis 三个属性的合集
    • order 决定弹性元素的排列顺序(前后顺序)
    • align-self 控制子项自己在侧轴的排列方式

    34.12 伸展系数

    flex-grow 指定弹性元素的伸展系数,默认值为0

    • 当父元素有多余空间的时,子元素如何伸展

    • 父元素的剩余空间,会按照比例进行分配

    34.12.1 flex-grow基础

    flex-grow 属性定义项目的扩大系数,用于分配容器的剩余空间,那么什么是剩余空间呢?

    其实非常简单,剩余空间计算方式就是:

    容器大小 - 所有项目的总大小
    
    • 1

    参考如下示例:

    image-20220812112444197

    其中:

    1. 每个项目的宽度为50px,3个为150px。
    2. 剩余空间为 450px - 150px = 300px。
    
    • 1
    • 2
    1. 默认为 0 ,即如果容器存在剩余空间,也不放大。
    2. flex-grow只能为>=0的数字,项目根据设置的系数进行放大。
    
    • 1
    • 2

    那么问题就来了:

    项目是如何根据设置的系数分配剩余空间呢?
    
    • 1

    这边涉及到两个关键公式:

    1)计算将多少剩余空间拿来分配。

    公式:剩余空间 * ( 所有项目的flex-grow之和 >= 1 ? 1 : 所有项目的flex-grow之和 )
    • 1

    这边用了一个三元表达式,理解不难,公式的意思就是说:

    如果 所有项目的flex-grow之和 大于等于1,那么就是所有的剩余空间都拿来分配,否则乘以系数即为要分配的剩余空间。

    2)计算每个项目分配到多少剩余空间。

    公式:要分配的剩余空间 * ( 单个项目flex-grow / 所有项目的flex-grow之和 )
    
    • 1

    简单的说,就是按照 flex-grow 占比进行分配。

    下面我们结合例子进行说明,对这边的计算公式进行理解。

    示例1,设置项目的flex-grow为1:

    有一个div(容器,450px),容器内包含3个div(项目,各50px)。

    .item {
    	/* 	flex-basis属性定义了项目占据主轴空间(main size)大小。 */
    	/* 	这边设置为50px */
    	flex-basis: 50px;
    	/* flex-grow 属性定义项目的扩大系数 */
    	/* 这边设置为1 */
    	flex-grow: 1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行效果:

    image-20220812112908755

    我们观察到3个项目的宽度都变成了150px,可以看到项目被进行了扩大。

    现在套公式看下情况:

    1)计算总共要分配多少剩余空间。

    要分配的剩余空间
     = 剩余空间 * ( 所有项目的flex-grow之和 >= 1 ? 1 : 所有项目的flex-grow之和 ) 
     = 300px * (3 >= 1 ? 1 : 3)
     = 300px * 1
     = 300px
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2)计算每个项目分配到多少剩余空间。

    因为每个项目flex-grow都为1,所以每个项目分配的剩余空间都一样。

    每个项目分配的剩余空间
     = 要分配的剩余空间 * ( 单个项目flex-grow / 所有项目的flex-grow之和 )
     = 300px * ( 1 / 3)
     = 100px
    
    • 1
    • 2
    • 3
    • 4

    每个项目多分配100px,加上自身设置的flex-basis,最终每个项目宽度就为150px了。

    示例2,设置项目1的flex-grow为1,项目2的flex-grow为2,项目3的flex-grow为3:

    我们直接套公式计算:

    1)计算总共要分配多少剩余空间。

    要分配的剩余空间
     = 剩余空间 * ( 所有项目的flex-grow之和 >= 1 ? 1 : 所有项目的flex-grow之和 ) 
     = 300px * (6 >= 1 ? 1 : 6)
     = 300px * 1
     = 300px
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2)计算每个项目分配到多少剩余空间。

    因为每个项目flex-grow都不一样,所以每个项目分配的剩余空间要分开计算。

    项目1分配的剩余空间
     = 要分配的剩余空间 * ( 项目1flex-grow / 所有项目的flex-grow之和 )
     = 300px * ( 1 / 6)
     = 50px
    
    项目2分配的剩余空间
     = 要分配的剩余空间 * ( 项目2flex-grow / 所有项目的flex-grow之和 )
     = 300px * ( 2 / 6)
     = 100px
    
    项目3分配的剩余空间
     = 要分配的剩余空间 * ( 项目3flex-grow / 所有项目的flex-grow之和 )
     = 300px * ( 3 / 6)
     = 150px 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    所以最终:项目1宽为100px、项目2宽为150px、项目3宽为200px。

    写上代码看看效果:

    .item {
    	/* 	flex-basis属性定义了项目占据主轴空间(main size)大小。 */
    	/* 	这边设置为50px */
    	flex-basis: 50px;
    }
    .item1 {
    	flex-grow: 1;
    }
    
    .item2 {
    	flex-grow: 2;
    }
    
    .item3 {
    	flex-grow: 3;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    运行效果:

    观察运行效果,符合预期。

    示例3:设置项目1的 flex-grow 为 0.1,项目2的 flex-grow 为0.2,项目3的 flex-grow 为 0.3:

    这个示例和上例差不多,只是数字变成了小数,并且总和不大于1。

    先套公式来计算一下:

    1)计算总共要分配多少剩余空间。

    要分配的剩余空间
     = 剩余空间 * ( 所有项目的flex-grow之和 >= 1 ? 1 : 所有项目的flex-grow之和 ) 
     = 300px * (0.6 >= 1 ? 1 : 0.6)
     = 300px * 0.6
     = 180px
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2)计算每个项目分配到多少剩余空间。因为每个项目flex-grow都不一样,所以每个项目分配的剩余空间要分开计算。

    项目1分配的剩余空间
     = 要分配的剩余空间 * ( 项目1flex-grow / 所有项目的flex-grow之和 )
     = 180px * ( 0.1 / 0.6)
     = 30px
    
    项目2分配的剩余空间
     = 要分配的剩余空间 * ( 项目2flex-grow / 所有项目的flex-grow之和 )
     = 180px * ( 0.2 / 0.6)
     = 60px
    
    项目3分配的剩余空间
     = 要分配的剩余空间 * ( 项目3flex-grow / 所有项目的flex-grow之和 )
     = 180px * ( 0.3 / 0.6)
     = 90px
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    所以最终:项目1宽为80px、项目2宽为110px、项目3宽为140px。

    样式代码如下:

    .item {
    	/* flex-basis属性定义了项目占据主轴空间(main size)大小。 */
    	flex-basis: 50px;
    }
    
    .item1 {
    	/* flex-grow属性定义项目的放大比例 */
    	flex-grow: 0.1;
    }
    
    .item2 {
    	/* flex-grow属性定义项目的放大比例 */
    	flex-grow: 0.2;
    }
    
    .item3 {
    	/* flex-grow属性定义项目的放大比例 */
    	flex-grow: 0.3;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    运行效果如下:

    image-20220812113709146

    符合计算预期。

    34.12.2 flow-grow应用

    flow-grow属性在项目中运用很多,比如页面布局、导航条、分页等。

    实例1:使用 flex 弹性布局实现如下效果:

    image-20220812113818509

    这个其实就是腾讯首页的导航条了,我们模拟实现一下,步骤分为4步:

    1)首先先写html标签,标签很简单一个 nav 包含若干 a 标签:

    <nav class="container">
    	<a class="item" href="#">新闻a>
    	<a class="item" href="#">视频a>
    	<a class="item" href="#">图片a>
    	<a class="item" href="#">军事a>
    	<a class="item" href="#">体育a>
    	<a class="item" href="#">NBAa>
    	<a class="item" href="#">娱乐a>
    	<a class="item" href="#">财经a>
    	<a class="item" href="#">科技a>
    nav>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2)设置基本样式,背景、颜色、边框圆角等:

    .container {
    	height: 44px;
    	background-color: #1479d7;
    	border-radius: 3px;
    }
    
    .item {
    	color: white;
    	text-align: center;
    	text-decoration: none;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    运行效果:

    image-20220812114128188

    3)设置容器为 flex 布局,项目 flex-grow 为1 平分剩余空间:

    .container {
    	/* 设置子元素的布局为flex布局 */
    	display: flex;
    }
    
    .item {
    	/* 设置项目放大系数 */
    	flex-grow: 1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    运行效果:

    image-20220812114149809

    4)再来一个上下居中即可,flex 弹性布局将容器属性 align-items 设置为 center 即可:

    .container {
    	/* 设置辅轴上项目居中排列 */
    	align-items: center;
    }
    
    • 1
    • 2
    • 3
    • 4

    运行效果:

    image-20220812114302213

    至此这个例子就完成了。

    和之前使用float相比,我们尝试改变容器大小,会发现项目也跟着变化,这个就是弹性的意思了。如下图所示:

    3.12.3 总结

    1. 容器内未被占用的空间称为剩余空间。
    2. flex-grow用于设置项目的放大系数。
    3. 项目放大尺寸计算包含两个公式:

    1)计算将多少剩余空间拿来分配。

    公式:剩余空间 * ( 所有项目的flex-grow之和 >= 1 ? 1 : 所有项目的flex-grow之和 )
    • 1

    2)计算每个项目分配到多少剩余空间。

    公式:要分配的剩余空间 * ( 单个项目flex-grow / 所有项目的flex-grow之和 )
    
    • 1
    1. flex-grow不是设置具体的尺寸,在弹性布局中应用广泛。

    34.13 缩减系数

    flex-shrink 指定弹性元素的收缩系数,默认值为1

    • 当父元素中的空间不足以容纳所有的子元素时,如何对子元素进行收缩

    • 缩减系数的计算方式比较复杂,缩减多少是根据 缩减系数元素大小 来计算

    简单的说 flex-grow 用于放大,那么 flex-shrink 就是用于缩小了,两个属性就是反过来,计算方式都类似。放大是因为有剩余空间,缩小就是因为项目的宽度超过容器了,有一个超出空间,所以就要进行缩小。

    34.13.1 flex-shrink基础

    超出空间计算方式:

    所有项目的总大小 - 容器大小
    
    • 1

    参考如下示例:

    image-20220812114904538

    容器宽度为450px,三个项目各为200px,总宽超过容器了,就自动缩小了。不难计算,这里超出的空间就是 200px * 3 - 450px = 150px

    其中:

    1. 默认值为1,表示所有项目等比例缩小。
    2. 如果为0,那么表示不缩小。
    
    • 1
    • 2

    缩小的尺寸计算方式和flew-grow类似,涉及到两个公式:

    1)计算超出空间中多少用来压缩。

    公式:超出空间 * ( 所有项目的flex-shrink之和 >= 1 ? 1 : 所有项目的flex-shrink之和 )
    • 1

    如果没有超出空间,那么就用压缩了;如果超出空间为150px,所有项目的flex-shrink之和为0.6,那么90px用来压缩。

    2)计算每个项目缩小多少空间。

    公式:要压缩的空间 * ( 单个项目flex-shrink / 所有项目的flex-shrink之和 )
    
    • 1

    简单的说,就是按照 flex-shrink 占比进行缩小。

    下面我们结合例子进行说明,对这边的计算公式进行理解。

    示例1,设置项目的 flex-shrink 为0:

    接上一篇例子,有一个div(容器,450px),容器内包含3个div(项目,flex-basis 为200px)。

    .item {
    	/* flex-basis属性定义了项目占据主轴空间(main size)大小。 */
    	flex-basis: 200px;
    	/* flex-shrink 属性定义项目的缩小系数 */
    	flex-shrink: 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    flex-shrink 为0表示不压缩项目。

    可以看到item3项目那边超出了容器一截。

    示例2,接上例,设置项目1、2、3的 flex-shrink 分别为0、1、2:

    套公式计算:

    1)计算超出空间中多少用来压缩。

    要压缩的空间
     = 总超出空间 * ( 所有项目的flex-shrink之和 >= 1 ? 1 : 所有项目的flex-shrink之和 ) 。
     = 150px * ( 3 >= 1 ? 1 : 3)
     = 150px
    
    • 1
    • 2
    • 3
    • 4

    2)计算每个项目缩小多少空间。

    项目1压缩的空间
     = 150px * ( 0 / 3 )
     = 0
    
    项目2压缩的空间
     = 150px * ( 1 / 3 )
     = 50px
    
    项目3压缩的空间
     = 150px * ( 2 / 3 )
     = 100px
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    所以最终:项目1宽为200px、项目2宽为150px、项目3宽为100px。

    写上代码看看效果:

    .item {
    	/* flex-basis属性定义了项目占据主轴空间(main size)大小。 */
    	flex-basis: 200px;
    }
    		
    .item1 {
    	flex-shrink: 0;
    }
    
    .item2 {
    	flex-shrink: 1;
    }
    
    .item3 {
    	flex-shrink: 2;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    运行效果:

    观察运行效果,符合预期。

    示例3:设置项目1、2、3的 flex-shrink 分别为 0.1、0.2、0.3:

    这个示例和上例差不多,只是数字变成了小数,并且总和不大于1。

    先套公式来计算一下:

    1)计算超出空间中多少用来压缩

    要压缩的空间
     = 总超出空间 * ( 所有项目的flex-shrink之和 >= 1 ? 1 : 所有项目的flex-shrink之和 ) 。
     = 150px * ( 0.6 >= 1 ? 1 : 0.6)
     = 90px
    
    • 1
    • 2
    • 3
    • 4

    2)计算每个项目缩小多少空间。

    项目1压缩的空间
     = 90px * ( 0.1 / 0.6 )
     = 15px
    
    项目2压缩的空间
     = 90px * ( 0.2 / 0.6 )
     = 30px
    
    项目3压缩的空间
     = 90px * ( 0.3 / 0.6 )
     = 45px
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    所以最终:项目1宽为185x、项目2宽为170px、项目3宽为155px。

    样式代码如下:

    .item {
    	/* flex-basis属性定义了项目占据主轴空间(main size)大小。 */
    	flex-basis: 200px;
    }
    
    .item1 {
    	flex-shrink: .1;
    }
    
    .item2 {
    	flex-shrink: .2;
    }
    
    .item3 {
    	flex-shrink: .3;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    运行效果如下:

    符合计算预期。

    34.13.2 总结

    1. 项目的总大小超出容器部分成为超出空间。
    2. flex-shrink用于设置项目的缩小系数。
    3. 项目缩小尺寸计算包含两个公式:

    1)计算超出空间中多少用来压缩。

    公式:总超出空间 * ( 所有项目的flex-shrink之和 >= 1 ? 1 : 所有项目的flex-shrink之和 )
    • 1

    2)计算每个项目缩小多少空间。

    公式:要压缩的空间 * ( 单个项目flex-shrink / 所有项目的flex-shrink之和 )
    
    • 1

    34.14 基础长度

    34.14.1 flex-basis基础

    flex-basis 指定的是元素在主轴上的基础长度

    • 如果主轴是横向的,则该值指定的就是元素的宽度

    • 如果主轴是纵向的,则该值指定的就是元素的高度

    • 默认值是auto,表示参考元素自身的高度或宽度

    • 如果传递了一个具体的数值,则以该值为准

    在这里可以先理解成 宽(width)属性,用法和 width 的一致,只是优先级比 width 更高。

    示例1 有一个div(容器),容器内包含3个div(项目),容器设置为 flex 弹性布局。

    image-20220812120114551

    容器内项目的宽度是根据内容自适应的,这个也就是 flex-basis 默认值为 auto 的含义了。

    下面设置项目的宽度为120px:

    .item {
    	/* flex-basis属性定义了项目占据主轴空间(main size)大小。 */
    	flex-basis: 120px;
    }
    
    • 1
    • 2
    • 3
    • 4

    运行效果:

    image-20220812120209155

    可以看到3个项目的宽度都为120px了,这个就是 flex-basis 的含义了。

    思考:

    如果设置 width: 100px,那么项目实际为多宽呢?
    
    • 1

    解答:因为 flex-basis 属性的优先级比 width 高,所以项目的宽度还是120px。

    思考:

    设置宽度为什么不直接用 width 属性?还要再多一个 flex-basis 属性,不是多此一举吗?
    
    • 1

    解答(难点):

    flex-basis 这边并没有说是定义项目的宽度,而是说:占据主轴空间的大小。
    因为设置容器属性 flex-direction 为 column或者column-reverse 的时候主轴会变成纵向的(可以想象成数学坐标轴的Y轴)。
    在这种情况下,flex-basis 就是设置高,可以理解成 height 属性。
    从这个意义上来讲,flex-basis 不全等于 width。
    
    • 1
    • 2
    • 3
    • 4

    3.14.2 总结

    1. flex-basis 属性设置在项目上的。
    2. flex-basis 是设置项目 占据主轴空间的大小、不全等于width。
    3. flex-basis 优先级比 width 更高。

    34.15 flex属性

    前面三节讲了 flex-grow、flex-shrink、flex-basis 三个项目属性。

    1. flex-grow 用于设置项目的放大系数。
    2. flex-shrink 用于设置项目的缩小系数。
    3. flex-basis 用于设置项目在主轴上的空间。

    那么项目属性 flex 就很简单了,他其实是3个属性的集中而已,语法格式如下:

    .item {
    	flex: flex-grow flex-shrink flex-basis | auto | none;
    }
    
    • 1
    • 2
    • 3

    其中:

    1. 这个属性可以独立设置 flex-grow flex-shrink flex-basis 的值,如:1 0 120px。
    2. auto 表示:1 1 auto,即等比例扩大或者压缩。
    3. none 表示:0 0 auto,即不扩大,也不压缩。
    
    • 1
    • 2
    • 3

    initialflex: 0 1 auto 默认值

    实务中经常会看到如下样式代码:

    .item {
    	flex: 1;
    }
    
    • 1
    • 2
    • 3

    这个其实就是表示 flex-grow 设置为1,各项目等比例放大。

    经常用作自适应布局,内容区会自动放大或缩小占满剩余空间。在chrome浏览器上也可以将flex: 1;

    image-20220812121004252

    flex: 2;

    image-20220812121016075

    下面有几个flex布局的常用场景:
    1、一个元素宽度(或高度)固定,另一个元素宽度(或高度)自适应。

    .parent {
    	display: flex;
    }
    // 高度/宽度固定
    .son1 {
    	width: 200px; //或者 height: 200px;
    	flex: none; // 加不加都可 相当于flex: 0 0 auto;
    }
    // 高度/宽度自适应
    .son2 {
    	flex: 1;  // flex: 1 1 0%;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2、子元素都设置flex: 1; 子元素盒子会平分并占满父盒子;

    我是一个div
    我是一个很多字div
    我是一个更多字而且第三个div
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    image-20220812121143203

    3、那么如果设置 flex: 1 1 auto;呢? 子元素盒子会根据自己的内容来适配并一起占满整个空间;

    我是一个div
    我是一个很多字div
    我是一个更多字而且第三个div
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    image-20220812121218240

    34.16 order属性定义项目的排列顺序

    order 用于是设置项目的排序顺序,从小到大排列。

    项目的排序默认会按照html的结构进行排序,如果需要定义排序顺序,可以通过order属性定义项目的排序顺序,语法格式如下:

    .item {
    	/* 整数,默认值为 0,可以为负数 */
    	order: ; 
    }
    
    • 1
    • 2
    • 3
    • 4

    其中:

    order 为整数,可以为负数。
    order 默认值为 0。
    项目按照 order 值从小到大排列。
    
    • 1
    • 2
    • 3

    如果之前有学习过sql,那么对 order 就很熟悉了。因为sql中排序的关键词就是 order by。

    示例1:有一个div(容器,450px),容器内包含5个div(项目,flex-grow 为1)。

    1)和前面章节相比多两个项目,方便看出排序效果。

    未设置排序前的效果:

    image-20220812121521482

    2)默认所有的项目 order 值都为0,设置项目1为99,项目3为-1,项目4为-2:

    因为项目是按照order从小到大排列,那么正常显示的顺序应该是:

    项目4、项目3、项目2、项目5、项目1。
    
    • 1

    写上代码:

    .item1 {
    	order: 99;
    }
    
    .item3 {
    	order: -1;
    }
    
    .item4 {
    	order: -2;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    运行效果:

    image-20220812121638855

    34.17 align-self属性

    项目属性 align-self,和 align-items 类似。align-items设置在容器上,作用所有的项目。align-self 设置在项目上,作用单个项目

    align-self 属性用来设置项目在辅轴方向上的对齐方式,设置在项目上,作用单个项目。
    而 align-items 设置在容器上,作用所有的项目。

    语法格式如下:

    .item {
    	align-self: auto(默认值) | flex-start | flex-end | center | baseline | stretch;
    }
    
    • 1
    • 2
    • 3

    其中:

    1. auto 表示继承容器的 align-items 属性。(默认值)
    2. flex-start 沿着辅轴方向 起点 对齐(默认值)。
    3. flex-end 沿着辅轴方向 结尾 对齐。
    4. center 沿着辅轴方向 居中 对齐。
    5. baseline 沿着辅轴方向,按照项目内的文字对齐。
    6. stretch 沿着辅轴方向自动进行拉升到最大。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    示例1,有一个div(容器,450px),容器内包含3个div(项目,flex-basis 为50px),设置 align-items 为 flex-start,项目1的align-self设置为 flex-end:

    .container {
    	/* 设置子元素的布局为flex布局 */
    	display: flex;
    	/* 设置项目交叉轴方向上的对齐方式 */
    	/* 作用于所有项目 */
    	align-items: flex-start;
    }
    
    .item1 {
    	/* 设置单个项目交叉轴方向上的对齐方式 */
    	/* 作用于单个项目 */
    	align-self: flex-end;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    运行效果:

    image-20220812122009637

    本节总结

    1. align-self 和 align-items 类似,默认值为auto,表示继承 align-items 的属性。
    2. align-self 设置在项目上,作用单个项目。align-items设置在容器上,作用所有的项目。
  • 相关阅读:
    Windows 远程控制 Mac 电脑怎么操作
    代码随想录算法训练营第day14|二叉树理论基础、二叉树递归遍历、二叉树迭代遍历
    如何从字符串中提取相关内容
    Visual Studio Community 2015中文版安装记录
    怎样合并PDF文件更快速?PDF合并工具有什么?
    HDU-3549Flow Problem 最大流模板题
    C ++ 4
    ps命令实用例子
    vue3使用animate,wow(wow不能用于商业化)
    SSM学习——springboot整合ssm(15)
  • 原文地址:https://blog.csdn.net/DSelegent/article/details/126301627