✅ 关于 Flex,很多优秀的前辈已经总结过了,比如:阮一峰《Flex 布局教程:语法篇》、知乎林东洲《30 分钟学会 Flex 布局》等等。他们主要是基于网页的,小辈斗胆笔耕一篇倾向于 “微信小程序” 的 Flex 博客。



微信小程序开发 🌲

上一篇文章链接: 微信小程序学习笔记③——wxml+wxss+js基础入门[样例+解析]

下一篇文章链接: 微信小程序(5)——如何制作好看的表格


一、Flex 概述

● 为什么要学 “布局”?
因为后面设计微信小程序的展示界面时,若没有一个良好的 “底层页面摆放逻辑”,那么我们的小程序很可能来实用过程中出现 “内容显示不全”、“图片变形或错位”、“表格错位”、“文本框重叠” 等莫名其妙的 Bug。学 “布局” 不是一个需要我们去敲它的底层逻辑,而是去学如何良好的使用它。

为什么要学 “Flex布局”?原因如下
2009年,W3C(万维网联盟,全称World Wide Web Consortium)提出了一种新的方案——“Flex布局”,可以简便、完整、响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能。Flex布局将成为未来布局的首选方案。

在这里插入图片描述

说明:以上是主流浏览器支持的力度。最下面的版本是最新版本,可以发现,几乎全部都是 “Supported”。


Flex 简介:全称为 “Flexible Box Layout”,即 “弹性盒布局”,旨在提供一种更有效的方式来布局对齐分配容器中项目之间的空间,即使它们的大小未知或动态变化。

Flex 布局背后的主要思想:是让容器能够改变其项目的宽度/高度(或顺序)以最好地填充可用空间(主要是为了适应各种显示设备和屏幕尺寸),以防止显示不完整或溢出。

“Flex 布局”与 “常规布局” 的对比:与常规布局(基于垂直的块和基于水平的内联)相反,弹性盒布局与方向无关。虽然这些适用于页面,但它们缺乏灵活性来支持大型或复杂的应用程序(尤其是在涉及方向更改、调整大小、拉伸、收缩等方面 → 比如说在拉伸缩小页面时,页面显示的东西也跟着 “弹性地” 变化,你可以试试拉伸这个网站:《A Complete Guide to Flexbox》)。

注意: Flexbox 布局最适合应用程序的组件和小规模布局,而 Grid 布局适用于更大规模的布局。

学习 Flex 的官方文章《A Complete Guide to Flexbox》《A Visual Guide to CSS3 Flexbox Properties》



二、基础知识和术语

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

在这里插入图片描述
说明
  ① 容器默认存在两根轴:水平的『主轴(main axis)』和垂直的『交叉轴(cross axis)』。【注,我们可以通过修改使垂直方向变为主轴,水平方向变为交叉轴,后面会讲

  ② 主轴与左右边框的交叉点,分别叫作『主轴开始处(main start)』、『主轴结束处(main end)』。

  ③ 交叉轴与左右边框的交叉点,分别叫作『交叉轴开始处(cross start)』、『交叉轴结束处(cross end)』。

  ④ 项目默认沿主轴排列。单个项目占据的主轴空间【注,这里的空间是一维的,即“长度空间”】叫作『占主轴尺寸(main size)』,占据的交叉轴空间叫做『占交叉轴尺寸(cross size)』。



三、Flex 容器初了解

在这里插入图片描述

● 任何一个容器都可以指定为 Flex 布局。样例如下:

WXML代码如下

<image src="./Images_Flex/Flex项目1.png" style="width: 60px;height: 60px;"></image>
<image src="./Images_Flex/Flex项目2.png" style="width: 60px;height: 60px;"></image>
<image src="./Images_Flex/Flex项目3.png" style="width: 60px;height: 60px;"></image>
<image src="./Images_Flex/Flex项目4.png" style="width: 60px;height: 60px;"></image>
<image src="./Images_Flex/Flex项目5.png" style="width: 60px;height: 60px;"></image>


<view class="MyContainer">
    <image src="./Images_Flex/Flex项目1.png" style="width: 60px;height: 60px;"></image>
    <image src="./Images_Flex/Flex项目2.png" style="width: 60px;height: 60px;"></image>
    <image src="./Images_Flex/Flex项目3.png" style="width: 60px;height: 60px;"></image>
    <image src="./Images_Flex/Flex项目4.png" style="width: 60px;height: 60px;"></image>
    <image src="./Images_Flex/Flex项目5.png" style="width: 60px;height: 60px;"></image>
</view>

WXSS代码如下

.MyContainer_1 {
    display: flex;
    justify-content: space-around;
}

代码说明
  ① 引入图片用的是 “image” 标签,src 指向图片的存储路径,styleclass 的功能类似,只不过可以直接在标签项里面写。
  ② px 是像素的意思,是一中计量单位,60px 表示占电脑屏幕的 60 个像素点。
  ③ .wxml 代码中的第二段中出现了 “嵌套”,这是笔者写 “微信小程序学习笔记” 以来第一次出现。可以理解为内层的标签『项目』会包含在它外层的标签『项目』的里面
  ④ container 是一个 WXSS 里面内嵌的一个 “封装好的选择器”,我们不用它,用自己写的。
  ⑤ display 是该选择器里面的一个( 布局)属性。
  ⑥ 项目默认沿主轴排列。

图片存储情况和运行结果

在这里插入图片描述

说明:左边演示框的上面一堆是普通的摆放,下面的是 flex 布局。为什么为这样子摆放,是 “justify-content: space-around;” 起的作用,后面会学到。【justify-content: space-around; → 每个项目两侧的间隔相等。且项目之间的间隔比项目与边框的间隔大一倍】



四、Flex 容器的属性

Flex 容器常用的有 6 个属性:flex-direction、flex-wrap、flex-flow、justify-content、align-items、align-content。接下来将依次对其进行学习。并在文末进行实践运用。


4.1 flex-direction 属性

flex-direction 属性:决定主轴的方向(即项目的排列方向)。它常用的有 4 个选项。

在这里插入图片描述

.box {
  flex-direction: row;  /* 或 row-reverse 或 column 或 column-reverse; */
}
选项功能
row(默认值)主轴为水平方向,起点在左端
row-reverse主轴为水平方向,起点在右端
column主轴为垂直方向,起点在上沿
column-reverse主轴为垂直方向,起点在下沿


4.2 flex-wrap 属性

● 默认情况下,项目都排在一条线(又称”轴线”)上。flex-wrap 属性:定义如果一条轴线排不下,如何换行。它常用的有 3 个选项。

在这里插入图片描述

.box{
  flex-wrap: nowrap | wrap | wrap-reverse;   /* 这样写只是为了方便展示, WXSS 没有这样的语法*/
}
选项功能演示图
nowrap(默认值)不换行下图中红色方块的排列方式
wrap换行,第一行在上方下图中黄色方块的排列方式
wrap-reverse换行,第一行在下方下图中蓝色方块的排列方式

在这里插入图片描述


4.3 flex-flow 属性

flex-flow 属性:是 flex-direction 属性和 flex-wrap 属性的简写形式,默认值为 row nowrap

.box{
   flex-flow: <flex-direction:有四种> <flex-wrap:有三种>;   /* 这样写只是为了方便展示, WXSS 没有这样的语法*/
}

样例:
.box{
   flex-flow: row nowrap;  
}



4.4 justify-content 属性

justify-content 属性:定义了项目在『主轴(main axis)』上的对齐方式。它常用的有 6 个选项。

在这里插入图片描述

.box{
  justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;   
  /* 这样写只是为了方便展示, WXSS 没有这样的语法*/
}
选项功能
flex-start(默认值)左对齐
flex-end右对齐
center居中
space-between两端对齐,项目之间的间隔都相等
space-around每个项目两侧的间隔相等。且项目之间的间隔比项目与边框的间隔大一倍
space-evenly每个项目两侧的间隔相等。且项目之间的间隔与项目与边框的间隔一样大


4.5 align-items 属性

align-items 属性:定义项目在『交叉轴(cross axis)』上如何对齐。它常用的有 5 个选项。【具体对齐方式与轴的方向有关。下面的演示图一律假设主轴为从左到右,交叉轴为从上到下】

在这里插入图片描述

.box{
  align-items: flex-start | flex-end | center | baseline | stretch;  
  /* 这样写只是为了方便展示, WXSS 没有这样的语法*/
}
选项功能
flex-start交叉轴的起点对齐
flex-end交叉轴的终点对齐
center交叉轴的中点对齐
baseline项目的第一行文字的基线对齐
stretch(默认值)如果项目未设置高度或设为auto,将占满整个容器的高度


4.6 align-content 属性

align-content 属性:定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。它常用的有 6 个选项。【具体对齐方式与轴的方向有关。下面的演示图一律假设主轴为从左到右,交叉轴为从上到下】

在这里插入图片描述

.box{
  align-content: flex-start | flex-end | center | space-between | space-around | stretch;
  /* 这样写只是为了方便展示, WXSS 没有这样的语法*/
}
选项功能
flex-start与交叉轴的起点对齐
flex-end与交叉轴的终点对齐
center与交叉轴的中点对齐
space-between与交叉轴两端对齐,轴线之间的间隔平均分布
space-around每根轴线两侧的间隔都相等,且轴线之间的间隔比轴线与边框的间隔大一倍
stretch(默认值)轴线伸展(即项目拉伸)以占用剩余空间


五、项目的属性

● 前面把 “容器” 的属性讲完了,接下来讲 “容器” 里面的 “项目”。

Flex 项目常用的有 6 个属性:order、flex-grow、flex-shrink、flex-basis、flex、align-self。


5.1 order 属性

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

在这里插入图片描述

.item {
  order: <integer>;		/* <integer> 即是我们需要写的数字*/
}


5.2 flex-grow 属性

flex-grow 属性:定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。

在这里插入图片描述

.item {
  flex-grow: <number>; 	/* <number> 即是我们需要编写的数字*/
}

说明:如果所有项目的 flex-grow 属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的 flex-grow 属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。如上图的第二个样例。


5.3 flex-shrink 属性

flex-shrink 属性:定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。【下图中,中间个项目的 flex-shrink0,其他两个为 1

在这里插入图片描述

.item {
  flex-shrink: <number>; 	/* <number> 即是我们需要编写的数字*/
}

说明
  ① 如果所有项目的 flex-shrink 属性都为1,当空间不足时,都将等比例缩小。
  ② 如果这时存在一个项目的 flex-shrink 属性为0,其他项目都为1,则空间不足时,前者不缩小,后者全部等比例缩小。
  ③ 负值对该属性无效。


5.4 flex-basis 属性

flex-basis 属性:定义了在分配多余空间之前,项目占据的『占主轴尺寸(main size)』。它的默认值为 auto,即项目的本来大小。但如果设置了 flex-basis,权重会比 width 属性高,因此会覆盖 widtn 属性。(假设主轴方向为 width 方向)

在这里插入图片描述

.item {
  flex-basis: <length>;		/* <length> 即是我们需要编写的数字*/
}

说明:它可以设为跟 widthheight 属性一样的值(比如350px),则项目将占据固定空间。


5.5 flex 属性

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

.item {
    flex: auto | none | [ <'flex-grow'> <'flex-shrink'> <'flex-basis'> ]	
}

● 该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)。

说明:建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。


5.6 align-self 属性

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

在这里插入图片描述

.item {
    align-self: auto | flex-start | flex-end | center | baseline | stretch;
    /* 这样写只是为了方便展示, WXSS 没有这样的语法*/
}
选项功能
auto(默认值)表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch
flex-start交叉轴的起点对齐
flex-end交叉轴的终点对齐
center交叉轴的中点对齐
baseline项目的第一行文字的基线对齐
stretch如果项目未设置高度或设为auto,将占满整个容器的高度


六、实战样例 —— 画骰子⭐️⭐️

● 光说不练假把式,又说又练真把式!

设计要求:用一个 “容器” 装 6 个骰子,每个骰子显示一个面。

在这里插入图片描述

WXML代码如下

<view class="MyContianer">
    <!-- 一点 -->
    <view class="square">
        <view class="null_paral"> 
            <view class="null_Point"></view>
        </view>

        <view class="second_1">
            <view class="Point"></view>
        </view>

        <view class="null_paral"> 
            <view class="null_Point"></view>
        </view>
    </view>

    <!-- 两点 -->
    <view class="square">
        <view class="first_1">
            <view class="Point"></view>
        </view>
        <view class="null_paral"> 
            <view class="null_Point"></view>
        </view>
        <view class="three_1">
            <view class="Point"></view>
        </view>
    </view>

    <!-- 三点 -->
    <view class="square">
        <view class="first_2">
            <view class="Point"></view>
        </view>
        <view class="second_1">
            <view class="Point"></view>
        </view>
        <view class="three_1">
            <view class="Point"></view>
        </view>
    </view>

    <!-- 四点 -->
    <view class="square">
        <view class="first_2">
            <view class="Point"></view>
            <view class="Point"></view>
        </view>
        <view class="null_paral"> 
            <view class="null_Point"></view>
        </view>
        <view class="three_2">
            <view class="Point"></view>
            <view class="Point"></view>
        </view>
    </view>

    <!-- 五点 -->
    <view class="square">
        <view class="first_2">
            <view class="Point"></view>
            <view class="Point"></view>
        </view>
        <view class="second_1">
            <view class="Point"></view>
        </view>
        <view class="three_2">
            <view class="Point"></view>
            <view class="Point"></view>
        </view>
    </view>

    <!-- 六点 -->
    <view class="square">
        <view class="first_2">
            <view class="Point"></view>
            <view class="Point"></view>
        </view>
        <view class="second_2">
            <view class="Point"></view>
            <view class="Point"></view>
        </view>
        <view class="three_2">
            <view class="Point"></view>
            <view class="Point"></view>
        </view>
    </view>
</view>

代码说明
  ① 我的设计方案是:最外层(第1层)一个大容器,flex 布局,且可换行。第2层是六个骰子(即“小容器”)。第3层是每个骰子里面的 “上、中、下” 的三个 “隐形的长方型框框”。最后一层(第4层)是画 “点” 的『view 组件』。
  ② 我设计 “空行” 的方法是:在那个 “隐形的长方型框框” 塞一个和背景(黑色)颜色一样的骰子。
  ③ first_1 的意思是:first 行存在 1 个 “点” 的情况。


WXSS代码如下

.MyContianer {
    margin-top:50px;
    background-color: #e1e7e9;
    border-left: 2px solid black;
    border-right: 2px solid black;
    border-top: 2px solid black;
    border-bottom: 2px solid black;
    height: 200px;
    width: auto;
    
    display: flex;
    flex-wrap: wrap;
    justify-content: space-around;  /* 主轴 */
    align-items: center;            /* 交叉轴(默认是竖轴)居中 */
}

.square {
    background-color: rgb(0, 0, 0);   /* 骰子底色*/
    width: 20%;     /* 容器 width 的 20% */
    height: 40%;    /* 容器 height 的 20% */
    margin-left: 5px; /* 外边距 */
    margin-right: 5px;

    /* 使用 flex 布局 */
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;
}

.null_paral, .first_1, .first_2, .second_1, .second_2, .three_1 ,.three_2 { /* 共有的属性*/
    padding: 3px;           /* 间距 */
    display: flex;          /* 使用flex布局 */
    align-items: center;    /* 交叉轴(默认是竖轴)居中 */
}

.null_paral {
    flex-direction: row;    /* 从左到右排列 */ 
    justify-content: space-between; /* 两端对齐,项目之间的间隔都相等 */
}

.first_1 {
    flex-direction: row;       /* 从左到右排列 */ 
}

.first_2 {
    flex-direction: row;       /* 从左到右排列 */ 
    justify-content: space-between;    /* 两端对齐,项目之间的间隔都相等 */
}
.second_1 {
    flex-direction: row;        /* 从左到右排列 */ 
    justify-content: center;    /* 水平居中 */
}

.second_2 {     /* 和 first_2 一样 */
    flex-direction: row;       /* 从左到右排列 */ 
    justify-content: space-between;    /* 两端对齐,项目之间的间隔都相等 */
}

.three_1 {  
    flex-direction: row-reverse;    /* 从右到左排列 */ 
}

.three_2 {     /* 和 first_2 一样 */
    flex-direction: row;       /* 从左到右排列 */ 
    justify-content: space-between;    /* 两端对齐,项目之间的间隔都相等 */
}

.Point {	/* 白色的点 */
    display: block;
    height: 20px;
    width: 20px;
    background-color: #ffffff;
    border-radius: 50%;
}

.null_Point {	/* “隐藏”的点 */
    display: block;
    height: 20px;
    width: 20px;
    background-color: black;
    border-radius: 50%;
}

代码说明:我觉得 .MyContianer{} 中的 flex-direction 应该设置为 row 才对,但是若这样设计,骰子的 “点” 就会很奇怪地排列,设置为 column 就没事。难道微信小程序有啥隐藏的 Bug?

运行结果

在这里插入图片描述



七、参考附录

[1] 《Flex 布局语法教程》

[2] 《A Complete Guide to Flexbox》

[3] 《最详细完整的flex弹性布局》

[4] 《30 分钟学会 Flex 布局》,作者:林东洲

[5] 《Flex 布局教程:语法篇》,作者:阮一峰

[6] 《一篇文章弄懂flex布局》

[7] 《A Visual Guide to CSS3 Flexbox Properties》

[8] 《微信小程序开发之七 —— Flex、Grid与List布局》

[9]《微信小程序开发指南》

上一篇文章链接: 微信小程序学习笔记③——wxml+wxss+js基础入门[样例+解析]

下一篇文章链接: 微信小程序(5)——如何制作好看的表格


⭐️ ⭐️

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐