简述flex布局

1,534 阅读11分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

flex布局

这个帖子分享一下移动端多个布局之一的flex布局,初学flex布局的时候,看过菜鸟教程、W3C的文章,但是呢并没有很容易就搞懂,是我太菜了,当时甚至不知道什么他们的文章里提到的主轴是什么......😂😂

弹性盒基础

弹性盒是一种简单而强大的布局方式,我们通过弹性盒指明空间的分布方式、内容的对齐方式盒元素的视觉顺序,把不同的组件放置在页面中。内容可以轻易横向或纵向排布,还不可以沿一个轴布局,或者折断成多行。这只是几个例子,可以实现的布局还有很多很多。使用弹性盒,内容的呈现顺序不再受源码顺序的限制。然而,这只是视觉上的调整,弹性盒相关的属性不会改变屏幕阅读器对内容的读取顺序。———— CSS权威指南
弹性盒模型布局最突出的一个特点可能是能让元素对不同的屏幕尺寸和不同的显示设备做好适应准备。这种布局通常在响应式网站中表现极好,因为内容能根据可用空间的大小增减尺寸。

如何激活弹性盒

弹性盒依赖父子关系。在元素上声明display:flexdisplay: inline-flex就能激活弹性布局,这个元素也随之成为弹性容器(flex container),负责在所占的空间内布置子元素,控制子元素的布局。而弹性容器的子元素称为弹性元素(flex item)
我个人比较喜欢叫这种父元素为容器,子元素为项目,这里我就以书上的叫法为准(叫法而已,无所谓的)

    <div class="one">
        <span>one-1</span>
        <span>one-2</span>
        <span>one-3</span>
    </div>
    <div class="two">
        <span>two-1</span>
        <span>two-2</span>
        <span>two-3</span>
    </div>
        .one {
            display: flex;
            margin-bottom: 20px;
        }
        .two {
            display: inline-flex;
        }
        div {
            border: 1px solid red;
            padding: 10px;
            background-color: silver;
        }
        div > *{
            border: 1px solid black;
            width: 50px;
            height: 30px;
        }

image.png
上面两个弹性容器之间唯一的区别是,第一个元素使用display:flex后生成是块级框的弹性容器(未设置宽的情况下宽与父元素同宽)。第二个元素使用display:inline-flex后生成的是行内框的弹性容器

注意!!!!
把一个元素设为弹性容器之后,只有直接子元素使用弹性盒布局,其他后代元素不受影响。你也可以把其他后代元素也设为弹性容器,实现更复杂的布局

并且子元素的floatclearvertical-align属性将失效


在聊各种属性之前,我觉得有必要分享一下我对轴的看法(刚刚上面也说了,当时看别人的文章甚至不知道主轴和侧轴是啥玩意儿)

image.png
上面画的线并不是轴本身,而是方向,主轴和侧轴所在的方向,因为它们并没有具体的哪条哪条线,不像初中数学在几何上建立一个直角坐标系,这个x轴就确定了
或者应该可以这么画😄

image.png
芜湖!太帅了,反正抽象理解就好了😄


激活了弹性盒之后,我们就能使用对应的属性,大概分为以下两种:父元素身上的属性 和 子元素身上的属性,下面介绍一些常用的

"弹性容器"(父元素) 常用属性

flex-direction 设置主轴的方向

  1. 主轴与侧轴:
    在flex布局中,是分为主轴和侧轴两个方向,同样的叫法有行和列、x轴和y轴
    · 默认主轴的方向就是x轴的方向,水平向右
    · 默认侧轴的方向就是y轴的方向,水平向下

  2. 属性值:
    flex-direction属性决定了主轴的方向
    注意:主轴和侧轴是会变化的,就看flex-direction设置谁为主轴,另外一条的就是侧轴。
    而且我们的子元素是 跟着主轴来排列的

    row : 默认值,从左到右
    row-reverse: 从右到左
    column: 从上到下
    column-reverse:从下到上

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

justify-content设置主轴上子元素的排列方式
justify-content属性定义了弹性元素在主轴上的对齐方式
PS:使用这个属性前,一定要确认好主轴是哪个

flex-start : 默认值,从头部开始,如果主轴是x轴,则从左到右
flex-end : 从尾部开始排列
center : 主轴居中对齐(如果主轴是x轴,则水平居中)
space-around : 平分剩余空间
space-between: 先两边贴边,再平分剩余空间
space-evenly: 把剩余空间拆开,每个弹性元素的间距相等
来看看justify-content不同值的效果

    <div>
        <span>1</span>
        <span>2</span>
        <span>3</span>
    </div>
        div {
            /* 给父级添加flxe属性 */
            display: flex;
            width: 800px;
            height: 300px;
            background-color: pink;

            /* 这里默认的主轴flex-direction是row也就是x轴,而justify-content是设置主轴上子元素的排列方式 */
            /* justify-content: flex-start;默认 */
        }

        span {
            width: 150px;
            height: 50px;
            background-color: skyblue;
        }

justify-content: flex-start;默认情况👇

image.png

justify-content: flex-end;👇

image.png

justify-content: center;👇

image.png

justify-content: space-between;👇
space-between值把每一行里的第一个弹性元素放在主轴起边,把每一行最后一个弹性元素放在主轴终边,然后余下的每一对相邻的弹性元素之间放置等量的空白。

image.png

justify-content: space-around;👇
space-around把余下的空间拆分开,把各部分的一半分配给每个弹性元素,看起来就像每个元素四周都有等量的不折叠外边距。注意,这意味着任何两个弹性元素之间的距离是第一个弹性元素与主轴起边之间以及最后一个弹性元素与主轴终边之间距离的两倍

image.png

justify-content: space-evenly;👇
space-evenly也把余下的空间拆分开,不过每个间距的长度是相等的。也就是说,到主轴起边和到终边之间的距离,与弹性元素之间的距离是一样的。 image.png

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

flex布局中有这么一个问题,当子元素在一行现实不开的时候,会缩小其他子盒子,然后一行显示

flex-wrap设置子元素是否换行
默认情况下,项目都排在一条线上。flex-wrap属性定义,flex布局中默认是不换行的

nowrap : 默认值,不换行
wrap : 换行

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

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

和justify-content类似,只不过该属性是控制子项在侧轴(默认是y轴)上的排列方式

flex-start : 从上到下(从主轴起边到终边)
flex-end : 从下到上(从主轴终边到起边)
center : 挤在一起居中
stretch : 拉伸(默认值)
baseline (baseline的值有点复杂,这里不描述了)

    <div>
        <span>1</span>
        <span>2</span>
        <span>3</span>
    </div>
     div {
            display: flex;
            width: 600px;
            height: 400px;
            background-color: pink;
            
            align-items: flex-start;

        }

        div span {
            width: 150px;
            height: 100px;
            background-color: purple;
            color: #fff;
            margin: 10px;
        }

align-items: flex-start;👇

image.png

align-items: flex-end;👇

image.png

align-items: center;👇

image.png

align-items: stretch;👇
这个拉伸需要子盒子不给高度才能,效果是将子盒子拉伸地和父盒子一样高(把上面代码中子盒子高注释掉)

image.png

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

因为我们激活了弹性盒之后呢,默认flex-wrap属性是不换行的,所以侧轴上也只有一行,当我们开启换行的时候,侧轴上看去就不止一行了。这里的align-content就是设置多行的情况,子元素在侧轴上的排列方式

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

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

flex-start : 默认值,在侧轴的头部开始排列
flex-end : 在侧轴的尾部开始排列
center : 在侧轴的中间显示
space-around : 子项目平分剩余空间
space-between : 子项目在侧轴先分布在两头,再平分剩余空间
stretch : 设置子项目元素高度平分父元素高度

这里举其中一个例子

    <div>
        <span>1</span>
        <span>2</span>
        <span>3</span>
        <span>4</span>
        <span>5</span>
        <span>6</span>
    </div>
        div {
            display: flex;
            width: 600px;
            height: 400px;
            background-color: pink;
            /* 子项目默认不换行,手动设置换行 */
            flex-wrap: wrap;
            /* 因为有了多行,所以在侧轴上控制子元素的对齐方式我们用align-content */
            align-content: center;
        }

        div span {
            width: 150px;
            height: 100px;
            background-color: purple;
            color: #fff;
            margin: 10px;
        }

align-items 和 align-content的区别:

  1. align-items 用于单行情况下,只有上对齐、下对齐、居中、拉伸
  2. align-content 用于换行(多行)的情况(且在单行情况下无效),可以设置上对齐、下对齐、居中、拉伸、以及space-around、space-between

总结:单行用align-items 多行用align-content(但其实可以都只用align-items)


复合属性flex-flow

flex-flow属性是flex-direction和flex-wrap属性的复合属性,用于简化代码

            /* 设置主轴为y轴,子项目允许换行 */
            /* flex-direction: column;
            flex-wrap: wrap; */

            /* 以上两句可以用复合写法 */
            flex-flow: column wrap;

"弹性元素"(子元素) 常用属性

接下来看看常用的设置在子元素身上的属性
flex布局常见的子项属性:

  1. flex子项目占的份数
  2. align-self 控制子项自己在侧轴的排列方式(容器中的控制侧轴子项目的排列方式 是 整体控制,align-self是添加在子项目身上是控制单独一个)
  3. order属性定义了子项的排列顺序(前后顺序)

flex

其实flex是flex-grow、flex-shrink和flex-basis的简写形式。虽然三个子属性可以单独使用,但是强烈建议始终使用简写flex

flex 属性:
flex属性定义子项目分配剩余空间,用flex来表示占多少份数
重点关键词:剩余!
如果子盒子都没宽度,那么剩余宽度就是整个父盒子的宽度
如果只有部分子盒子有宽度,那么剩余的就是除了这些有宽度子盒子之外的其他区域

    .items {
             flex:<number>;  默认是0

             补充:不一定是写数字,可以写百分比,比如20%
             意为,占父盒子的20%
         } 

例子:

    <section>
        <!-- 情况1:左右两个盒子固定,中间的盒子占满剩下的 -->
        <div></div>
        <div></div>
        <div></div>
    </section>
    <p>
        <!-- 情况2:不给盒子宽度,将父盒子宽度平均分成3等份 -->
        <span>1</span>
        <span>2</span>
        <span>3</span>
    </p>
    section {
            display: flex;
            width: 60%;
            background-color: pink;
            margin: 0 auto;
        }

        section div:nth-child(1) {
            width: 100px;
            height: 150px;
            background-color: red;
        }

        section div:nth-child(2) {
            flex: 1;
            /* 将剩余空间分成1份全部给2号盒子 
                这种写法可以在上面那个京东案例里面,给搜索框添加
            */
        }

        section div:nth-child(3) {
            width: 100px;
            height: 150px;
            background-color: blueviolet;
        }

        p {
            display: flex;
            width: 60%;
            height: 150px;
            background-color: pink;
            margin: 100px auto;
        }

        p span {
            flex: 1;
            /* 
            此时p span选中的是所有的子盒子span,flex:1意为每个span占1份,有3个span,则父盒子被分为3份。 
            如果是flex:2也是一样,意为每个span占2份,有3个span,则父盒子p被分为了6份,但视觉效果来看是与flex:1是一样的,因为不管span是多少份,每个span都是占总的1/3。
            */
        }

        p span:nth-child(2) {
            flex: 2;
            /* 这里的flex:2是意为第二个span占两份,而第一个和第三个都是占1份,所以从视觉上来看 A:B:C为1:2:1 */
        }

image.png

align-self和order

align-self 控制子项目自己在侧轴上的排列方式

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

        语法:
        span:nth-child(2) {
            设置自己在侧轴上的对齐方式
            align-selfflex-end
        }

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

数值越小,排列越靠前,默认为0
注意:和z-index不一样

    <div>
        <span>1</span>
        <span>2</span>
        <span>3</span>
    </div>
    div {
            display: flex;
            /* 这样写是让3个盒子在侧轴上,沿着底部对齐 */
            /* align-items: flex-end; */
            /* 如果我只想让3号盒子下来底侧,要怎么写:只能给3号盒子自己一个样式,不能像这个align-items一样给父盒子,因为控制的是所有子盒子(单行)在侧轴的对齐方式 */
            width: 80%;
            height: 300px;
            background-color: pink;
        }

        div span {
            width: 150px;
            height: 100px;
            background-color: purple;
            margin-right: 5px;
        }

        /* 如果在不改变结构的情况下,怎么把二号盒子放到最前面? */
        div span:nth-child(2) {
            /* 默认是0,-1比0小,会放到最前面 */
            order: -1;
        }

        div span:nth-child(3) {
            /* order: -2; */
            align-self: flex-end;
        }

image.png


以上,有部分解释是摘自书上,毕竟我认为官方的解释肯定比我自己解释好0 0
移动端还有其他几大布局大家应该熟的不行了,我就不做记录了,太懒了0 0
其他有错误的地方,请多多指教~