Flex+Grid 布局
FlexBox 基础
使用 display: flex 开启 Flex 布局
方向 Direction
Direction 定义了主轴的方向,决定项目是水平排列还是垂直排列的。
flex-direction 默认值为 row,即默认以横排列(左右排)
此时,我们的主轴就是从左到右。此时所有的项目(item)会以左到右依次排列。与这条主轴垂直的,即是交叉轴,交叉轴为从上到下排列
当 flex-direction 值为 column 时,主轴是垂直的,其排列为从上到下
此时的交叉轴则是打横的,其排列为从左到右
主轴对齐 Justify Content
justify-content 管理项目在主轴上的对齐和分布。
主轴值分为两大类
- 对齐类
- flex-start(默认): 向起点对齐
- flex-end: 向终点对齐
- center: 居中对齐
- 分布类
- space-between: 两端对齐,中间平分
- space-around: 项目两侧间距相等,所以项目与项目之间的距离,是项目与边缘的两倍
- space-evenly: 所有间距完全相等,平均等分相距距离
交叉轴对齐 align-item
align-items 管理项目在交叉轴上的对齐方式。
- stretch(默认):项目被拉伸以填满交叉轴;如果项目没有设置高度时,会被自动拉伸到容器的高度。
-
- flex-start: 向交叉轴的起点对齐
- flex-end: 向交叉轴的终点对齐。
- center: 在交叉轴中整体居中。
空间分配机制
几个子元素在容器中,有的被拉伸,有的被压缩,但最终尺寸似乎难以预测。
基本认识
Flex 布局除了对项目进行方向性排列的控制外,也会对项目的大小进行管理,如果一个页面中的空间,不足以存下这些项目时,这些项目应该要如何处理?是统一以比例压缩,还是只以某个项目进行压缩,还是进行重新排序等等。相对比如果项目不能完全填充页面中的空间时,又要怎样的方式进行分配空间。
其总体计算可以参考以下图的流程:
flex-basis 元素最初定义大小
基准宽度:空间分配的计算起点。元素的“理想”尺寸
也就是元素最初希望的大小,它在设置里有三种值,
基准值是用于参与空间扩大和缩小时,对元素的比例缩放有关系的,谁要的基准值越多,缩放比例也越大。
- auto :元素最初大小由它的内容所撑开的大小决定(也可以是css控制大小的决定)
- xxxpx : 指定元素特定的初始空间占用值,如果设置100px,则认为这个元素一开始就是100px大
- 0: 指这个元素初始大小是0
flex-grow 元素扩大比例
扩张因子:当容器有剩余空间时,决定如何“瓜分”这些空间
这是假设如果项目放在页面中后,依然有剩余空间的情况下的设置项。
案例:
- 容器宽度 600px,空间充足的情况
- Flex 属性值说明:flex: flex-grow | flex-shrink | flex-basis
- 子项A: flex: 1 1 0; (基准宽度0, 空间扩充比例为 1, 空间收缩比为 1)
- 子项B (本身内容占 200px): flex: 2 1 auto; (基准宽度为自动, 空间扩充比例为 2, 空间收缩比为 1)
- 子项C: flex 1 1 100px; (基准宽度100px, 空间扩充比例为 1, 空间收缩比为 1)
1.计算基准宽度,已知【A】定义宽基准为0,【B】定义宽基准为自动,因为自身有内容200px所以基准为200px, 【C】定义固定宽基准为100px
总基准宽 = 0 + 200 + 100 = 300px
2.计算剩余空间,目前容器总宽有 600px
剩余空间 = 600px - 300px = 300px
因此当前空间是充足的,所以开始计算 grow 值。
3.计算总的 grow 值,【A】定义为 1,【B】定义为 2,【C】定义为1
总Grow = 1 + 2 + 1 = 4
所以
【A】在总的空间中占有比例为 A的分配比例 = 1 / 4 = 0.25
【B】在总的空间中占有比例为B的分配比例 = 2 / 4 = 0.5
【C】在总的空间中占有比例为C的分配比例 = 1 / 4 = 0.25
4.计算每个项目额外空间占用的空间位置为:剩余空间按 grow 比例分配
【A】占有: A的占有空间 = 300px * 0.25 = 75px
【B】占有: B的占有空间 = 300px * 0.5 = 150px
【C】占有: C的占有空间 = 300px * 0.25 = 75px
5.计算最终的每个项目的占用空间大小:申请的基准空间 + 额外提供的空间
【A】占有: A最终占有空间 = 0 + 75px = 75px
【B】占有: B最终占有空间 = 200 + 150px = 350px
【C】占有: C最终占有空间 = 100 + 75px = 175px
flex-shrink 元素缩小比例
收缩因子:当容器空间不足时,决定如何“分摊”超出的部分。
这是假设如果项目放在页面中后,页面没有更多的空间来存放这些项目时的情况。
案例:
- 容器宽度 400px,空间不足的情况
- Flex 属性值说明:flex: flex-grow | flex-shrink | flex-basis
- 子项A : flex 1 1 300px (A 要求至少占有300px,如果空间不足按比例1来收缩)
- 子项B : flex 1 2 200px (B 要求至少占有200px,如果空间不足按比例2来收缩)
1.计算总的基准宽度:基准宽度 = 300px + 200px = 500px
2.计算剩余的基准宽度:基准宽度 = 400px - 500px = -100px ,显然此时是空间不足以分配了。
因此当前空间是不足的,所以开始计算 shrink 值。
3.计算收缩比例分配收缩量
【A】的权重值为:权重 = 300px * 1 = 300
【B】的权重值为:权重 = 200px * 2 = 400
总权重值为: 300 + 400 = 700
【A】的压缩象素为: 300 / 700 * 100% = 42.86px
【B】的压缩象素为:400 / 700 * 100% = 57.14px
注意:实际上就是把这多出的空间,用它们自身的基准和权重在总体项目的比例来分配出需要收缩的量。
4.最总项目的实际宽度计算为
【A】的最终宽度为:300px - 42.86px = 257.14px
【A】的最终宽度为:200px - 57.14px = 142.86px
flex-wrap 是否换行
对于项目在一行中时,容器的宽度会直接影响项目的大小,如果容器的空间不足以容纳项目时,项目就会被无限制的压缩,甚至超出容器边界。
对于这一问题,flex-wrap 是用于控制项目当出现压缩到要超出容器时,是否换行的属性,默认值是 no warp 不换行。
- no wrap 绝不换舻,强行挤在同一行
- wrap 空间不足时,自动将项目移到新行
- wrap-reverse 与 wrap 类似,但新行会出现在已有行的上方
wrap换行规则。
wrap-reverse 时的规则
align-content 换行间距
对于 flex-wrap 中设置的换行情况,在项目换行时,align-items 是只对一行项目的排列方式,对于换行的排列是不负责的,所以需要使用 align-content 来做换行的排列。
有如下几个属性值:
- flex-start: 队列紧贴最上方,从上往下堆排
flex-end:队列紧贴最下方,从下往上堆排
- center:队列整体居中,从上往下堆排,但保持整体居中
- space-between:队列头和尾会紧贴边缘,多出的空间距离给到中间的行平分
- space-around:把队列中的每一行都设置同等的空间距离,所以中间行间距会是边缘行距边缘间距的2倍
- stretch:如果每个项目都不设置高度的情况下,会使队列中所有项目高度拉伸填满所有空间
align-self 单元素设置
align-self 是用于控制单个元素的独特对齐方式的属性。
对于我们使用的 align-items 属性,它只会把结构中的所有元素都以一种统一的方式进行排列,但是如果我想单独对某一个元素进行另类的对齐,就需要使用 align-self了,当设置了align-self 属性值后,align-items 属性会失效。
值与 align-items 一样
- auto: 跟父元素的 align-items 的设置相同(就是align-self不起作用)
- flex-start: 在交叉轴的起点对齐
- flex-end: 在交叉轴的终点对齐
- center: 在交叉轴上居中对齐
- baseline: 基于项目的第一行文字的基线对齐,对于文字对不齐的比较有用
- stretch: 若元素没有设置高度或为 auto 时,会拉伸整个容器高度。
示例效果:
order 项目排序
它允许我们仅通过css来调整Flex子项的视觉排列顺序,无需改动html源码
- 所有子项的order默认都为 0
- 浏览器根据 order 值的大小排序,数值越小,排列越靠前
- order 值可以是负数
基础三栏布局
1.构建三栏布局
<div class="container">
<div class="left">左边栏</div>
<div class="right">
<div class="top">上顶层</div>
<div class="middle">中间内容层</div>
</div>
</div>
2.使用flex布局定义其空间:
.container {
// 外层设置为 flex 布局
display: flex;
// 使用从左到右排
justify-content: flex-start;
// 设置从上到下排,没有设置高度的会自动填充高度
align-items: stretch;
padding: 10px;
.left {
// 设置左边固定大小为 300 不允许缩
max-width: 300px;
// 设置左边不进行缩进
flex-shrink: 0;
}
.right {
// 设置右边为扩张层
flex-grow: 1;
// 设置右边扩张最大只能到 1000px
max-width: 1000px;
// 设置使其子元素也为 flex
display: flex;
// 设置顶部和内容为上下排列
flex-direction: column;
// 设置从上往下排,中间没空距
justify-content: flex-start;
.top {
height: 100px;
}
.middle {
flex-grow: 1;
}
}
}
Grid 布局
rf 单位说明
在css中,有多种单位体系,最常用的单位分为三类
- 固定单位
- px、em、rem
- 可以提供可预测的,绝对的尺寸
- 适用于固定侧边栏、导航栏等场景
- 相对单位
- %、vw、vh
- 相对于容器或视口的尺寸
- 善于创建与父容器紧密关联的布局
- 自动单位
- auto
- 由内容决定尺寸
- 遵循内容优先原则
在Grid 布局中,有一个专用的单为 fr
- Grid 面局最具特色的单位
- 1fr 代表在网格中“可用空间”的一份
图示fr的含意:
1.若在一个容器中,有其它单位占位的,则先扣除其它单位的空间后,再计算,剩下的就是fr
2.若在一个容器中设置2个以上的方格,每个方格各有自己的fr,则会按比例分配:
3.当在一个容器中,有其它的单位占位,也设置了方格之间的间距(gap)时,会先扣除其它单位的占位,和间距后再计算方格空间比例:这样的好处是,当可变量(如间距改变后),不需要人工重新计算每个方格的大小。
grid-template-columns 定义方格列
Grid 的思维是把一个页面,当作一个大方格,我们的工作是,需要在这个大方格当中,切分多少行,切分多少列,然后我们的内容就放在这些行和列构成的格子中。
要定义多少列,我们可以使用 grid-template-columns 定义。它可以接收一个数组,数组多少个成员就是定义多少列。
示例:
div{
// 定义布局为方格布局
display: grid;
/*
设置列数
5列,第一列200px,最后一列200px
剩下的切成4份,第二列占一份,第三列占一份,第四列占2份
*/
grid-template-columns: 100px 1fr 1fr 2fr 200px;
}
grid-template-rows 定义方格行
通过定义方格列,可以把一个页面分成多少列,再通过定义方格行,形成一个个方格大小
/*
定义三个方格行,第一行20px,第二行30px,第三行占有剩下所有空间
*/
grid-template-rows: 20px 30px auto;
gap 方格间距控制
我们还可以设置每个方格的间距,方格的间距会占用页面空间,所以fr单位可以帮我们扣掉方格间距后再计算格子大小:
div{
// 定义布局为方格布局
display: grid;
/*
设置列数
5列,第一列200px,最后一列200px
剩下的切成4份,第二列占一份,第三列占一份,第四列占2份
*/
grid-template-columns: 100px 1fr 1fr 2fr 200px;
/*
定义三个方格行,第一行20px,第二行30px,第三行占有剩下所有空间
*/
grid-template-rows: 20px 30px auto;
/*
设置方格间距为10px,本例中设置了5列,则有4列会有间距,共占40px
*/
gap: 10px;
}
间距家族有三个属性:
- column-gap : 设置列与列之间的间距
- row-gap : 设置行与行之间的间距
- gap : 同时设置行和列的间距
- 格式 gap: 行间距 列间距
- 格式 gap: 行列间距
repeat 函数创建列
grid-template-columns 中创建多少列,我们就要传入多少个参数值,那如果列数多的情况下,我们就需要传入好多参数,repeat 可以帮我们批量创建:
// 设置10列,每列占用1份空间,即每列 10%总页面大小
grid-template-columns: repeat(10, 1fr);
精确布局
定义列的开始位置和行开始位置
通俗的讲就是,定义我们的内容,应该是从第几行和第几列开始放置(在一个片网格中,不一定内容是从第一行第一列的格子开始的)
// 定义内容会存放于页面中第一列到第三列之间
grid-column-start: 1;
grid-column-end: 3;
// 定义内容会存放于页面中第二列到第四列之间
grid-row-start: 2;
grid-row-end: 4;
我们可以使用简单写法:
// 定义内容会存放于页面中第一格线到第三格线之间
grid-column: 1 / 3;
// 定义内容会存放于页面中第二格线到第四格线之间
grid-row: 2 / 4;
若我们不知道页面中被划分了多少个格子,我们可以使用 负数 定义,-1表示倒数第一行,-2表示倒数第二行
// 定义内容会存放于页面中第一格线到倒数第一格线
grid-column: 1 / -1;
// 定义内容会存放于页面中第二格线到倒数第二格线
grid-row: 2 / -2;
案例:通过下面的颜色的格子区分,我们可以看出有三个item,每个item占有一定的位置的格子
通过分析上面的颜色,
- item1
- 占据的列位置是 列线1~列线5
- 占据的行位置是 行线1~行线3
- item2
- 占据的列位置是 列线5~列线8(或-1)
- 占据的行位置是 行线1~行线6(或-1)
- item3
- 占据的列位置是 列线1~列线5
- 占据的行位置是 行线3~行线5
因此我们可以在css中这样定义:
item1 {
grid-column: 1 / 5;
grid-row: 1 / 3;
background-color: pink;
}
item2 {
grid-column: 5 / -1;
grid-row: 1 / -1;
background-color: greenyellow;
}
item3 {
grid-column: 1 / 5;
grid-row: 3 / 5;
background-color: orange;
}
span 动态占用网格
从上面的章节我们可以简单的通过定义开始的列线,和结尾的列线,来定义一块内容应占有页面中多少网格。
但是有时我们不想关心内容块要从那里占到那里,而是希望它总是要用多少个网格
比如我们的 item1 不关心占用网格线A~网格线B,只关心 item1 从网格线A开始,需要占用 3个网格。
我们可以使用上面的方式来定义
// 从网格线 1 占到 网格线 4
grid-column: 1 / 4;
但是我们可以使用 span 关键字来告诉它,我们只关心内容块占有多少块,而不是占有多少格到多少格
// 从网格线1开始,必须占有3个格子空间
grid-column: 1 / span 3;
利用媒体查询,我们还能运态切换内容块的占用情况:
item1 {
// 从网格线1开始,必须占有3个格子空间
grid-column: 1 / span 3;
}
// 当屏小于 768px 时,使 item 开始占有4个格子空间
@media (min-width: 768px) {
item1 {
grid-column: 1 / span 4;
}
}
在某些情况下,我们还能不声明内容块从那条网格线开始,而是让浏览器自动分配摆方位置:
// 不要管我从那条格线开始放,浏览器看着放,反正给我4列3行的空间就行
item1 {
grid-column: span 4;
grid-row: span 3;
background-color: pink;
}
命名网格布局
在html中定义好所有结构的名称,我们就可以利用这些名称来做统一化布局了,甚至在小屏下使用媒体查询方式来重新排板布局
我们来看一下css代码:
// 在一个容器中包含 header, nav, content, aside, footer 几个区域
.container {
display: grid;
// 声明这些元素统一化使用网格布局
grid-template-areas:
"header"
"nav"
"content"
"aside"
"footer";
// 以上这些元素统一占有一列份额的空间
grid-template-columns: 1fr;
// 格子相距 10px
gap: 10px;
}
当页面太小时,我们还能通过媒体查询来改变它们的布局
@media (min-width: 768px) {
container {
grid-template-areas:
"header header" // 这一二列依然header全占
"nav content" // 这一列放 nav 第二列放 content
"aside aside" // 这一二列依然 aside 全占
"footer footer"; // 这一二列依然 footer 全占
}
// 以上的两列的空间占用分别是 200px 和 1fr
grid-template-columns: 200px 1fr;
}
容器级对齐
所谓的容器级对齐,是指整门页面中的所有网格之间的对齐。
容器级对齐属性与Flex类似
- justify-content: 控制网格在行轴上的对齐
- align-content: 控制网格在列轴上的对齐
属性值与 Flex 也一样:
- start: 网格在容器的起始位置对齐
- end: 网格在容器的结束位置对齐
- center: 网格在容器中居中
- space-around: 轨道均匀分布,首尾距边缘为轨道间距的一半
- space-between: 轨道均匀分布,首尾轨道紧贴容器边缘
- space-evenly: 完全均匀分布
单元格内对齐
对于每个网格内,也可以做对齐,单元格对齐有两种定义
- 容器统一定义
- justify-items: 控制所有项目在各自单元格内的水平对齐
- align-items: 控制所有项目在各自单元格内的垂直对齐
- 项目独立定义:
- justify-self: 覆盖 justify-items 属性,控制单个项目的水平对齐
- align-self: 覆盖 align-items 属性,控制单个项目的垂直对齐
属性值:
- start: 项目对齐到单元格的起始边缘
- end: 项目对齐到单元格的结束边缘
- center: 项目在单元格内居中
- stretvh(默认值): 项目拉伸填满整个单元格空间
响应式网格布局
minmax() 函数:为轨道设定弹性边界
在响应式面局中,我们需要让元素既能灵活伸缩,又不会在极端情况下导致内容失真
- min: 轨道的最小尺寸,保证内容的可读性
- max: 轨道的最大尺寸,通常使用 1fr 等弹性单位
案例:在设定的三列中,使两列弹性的控制其网格大小
.container {
display: grid;
// 创建三列网格,第一列最小不小于200px 最大占一份额空间
// 第二列固定 500px 空间
// 第三列最大 1份额空间,最小100px空间
grid-template-columns: minmax(200px, 1fr) 500px minmax(100px, 1fr);
}
auto-fit vs auto-fill : 两种自动布局模式
这两个关键字都会不断的创建列,直到空间用光为止,但处理“剩余空间”的方式不同
auto-fill:保守填充
- 1.用尽可能多的轨道填充容器
- 2.保留空轨道作为空白区域
- 3.适合希望保持轨道尺寸严格的场景
案例:
- 总空间大小 900px
- 轨道最小宽度 200px, 最大 1fr
- 实际网格项 2 个
对于 fill 来说,它会认为,每个网格项最小200px空间,所以:
900px / 200px = 4.5 会给页面分成4个网格,但还有0.5个网格的空间,会平均分给这4个网格,
最终每个网格不小为 200px + 100 / 4 = 225px
当有两个网格项时,只会填充这两个网格的空间,留空剩下两个网格的空间,如下图:
auto-fit: 适应填满
- 1.创建轨道后,折叠空轨道
- 2.让现有网格项拉伸填满容器
- 3.适合构建自适应卡片风格
案例:
- 总空间大小 900px
- 轨道最小宽度 200px, 最大 1fr
- 实际网格项 2 个
对于 fit 来说,它会认为,每个网格项最小200px空间,所以:
900px / 200px = 4.5 会给页面分成4个网格,每个网格本应 225px,
但是因为只需要两个网格占用空间,会把剩余的两个空白网格空间调为0px以给其它网格使用:

















flex-end:队列紧贴最下方,从下往上堆排
















共有 0 条评论