弹性盒子布局(Flex Box Layout

弹性盒子是一种基于父容器的布局机制,它通过 display: flex 来激活,激活后容器中的子元素可以在水平或垂直方向上膨胀以填充额外的空间,或收缩以适应更小的空间

弹性盒子布局的基本概念:

Flex Container(弹性容器, 伸缩容器)
display 的值设置为 flexinline-flex 的元素为弹性容器

Flex Item(弹性项目, 伸缩项目)
弹性容器( Flex Container ) 的每个子元素称为弹性项目

main axis(主轴)
所有弹性项目( Flex Item )沿其一侧排列的轴称为主轴

cross axis(交叉轴)
垂直于主轴的轴称为交叉轴

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/IMG_20250614_225117.5q7o7xqedm.webp

样例 HTML:

1
2
3
4
5
6
7
<div class="container">  
<div style="background-color: lightgray">盒子1</div>
<div style="background-color: lightgreen">盒子2</div>
<div style="background-color: lightpink">盒子3</div>
<div style="background-color: lightsalmon">盒子4</div>
<div style="background-color: lightskyblue">盒子5</div>
</div>

弹性容器属性

flex-direction(主轴方向)

flex-direction 用来设置弹性容器中子元素沿主轴的排列方向

CSS 基础样式(基于样例 HTML):

1
2
3
4
5
6
7
8
9
.container {  
width: 900px;
border: 3px solid black;
display: flex;
}
.container div {
width: 120px;
height: 300px;
}

row:设置主轴为水平方向

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/37389c5581f1b1e0f393d0be40e6c469.6ikjpp0twa.webp

1
2
3
.container {  
flex-direction: row;
}

row-reverse:与 row 的排列方向相反

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/803603266f73491749545ce23448476f.5mo2a8tboy.webp

1
2
3
.container {  
flex-direction: row-reverse;
}

column:设置主轴为垂直方向

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/54aa34ebb2e75870d64dca6df7f3dabe.51eeny0nqy.webp

1
2
3
.container {  
flex-direction: column;
}

column-reverse:与 column 的排列方向相反

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/590a72e8867f83e75d7962b9f75a767c.3gonoh59p9.webp

1
2
3
.container {  
flex-direction: column-reverse;
}

容器内子元素的排列方向:

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/88f718156e75ca09a7b07cbb3bc0af39.7axf7fbdsh.webp

justify-content(主轴对齐方式)

justify-content 用于控制主轴上弹性项目的对齐方式

CSS 基础样式(基于样例 HTML):

1
2
3
4
5
6
7
8
9
.container {  
width: 900px;
border: 3px solid black;
display: flex;
}
.container div {
width: 120px;
height: 300px;
}

center:弹性项目向第一行的中间位置对齐

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/3ca45a48c335c9f0acd94adc0d12a288.3nrvjx52h0.webp

1
2
3
.container {  
justify-content: center;
}

flex-start:伸缩项目向第一行的开始位置对齐

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/ab29192583e9110496601b63929eb8af.lvzip5ly0.webp

1
2
3
.container {  
justify-content: flex-start;
}

flex-end:伸缩项目向第一行的结束位置对齐

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/9b46ff363f323af3ef75ffd21a9b54f6.77dt9qb6ya.webp

1
2
3
.container {  
justify-content: flex-end;
}

space-between:伸缩项目会平均分布在一行中

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/a9a0f85b87fd467e48a29f4bd552f02a.4xusq8s0ce.webp

1
2
3
.container {  
justify-content: space-between;
}

space-around:伸缩项目会平均分布在一行中,两端保留一半的空间

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/848efdf5bcf7c9c876e5e2bcebfccaa7.102f9kj4f7.webp

1
2
3
.container {  
justify-content: space-around;
}

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/08d9bd85aa3da08e92df855455ac420c.8vn66x6edb.webp

align-items(交叉轴对齐方式)

align-items 用于设置弹性项目在交叉轴(cross axis)上的对齐方式

CSS 基础样式(基于样例 HTML):

1
2
3
4
5
6
7
8
9
10
11
12
.container {  
width: 900px;
height: 300px;
border: 3px solid black;
display: flex;
/* 主轴对齐方式 */
justify-content: space-between;
}
.container div {
width: 120px;
height: 150px;
}

stretch:默认值,伸缩项目拉伸填充整个伸缩容器

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/45063f087bcef0f2da756137e27bed0d.26lqi6xx3t.webp

1
2
3
4
.container {  
/* 交叉轴对齐方式 */
align-items: stretch;
}

center:伸缩项目向侧轴的中间位置对齐

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/624fbce6d802f1d792af745771ab51a9.8hgqg2p345.webp

1
2
3
4
.container {  
/* 侧轴对齐方式 */
align-items: center;
}

flex-start:伸缩项目向侧轴的起点位置对齐

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/45063f087bcef0f2da756137e27bed0d.26lqi6xx3t.webp

1
2
3
4
.container {  
/* 侧轴对齐方式 */
align-items: flex-start;
}

flex-end:伸缩项目向侧轴的终点位置对齐

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/ee182a22b02e5b71410343411fe9a013.8adiknddof.webp

1
2
3
4
.container {  
/* 侧轴对齐方式 */
align-items: flex-end;
}

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/1cffb7d71df4c341267517e04e634d94.3yepd5plzh.webp

flex-wrap(单行/多行显示)

flex-wrap 用于控制当弹性项目在主轴方向上超出容器空间时,是否换行

CSS 基础样式(基于样例 HTML):

1
2
3
4
5
6
7
8
9
10
11
12
.container {  
width: 900px;
height: 300px;
border: 3px solid black;
display: flex;
/* 主轴对齐方式 */
justify-content: space-between;
}
.container div {
width: 120px;
height: 150px;
}

nowrap:设置伸缩项目单行显示。这种方式可能导致溢出伸缩容器

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/f44c75285737bc115ce759d8da66c29a.8dx4ievlaq.webp

可见,容器宽度 900px,容器内一共 9 个子元素,每个 120px,他们紧紧的排列在一起

1
2
3
.container {  
flex-wrap: nowrap;
}

wrap:设置伸缩项目多行显示

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/6a7a66335ef131c61852a1da4ea223e0.6bhbucyw1n.webp

当多行显示时,第一行放不下的元素会被放到下一行(第二行),因为设置了主轴对齐方式为 space-between,所以多出来的两个元素分别到了两端

1
2
3
.container {  
flex-wrap: wrap;
}

wrap-reverse:与 wrap 相反

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/68f3e9345e97d6168e135a0a57b72767.5xaw3hs662.webp

当多行显示时,第一行放不下的元素会被放到上一行(第二行),因为设置了主轴对齐方式为 space-between,所以多出来的两个元素分别到了两端

1
2
3
.container {  
flex-wrap: wrap-reverse;
}

align-content(交叉轴多行对齐方式)

align-content 用于控制多行弹性项目在交叉轴(cross axis)方向上的对齐方式

CSS 基础样式(基于样例 HTML):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.container {  
width: 900px;
height: 600px;
border: 3px solid black;
/* 将当前元素设置为弹性盒子模型的伸缩容器 */
display: flex;
/* justify-content属性表示项目在主轴的对其方式 */
justify-content: space-between;
/* 设置伸缩项目是单行显示还是多行显示 */
flex-wrap: wrap;
}
.container div {
width: 120px;
height: 150px;
}

stretch:默认值,各行将会伸展以占用额外的空间

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/3c1090dbd41ba0eba17c7898c87e998a.1e8v1e9f5j.webp

1
2
3
4
.container {  
/* align-content属性设置伸缩项目所在行的对齐方式 */
align-content: stretch;
}

center:各行向伸缩容器的中间位置对齐

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/805a28e03655fbd3119c4afdcb9c4ed1.7lk91k6rsr.webp

1
2
3
4
.container {  
/* align-content属性设置伸缩项目所在行的对齐方式 */
align-content: center;
}

flex-start:各行向伸缩容器的起点位置对齐

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/d30affd9e07a03e34346a8edaaa7a003.2324lf042o.webp

1
2
3
4
.container {  
/* align-content属性设置伸缩项目所在行的对齐方式 */
align-content: flex-start;
}

flex-end:各行向伸缩容器的终点位置对齐

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/0e35ad282dcd38703964d990508fe8cc.39lfu0qabc.webp

1
2
3
4
.container {  
/* align-content属性设置伸缩项目所在行的对齐方式 */
align-content: flex-end;
}

space-between:各行会平均分布在一行中。第一项与起始点齐平,最后一项与终止点齐平

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/dfdf45e4d48810985cc5931aa556b6f2.7w72upqdqz.webp

1
2
3
4
.container {  
/* align-content属性设置伸缩项目所在行的对齐方式 */
align-content: space-between;
}

space-around:各行会平均分布在一行中,两端保留一半的空间

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/a0b03d2eca5689738240e2dbc22175a3.5mo2b87h2v.webp

1
2
3
4
.container {  
/* align-content属性设置伸缩项目所在行的对齐方式 */
align-content: space-around;
}

flex-flow

flex-flow 属性适用于伸缩容器元素,该属性是 flex-direction 和 flex-wrap 的简写。

其语法:flex-flow: <'flex-direction'> || <'flex-wrap'>,示例:flex-flow: row wrap

弹性项目属性

flex-grow(伸展比例)

flex-grow 属性用来控制弹性项目在主轴上的放大比例 (剩余空间按比例分配)。默认为 0,即如果容器存在剩余空间,也不放大

其属性的取值为数字

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/c2e4f379f5fe91245eee27eabc7c67b2.8l0ceqoh5l.webp

flex-shrink(收缩比例)

flex-shrink 属性定义了弹性项目的在主轴上的缩小比例,默认为 1,即如果空间不足,该项目将缩小

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/ae80f26c2897a68994540eb38de25f3a.92qe3c2dcx.webp

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

flex-basis(初始大小)

flex-basis 属性定义了在还没计算 flex-growflex-shrink 之前,弹性项目的主轴大小( 初始大小 )是多少,默认值 auto,根据内容推算初始大小

大部分情况下 flex-basis 属性和 widthheight 表现一致,如果两者同时使用 flex-basis 优先级会高一些

例:

1
2
3
4
.item {
flex-basis: 200px;
}
/* 表示这个元素在主轴方向上「初始是 200px」,然后再参与伸展 (flex-grow) 或收缩 (flex-shrink) 的计算 */

order(顺序)

order 属性用于设置弹性项目在布局时的顺序。默认为 0,值越大越靠后

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
<style>  
.container {
width: 900px;
height: 600px;
border: 3px solid black;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.container div {
width: 120px;
height: 150px;
}
.container div:nth-child(1) {
order: 2;
}
.container div:nth-child(2) {
order: 3;
}
.container div:nth-child(3) {
order: 1;
}
</style>
<div class="container">
<div style="background-color: lightgray">盒子1 - order:2</div>
<div style="background-color: lightgreen">盒子2 - order:3</div>
<div style="background-color: lightpink">盒子3 - order:1</div>
</div>

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/image.32i8z7pnp4.webp

网格布局(Grid Layout)

Grid Layout 是一种允许你以网格(rows 和 columns)来对网页内容进行布局的模块,相比 Flex Box 布局,网格布局可以在行和列两个维度上同时进行布局( 二维布局 )

它可以非常轻松地把页面分割成主要区域,还可以在小部件内定义更复杂的布局

网格布局与弹性盒子布局有一些相同的概念:

Grid Container(网格容器)
display 的值设置为 gridinline-grid 的元素为网格容器

Grid Item(网格项目)
网格容器( Grid Container )的直接子元素为网格项目

样例 HTML:

1
2
3
4
5
6
7
8
9
10
11
<div class="container">
    <div class="grid-item" style="background-color: red">1</div>
    <div class="grid-item" style="background-color: green">2</div>
    <div class="grid-item" style="background-color: blue">3</div>
    <div class="grid-item" style="background-color: violet">4</div>
    <div class="grid-item" style="background-color: pink">5</div>
    <div class="grid-item" style="background-color: purple">6</div>
    <div class="grid-item" style="background-color: orange">7</div>
    <div class="grid-item" style="background-color: sienna">8</div>
    <div class="grid-item" style="background-color: bisque">9</div>
</div>

网格容器属性

grid-template-columns & grid-template-rows(列宽与行高)

grid-template-columns & grid-template-rows 用于定义列的宽度行的高度

1
2
3
4
5
6
7
8
.container {
/* 定义网格布局 */
display: grid;
/* 定义三列网格,宽度为200px */
grid-template-columns: 200px 200px 200px;
/* 定义三行网格,高度为60px */
grid-template-rows: 60px 60px 60px;
}

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/634abbb85ba0e.2doz0wvql5.webp

grid-template 的其它值:

repeat 函数用于重复一个值或模式,其接受两个参数:

  • 重复的次数
  • 重复的值或模式
1
2
3
4
5
6
7
.container {  
display: grid;
/* 三列网格,每列宽为 33.33% */
grid-template-columns: repeat(3, 33.33%);
/* 三行网格,每行高为 33.33% */
grid-template-rows: repeat(3, 33.33%);
}

定义六列,第一列和第四列的宽度为 40px,第二列和第五列为 60px,第三列和第六列为 80px

1
2
3
4
.container{  
/* 以下定义相当于 grid-template-columns: 40px 60px 80px 40px 60px 80px; */
grid-template-columns: repeat(2, 40px 60px 80px);
}

该函数用于产生一个长度范围,其接受两个参数:

  • 最小值
  • 最大值

grid-template-columns: 1fr 1fr minmax(100px, 1fr); 表示第三列宽度最小为 100 像素,最大为 1 个单位

当单元格大小固定,但容器大小不确定时,希望每一行或每一列都尽可能的容纳多个单元格,此时则可以使用关键字 auto-fill 或 auto-fit 关键词

1
2
3
4
5
6
7
.container {
display: grid;
/* 定义多列网格(数量取决于父容器宽度),每列宽度200px */
grid-template-columns: repeat(auto-fill, 200px);
/* 定义 3 行网格,每行高度60px */
grid-template-rows: repeat(3, 60px);
}
1
2
3
4
5
6
7
.container {
display: grid;
/* 定义多列网格,每列宽度最小为 200px, 容器剩余空间自动均分, 如果是 auto-fill 就不会利用剩余空间 */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
/* 定义 3 行网格,每行高度60px */
grid-template-rows: repeat(3, 60px);
}

fr 是 Grid 中用于表示空间分配比例的单位,例如 grid-template-columns: 1fr 2fr; 则表示前者为宽度为 1 个单位,则后者为前者的两倍:2 个单位

fr 单位也可以与绝对单位相配合:grid-template-columns: 150px 1fr 2fr;,此时则表示:第一列为 200px,剩余宽度分配成 1:2 的比例并分配给第二列和第三列

1
2
3
4
5
6
7
8
.container {  
/* 定义网格布局 */
display: grid;
/* 定义三列网格,第一列宽度为200px,剩余宽度分配成1:2的比例并分配给第二列和第三列 */
grid-template-columns: 200px 1fr 2fr;
/* 定义三行网格,高度为60px */
grid-template-rows: repeat(3, 60px);
}

auto 关键字表示由浏览器分配剩余可用长度。例如:grid-template-columns: 100px auto 100px; 表示第一列与第三列宽度为 100 像素,第二列则占用全部剩余宽度

row-gap & column-gap(间距)

  • row-gap 属性设置行与行的间隔(行间距)
  • column-gap 属性设置列与列的间隔(列间距)
1
2
3
4
5
6
7
.container {
display: grid;
grid-template-columns: repeat(3, 200px);
grid-template-rows: repeat(3, 60px);
row-gap: 20px; /* 20像素行间距 */
column-gap: 30px; /* 30像素列间距 */
}

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/PowerToys_Paste_20250703202708.7snhmzv5z4.webp

gap 属性是 column-gap 和 row-gap 的合并简写形式,语法如下

  • gap: <grid-row-gap> <grid-column-gap>;

grid-template-areas & grid-area(区域)

网格布局允许指定 “区域”(area),一个区域由单个或多个单元格组成

grid-template-areas 属性用于定义区域,grid-area 属性(网格项目属性)指定项目放在哪一个区域

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
35
36
37
38
39
40
41
42
43
44
45
<html>
<head>
    <style>
        header {
            background-color: rgba(252, 20, 20, 0.7);
            grid-area: header;
        }
        aside {
            background-color: rgba(254, 172, 21, 0.7);
            grid-area: sidebar;
        }
        main {
            background-color: rgba(25, 98, 255, 0.7);
            grid-area: content;
        }
        footer {
            background-color: rgba(3, 157, 3, 0.7);
            grid-area: footer;
        }
        .container {
        /* 容器内部居中 */
        justify-content: center;
            display: grid;
            gap: 10px;
            /* 列宽 第 1 列宽度会自动计算为剩余宽度(800 - 300 - 300 = 200), 第 2 列宽度为 300px, 第 3 列宽度为 300px */
            grid-template-columns: 200px 300px 300px;
            /* 行高 第 1 行高 50px, 第 2 行高 250px, 第 3 行高 80px */
            grid-template-rows: 50px 250px 80px;
            /* 根据文本模板定义三行三列网格 */
            grid-template-areas:
                "header header header" /* 第一行为 header 区域 */
                "sidebar content content" /* 第二行 左边 sidebar 区域占 1 个单元格, 右边 content 区域占 2 个单元格 */
                "footer footer footer"; /* 第三行为 footer 区域 */
        }
    </style>
</head>
<body>
    <div class="container">
        <header>头部</header>
        <aside>侧边栏</aside>
        <main>内容</main>
        <footer>底部</footer>
    </div>
</body>
</html>

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/image.7pksvjpkz.webp

justify-items & align-items(单元格对齐方式)

  • justify-items:控制 每个格子里的内容水平方向 的对齐方式
  • align-items:控制 每个格子里的内容垂直方向 的对齐方式

justify-items 和 align-items 属性的取值和写法完全一样:

1
2
3
4
.container {  
justify-items: start | end | center | stretch;
align-items: start | end | center | stretch;
}
  • start:对齐单元格的起始边缘
  • end:对齐单元格的结束边缘
  • center:单元格内部居中
  • stretch:拉伸,占满单元格的整个宽度(默认值)

例如:justify-items: start; 属性表示该单元格内容左对齐

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/image.mcxgnez4.webp

简写属性 place-items

  • place-items: <align-items> <justify-items>;

justify-content & align-content(网格整体对齐方式)

  • justify-content水平方向上对齐整个 grid 容器
  • align-content垂直方向上对齐整个 grid 容器

Tips:它们只在 网格总尺寸小于容器尺寸时起作用

1
2
3
4
.container {  
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
}

靠容器起始边对齐

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/image.5fkvfwiugf.webp

靠容器末端对齐

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/image.5q7p91zlb8.webp

容器内部居中

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/image.5c19i6s7vh.webp

项目大小没有指定时,拉伸占据整个网格容器

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/image.8dx5jeumjo.webp

每个项目两侧的间隔相等。所以,项目之间的间隔比项目与容器边框的间隔大一倍

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/image.3d52ruotyy.webp

首尾贴边,中间均分空间

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/image.5mo3bcalm3.webp

项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔

https://cdn.jsdelivr.net/gh/k34869/picx-images-hosting@master/image.32i8ypbl1s.webp

简写属性 place-content

  • place-content: <align-content> <justify-content>;