Grid 布局-容器项
grid 网格布局是一个用于web的二维布局系统, 多行多列.
flex 单行布局则更倾向于一维布局, 一行或者一列.
Grid 重点
只是用表格进行排版哈, 横向内容直接无关联哦.
容器项 | 子项 | 布局应用 |
---|---|---|
定义网格及 fr 单位 | 显式与隐式网格 | 叠加布局 |
合并网格及命名 | 基于线的元素放置 | 多种组合排列布局 |
网格间隙及简写 | 子项对齐方式 | 栅格布局 |
网格对齐方式及简写 | repeat() 与 minmax() | 容器自适应行列布局 |
Grid 容器项属性
因为是二维的, 这个属性的数量就比 flex 要多很多哦, 但其实真正也没有常用那没多啦.
A | B |
---|---|
justify-items | grid-template-rows |
align-items | grid-template-columns |
place-items | grai-template-areas |
justify-content | grid-template |
align-content | grid-row-gap |
place-content | grid-column-gap |
grid-auto-flow | grid-gap |
grid-auto-rows | / |
grid-auto-columns | / |
定义网格和 fr 单位
这个 grid 和 表格 table 其实有点相像.
都是有行 row, 有列 column, 有单元格 cell, 有间隙 gap, 有合并单元格区域 area.
定义网格的行和列维度, 及其网格线名称, 轨道尺寸大小等, 主要用这两个属性:
- grid-template-rows
- grid-template-columns
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>grid-template</title>
<style>
.main {
width: 300px;
height: 200px;
background-color: pink;
/* 用 display 声明容器项是 grid */
display: grid;
/* 声明行列 */
/* grid-template-rows: 100px 100px 100px; */
/* grid-template-columns: 100px 100px 100px; */
/* grid-template-rows: 50px 20% auto; */
/* grid-template-columns: 50px 50px; */
/* fr 分配空间, 类似 flex 的 1, 2, 这种 */
grid-template-rows: 2fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
}
.main div {
background-color: skyblue;
}
</style>
</head>
<body>
<div class="main">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<!-- <div>7</div>
<div>8</div>
<div>9</div> -->
</div>
</body>
</html>
合并网格及命名
grid-template-area
会以命名方式的形式定义网格区域, 即 合并单元格
.
在子项上需要配合 grid-area
进行使用.
- grid-template-rows + grid-template-columns
- grid-template-areas
- grid-area 子项引用
- grid-template = 行列 + 合并区域
实战了一下, 确实通过 grid-template
简写的方式比较高效简洁哦:
grid-template:
"a1 a1 a2" 1fr
"a1 a1 a2" 1fr
"a3 a3 a3" 1fr
/ 1fr 1fr 1fr;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>grid-template-area</title>
<style>
.main {
width: 300px;
height: 200px;
background-color: pink;
display: grid;
/* grid-template-rows: 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
/* 自定义区域名字进行合并 */
/* grid-template-areas:
"a1 a1 a2"
"a1 a1 a2"
"a3 a3 a3"; */
/* grid-template 简写: 右边的 fr 表示行, 最下边的 '/ + fr' 表示列 */
grid-template:
"a1 a1 a2" 1fr
"a1 a1 a2" 1fr
"a3 a3 a3" 1fr
/ 1fr 1fr 1fr;
}
.main div {
background-color: pink;
box-sizing: border-box;
border: 1px solid #000;
}
/* 子项上去使用 */
.main div:nth-of-type(1) {
grid-area: a1;
}
.main div:nth-of-type(2) {
grid-area: a2;
}
.main div:nth-of-type(3) {
grid-area: a3;
}
</style>
</head>
<body>
<div class="main">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
</body>
</html>
网格间隙及简写
主要是在容器项设置子项行列间的间隙大小, 主要这三个, grid-row-gap
, grid-column-gap
, grid-gap
单位了兼容其他容器的布局方式, 比如 flex, 因此我们更推荐使用时将 grid 前缀去掉, 即变成了:
- row-gap
- column-gap
- gap
不论是 grid 还是 flex, 直接用 gap: xx px;
即设置好行列间隙啦.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>grid-gap</title>
<style>
.main {
width: 300px;
height: 200px;
background-color: pink;
display: grid;
grid-template:
"a1 a1 a2" 1fr
"a1 a1 a2" 1fr
"a3 a3 a3" 1fr
/ 1fr 1fr 1fr;
/* 设置行列间距 */
/* row-gap: 20px;
column-gap: 30px; */
/* gap 推荐复合写法, 先行后列 */
gap: 10px 20px;
}
.main div {
background-color: pink;
box-sizing: border-box;
border: 1px solid #000;
}
/* 子项上去使用 */
.main div:nth-of-type(1) {
grid-area: a1;
}
.main div:nth-of-type(2) {
grid-area: a2;
}
.main div:nth-of-type(3) {
grid-area: a3;
}
.main2 {
/* 不给高度让它换行自动撑开 */
width: 300px;
background: pink;
display: flex;
flex-wrap: wrap;
/* 和 grid 一样, 这个 gap 是通用的 */
/* row-gap: 10px;
column-gap: 20px; */
/* 1个值写法, 给行列都设置10的间隙 */
gap: 10px;
}
.main2 div {
width: 100px;
height: 100px;
background-color: skyblue;
}
</style>
</head>
<body>
<div class="main">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
<!-- 和 grid 一样, 这个 gap属性 是通用的 -->
<div class="main2">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</div>
</body>
</html>
网格对齐方式及简写
和 flex 对齐方式类似, 也是通过在容器项中, 设置在自行网格中的对齐方式来进行排版控制, 默认值是 strench
即是拉伸的, 它是设置每个子项相对自身区域的比如 左对齐, 居中, 靠上/靠下等.
容器尺寸小于网格区域尺寸时, 才能看到效果
- justify-items
- align-items
- place-items
也是同上面的 gap 一样, 只要记住它是相对于子项自己区域的排列就好啦, 复合写法测一下就行不用记.
/* 先垂直, 再水平, 不过不用记, 测试一把就知道啦 */
place-items: end center;
还有与之相对于的三个属性, 它是设置整个网格对齐方式, 如左对齐, 居中, 靠上/靠下等.
容器尺寸大于元素尺寸时, 才能看到效果
- justify-content
- align-content
- place-content
同理, 也是只要记住它是相对于整个网格的位置排列 就好啦, 复合写法测一下就行不用记.
/* 先上下, 后左右 不过不用记, 测试一把就知道啦 */
place-content: start end;
当容器尺寸 <= 网格区域尺寸时, place-items
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>place-items</title>
<style>
.main {
width: 300px;
height: 200px;
background-color: pink;
display: grid;
grid-template-rows: 100px 100px 100px;
grid-template-columns: 100px 100px 100px;
/* 当子项尺寸小于分配区域时, 相对于自身分配与的对齐 */
/* start, center, end */
/* justify-items: center;
align-items: start; */
/* 先垂直, 再水平, 不过不用记, 测试一把就知道啦 */
place-items: end center;
}
.main div {
/* 当子项尺寸小于分配区域时, 默认就会填不满容器 */
width: 50px;
height: 50px;
background-color: skyblue;
}
</style>
</head>
<body>
<div class="main">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
<div>9</div>
</div>
</body>
</html>
当容器尺寸 > 网格区域尺寸要大时, place-content
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>place-content</title>
<style>
.main {
width: 500px;
height: 500px;
background-color: pink;
display: grid;
grid-template-rows: 100px 100px 100px;
grid-template-columns: 100px 100px 100px;
/* align-content: start;
align-content: end; */
/* 先上下, 后左右 不过不用记, 测试一把就知道啦 */
/* place-content: start end; */
}
.main div {
width: 50px;
height: 50px;
background-color: skyblue;
}
</style>
</head>
<body>
<div class="main">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
<div>9</div>
</div>
</body>
</html>
但这个容器比整个网格尺寸要大的场景是非常小的, 通常都是会设置为一样的大小, 因此这个 place-content 属性应该是很少用到的啦, 但 place-items
却基本都会用到哦.
隐式网格于显式网格
用来设置在显式网格之外的隐式网格, 如何排列及尺寸大小, 也是对应三个属性:
- grid-auto-fow
- grid-auto-rows
- grid-auto-colums
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>自适应行列排列 grid-auto-flow</title>
<style>
.main {
width: 300px;
height: 300px;
background-color: pink;
display: grid;
/* 设置为 1x3, 多的部分就变成隐式网格了 */
/* grid-template-rows: 100px; */
/* grid-template-columns: 100px 100px 100px; */
/* 默认 row 就是行产生隐式网格, 多出来的会自动折行 */
/* grid-auto-flow: row; */
/* 默认宽度会保持一致, 高度会拉伸, 但可调整 */
/* grid-auto-rows: 100px; */
/* 设置为 3x1, 要设置多的部分按列进行隐式网格折列, 否则会超出容器 */
grid-template-rows: 100px 100px 100px;
grid-template-columns: 100px;
/* 需要手动设置折列了哦, 高度保持一致, 宽度拉伸 */
grid-auto-flow: column;
/* 但宽度也可以调整 */
grid-auto-columns: 100px;
}
.main div {
background-color: skyblue;
border: 1px solid #000;
box-sizing: border-box;
}
</style>
</head>
<body>
<div class="main">
<div>1</div>
<div>2</div>
<div>3</div>
<!-- 隐式网格 -->
<div>4</div>
<div>5</div>
</div>
</body>
</html>
关于 grid 布局, 容器项常用的属性就差不多啦, 看上去很多, 其实也不少, 关键是有个理解和能查询就行啦.