css实例学习:深入理解 flex 属性如何控制布局效果

2022年7月8日16:50:54网页制作评论267 views字数 4157阅读模式

css实例学习:深入理解 flex 属性如何控制布局效果

flex 布局开发中使用得频率也很高,但是大部份时间只是轻度使用,例如设置水平布局等。实际上 flex 布局中也有许多小细节。本文从实例得角度来分析 flex 布局中得常见属性如何控制布局效果。

flex

flex 参数用于控制 flex 项目在主轴上的宽度分配,主要由以下几个参数决定:

  • flex-grow: 子元素未占满空间时,如何进行增长
  • flex-shink: 子元素超出宽度时,子元素如何收缩
  • flex-basis:子元素的初始宽度

flex-grow

当容器设置了 flex 布局后,子元素会在主轴排列为一行。当子元素的总宽度不足容器时可以设置 flex-grow: 非零值,子元素会增加宽度以填满容器。例如:

<html>
    <style>
        .container{
            display: flex;
            width: 600px;
            flex-wrap: no-wrap;
            border: 5px dashed slategrey;
        }
        .items{
            border-radius: 5px;
            text-align: center;
            font-size: 2em;
            color: white;
            flex-grow: 0;
        }
        .items:nth-child(1){
            background-color: darkgray;
            width: 100px;
        }
        .items:nth-child(2){
            background-color: aquamarine;
            width: 100px;
        }
        .items:nth-child(3){
            background-color: cadetblue;
            width: 100px;
        }
    </style>
    <body>
        <div class="container">
            <div class="items">1</div>
            <div class="items">2</div>
            <div class="items">3</div>
        </div>
    </body>
</html>

设置容器的宽度为 600px,每个子元素的宽度为 100px,并且设置 flex-grow: 0,此时子元素不会进行任何增长,效果为:

css实例学习:深入理解 flex 属性如何控制布局效果

当我们对每个子元素设置 flex-grow: 1 时,子元素会伸长以填满子元素:

css实例学习:深入理解 flex 属性如何控制布局效果

当然,对于不同的子元素可以设置不同的数值,此时每个子元素的伸长值会按照 flex-grow 进行分配。例如对于三个子元素分别设置 1 2 1。则效果为:

css实例学习:深入理解 flex 属性如何控制布局效果

三个子元素的宽度分别为 175 250 175,计算的逻辑为:

剩余宽度 = 600 - 100 * 3 = 600 - 300 = 300

第1, 3个子元素增长宽度 = 1 / (1 + 2 + 1) * 300 = 1/4 * 300 = 75
第 2 个子元素增长宽度 = 2 / (1 + 2 + 1) * 300 = 1/2 * 300 = 150

因此最终宽度为:
100 + 75 = 175
100 + 150 = 250
100 + 75 = 175

flex-shink

当子元素宽度不足时可以伸长,同样,当子元素宽度超出容器时也可以收缩,由 flex-shink 控制。将父元素宽度改为 400px,每个子元素宽度为 200px。子元素总宽度超过父元素, 设置 flex-shink: 0 观察不收缩的情况:

<html>
    <style>
        .container{
            display: flex;
            width: 400px;
            flex-wrap: no-wrap;
            border: 5px dashed slategrey;
        }
        .items{
            border-radius: 5px;
            text-align: center;
            font-size: 2em;
            color: white;
            flex-shrink: 0;
        }
        .items:nth-child(1){
            background-color: darkgray;
            width: 200px;
        }
        .items:nth-child(2){
            background-color: aquamarine;
            width: 200px;
        }
        .items:nth-child(3){
            background-color: cadetblue;
            width: 200px;
        }
    </style>
    <body>
        <div class="container">
            <div class="items">1</div>
            <div class="items">2</div>
            <div class="items">3</div>
        </div>
    </body>
</html>

css实例学习:深入理解 flex 属性如何控制布局效果 可以看出第 3 个子元素超出父容器,此时对每个子元素设置 flex-shink: 1:

css实例学习:深入理解 flex 属性如何控制布局效果

可以看出每个子元素都进行了收缩以适应父组件的宽度。当然 flex-shink 也可以针对不同的子元素设置不同的值,此时按比例进行收缩。例如设置为 1 2 1:

css实例学习:深入理解 flex 属性如何控制布局效果

计算方法与 flex-grow 类似:

超出 = 400 - 200 * 3 = -200

第1, 3个子元素收缩(负增长)宽度 = 1 / (1 + 2 + 1) * 300 = 1/4 * -200 = -50
第 2 个子元素收缩(负增长)宽度 = 2 / (1 + 2 + 1) * 300 = 1/2 * -200 = -100

因此最终宽度为:
200 - 50 = 150
200 - 200 = 100
200 - 50 = 150

flex-basis

无论是 grow 还是 shrink 都是按容器的宽度和子元素的初始宽度。实际上初始宽度就由flex-basis决定。在上面的例子中,我们设置了 width,实际上最终起作用的还是 flex-basis。flex 常用值为:

  • auto: 如果子元素设置了 width,则为 width。否则为子元素的 max-content
  • 宽度值: 指定宽度值,会覆盖 width

可以看出如果子元素既没有指定 width,也没有指定 flex-basis,则子元素初始宽度为 max-length。何为 max-length 呢,看下面这个例子:

<html>
    <body>
        <div style="width: 100px; border: 2px dashed;">
            <div style="width: max-content; border: 1px solid;">helo world 123 123 123</div>
            <div style="border: 1px solid;">helo world 123 123 123</div>
        </div>
    </body>
</html>

css实例学习:深入理解 flex 属性如何控制布局效果

可以看出,如果一个子元素未指定宽度,其不会超过父元素的宽度。但是指定了width: max-content 之后子元素会按最长宽度计算,直接超出父容器。

我们仅保留在第一个子元素, 并设置 flex-shink 为 0 表示不进行任何收缩,效果为:

css实例学习:深入理解 flex 属性如何控制布局效果

可以看出确实表现为 max-content 的宽度。

flex-basis = 0

flex-basis 设置为 0 时等于将子元素的宽度设置为0,此时增长与收缩都为等比例。例如,当我们固定子元素宽度时并进行伸长或者收缩时,子元素最终的宽度并不是完全以 flex-grow 为等比例,因为计算时会考虑 flex-basis。当子元素宽度不固定,但是我们又希望其宽度严格按照 flex-grow 进行宽度划分则可以设置 flex-basis:0

例如设置三个不定宽度的子元素,设置 flex-basis: auto,三个子元素设置 flex-grow: 1,效果为:

css实例学习:深入理解 flex 属性如何控制布局效果

明显每个子元素宽度不同。但是如果此时我们希望三个元素宽度严格按照 1:1:1 分别,就可以设置 flex-grow:0,效果为:

css实例学习:深入理解 flex 属性如何控制布局效果

flex-wrap

很多时候都会说 flex 是一维的布局,实际上 flex 也可以处理一些简单的二位布局。当设置 flex-wrap: wrap 时,如果子元素的宽度超过父容器,那么剩余的子元素就会换行显示。同时,设置了 flex-wrap: wrap 也会对 flex-shrink 产生影响,表现为:

  1. 如果多个子元素宽度之和超过父容器,但不存在任何一个元素宽度超过父容器。此时 flex-shrink 设置不起作用。因为超出父容器宽度的元素会换行。
  2. 如果某个子元素的宽度超过父容器,那么如果该元素设置了 flex-shrink: 非零值,则会收缩以适应父容器,否则会直接溢出父容器。

例如设置父元素宽度为 500px,三个子元素为 200px 并分别设置 flex-wrap:0则显示效果为:

css实例学习:深入理解 flex 属性如何控制布局效果

可以看出由于第三个元素超出了父容器的宽度,因此被换行显示,此时这几个元素并没有收缩以适应父容器。

此时 flex-grow 仍然可以起作用。其逻辑为初始宽度可以位于同一行的元素会拉伸以适应父容器宽度。对每个子元素设置 flex-grow: 1 效果为:

css实例学习:深入理解 flex 属性如何控制布局效果

利用这个特性,我们可以写出一个九宫格布局:

<html>
    <style>
        .container{
            display: flex;
            width: 9rem;
            border: 5px dashed slategrey;
            flex-wrap: wrap;
        }
        .items{
            border-radius: 5px;
            text-align: center;
            font-size: 2em;
            color: white;
            flex: 0 0 3rem;
        }
        .items:nth-child(2n + 1){
            background-color: darkgray;
        }
        .items:nth-child(2n){
            background-color: aquamarine;
        }
    </style>
    <body>
        <div class="container">
            <div class="items">1</div>
            <div class="items">2</div>
            <div class="items">3</div>
            <div class="items">4</div>
            <div class="items">5</div>
            <div class="items">6</div>
            <div class="items">7</div>
            <div class="items">8</div>
            <div class="items">9</div>
        </div>
        
    </body>
</html>

css实例学习:深入理解 flex 属性如何控制布局效果

总结

  1. flex-grow: 当子元素的初始长度之和小于父容器时,如何伸长以适应父容器
  2. flex-shrink: 当子元素的初始长度之后大于父容器时,如何收缩以适应父容器
  3. flex-basis: 控制子元素的初始长度。
    1. auto: 如果子元素固定宽度则为该宽度。否则为 max-content
    2. 固定值,相当于设置 widht 为该值
    3. 设置该值会覆盖子元素 width
  4. flex-wrap: 当子元素的初始长度之后大于父容器时是否不收缩子元素而是直接换行

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/zhizuo/24839.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定