一、 简介
下面代码是该小节所有案例的 DOM 结构
<div className="container">
{Array.from({ length: 9 }).map((v, index) => (
<div className="project" key={index}>
{index + 1}
</div>
))}
</div>
1.1 概念
- 网格布局 (Grid) 是一种强大的 CSS 布局方案
- 它通过将容器划分成一个个网格, 并指定网格的大小、布局、位置、层级实现基本布局
- 它通过设置子项所占的网格多少、位置、排列从而做出各种各样的布局
1.2 和 Flex 布局的区别
- Flexbox 是一种一维布局、更适用于一行或者一列布局
- Grid 是一种二维布局、更适用于多行和多列布局
- Grid 和 flexbox 的一个很大的差异是 Grid 允许我们在二维空间(多行多列)控制元素的位置, flexbox 则不行。但这并不意味着你永远不能在一维布局中使用 Grid, 在需要准确地在一维空间控制元素的尺寸和位置时选择我们依然可以选择使用 Grid
二、 基本术语
2.1 容器、项目
Grid 布局是通过 display: grid
在容器内建立网格格式化上下文, 容器内部子元素
, 称为"项目", 需要注意的是项目只能是容器的顶层子元素
, 不包含项目的子元素,
下面代码: class = 'container'
就是容器, class = 'project'
就是项目
<style>
.container {
display: grid;
}
</style>
<div class="container">
<div class="project"></div>
<div class="project"></div>
<div class="project"></div>
</div>
2.2 行、列
Grid 布局是通过 display: grid
将容器划分为多个网格, 既然是网格那么自然就有了行和列的概念, 如图:
2.3 单元格
行和列的交叉区域, 称为 单元格
(cell) 。正常情况下, n 行和 m 列会产生 n x m 个单元格, 如图:
2.4 网格线
划分网格的线, 被称为 网格线
(grid line) 。水平网格线划分出行, 垂直网格线划分出列。正常情况下, n 行有 n + 1 根水平网格线, m 列有 m + 1 根垂直网格线, 如图是一个 5 * 4 的单元格公产生 6 根垂直网格线 5 根水平网格线
2.5 网格区域
以网格线为界可被划分为一块块区域, 可使用 grid-template-areas
定义每个单元格区域名称
三、 容器属性
3.1 display
display: grid
指定一个容器采用网格布局, 默认容器为块级元素display: inline-grid
指定一个容器采用网格布局, 特别要注意的是容器将被设为行内元素- 注意: 容器设置为网格布局后, 容器子元素 (项目) 的
float
、display: inline-block
、display: table-cell
、vertical-align
和column-*
等属性将失效。
.container {
display: grid;
}
3.2 划分网格: grid-template-columns、grid-template-rows
这两个属性用于定于容器网格大小数量, grid-template-columns
属性定义每一列的列宽、数量, grid-template-rows
属性则定义每一行的行高、数量。
3.2.1 可取值: <length> 非负值的长度大小
下面代码指定了一个三行三列的网格, 列宽和行高都是 100px
, 每个子项默认从左向右进行排列并且占满一个网格。
.container {
width: 300px;
display: grid;
grid-template-rows: 100px 100px 100px;
grid-template-columns: 100px 100px 100px;
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
3.2.2 可取值: <percentage> 非负值且相对于网格容器的百分比
下面代码指定了一个三行三列的网格, 列宽和行高都是 33.33%
, 每个子项默认从左向右进行排列并且占满一个网格。
.container {
width: 300px;
height: 200px;
display: grid;
grid-template-rows: 33.33% 33.33% 33.33%;
grid-template-columns: 33.33% 33.33% 33.33%;
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
3.2.3 可取值: <flex> 非负值, 用单位 fr 来定义网格占剩余可分配空间的比例
下面代码指定了一个三行三列的网格, 第三列宽度为 100px, 第一列和第二列占满所有剩余空间, 并且第二列宽度是第一列的两倍。
.container {
width: 300px;
display: grid;
grid-template-rows: 100px 100px 100px;
grid-template-columns: 1fr 2fr 100px;
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
3.2.4 可取值: auto 自适应宽度
- 下面代码指定了一个三行三列的网格, 第一列和第三列宽度各为
50px
, 第二列自适应(占满所有剩余空间)
.container {
width: 300px;
display: grid;
grid-template-rows: 100px 100px 100px;
grid-template-columns: 50px auto 50px;
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
- 下面代码指定了一个三行三列的网格, 第一列宽度为
50px
, 第二列和第三列自适应(等比例分配剩余空间)
.container {
width: 300px;
display: grid;
grid-template-rows: 100px 100px 100px;
// 等价于: grid-template-columns: 50px 1fr 1fr;
grid-template-columns: 50px auto auto;
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
3.2.5 可取值: minmax(min, max) 定义大小范围, 宽度大于等于 min 值, 并且小于等于 max 值
下面代码指定了一个三行三列的网格, 第一列和第三列设置最小宽度 100px
最大宽度 1fr
, 在容器宽度足够大的情况下列宽等比例缩放, 在容器宽度不足情况下第一列和第三列将固定宽度 100px 第二列宽度自适应
.container {
display: grid;
grid-template-rows: 100px 100px 100px;
grid-template-columns: minmax(100px, 1fr) 1fr minmax(100px, 1fr);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
3.2.6 可取值: repeat() 用于简化重复值
- 下面代码指定了一个三行三列的网格,
grid-template-columns: repeat(3, 100px)
等价于grid-template-columns: 100px 100px 100px
.container {
width: 300px;
display: grid;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 1fr);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
- 下面代码使用
auto-fill
关键字, 该关键字表示自动填充所有剩余空间, 下面代码中repeat(auto-fill, 100px)
将自动创建列(列宽 50px)并占满所有剩余空间
.container {
width: 300px;
display: grid;
grid-template-rows: repeat(3, 100px);
grid-template-columns: 200px repeat(auto-fill, 50px);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
3.2.7 定义网格线名称
在 grid-template-columns
属性和 grid-template-rows
属性里面可通过 [网格线名称 <网格线名称>]
为网格线定义一个或多个名称, 为网格线定义名称方便容器内项目进行布局
下面是几种常见的情景
grid-template-rows: [c1 a1] 100px [c2 a2] 100px [c3] 100px [c4];
repeat(3, [col-start] 250px [col-end]);
3.3 设置网格间距: row-gap、 column-gap、 gap
3.3.1 row-gap: 用于定义行间距
可取值有长度单位、百分比
下面代码指定了一个三行三列的网格并设置了行间距 10px
.container {
width: 300px;
height: 300px;
display: grid;
row-gap: 10px;
grid-template-rows: repeat(3, 1fr);
grid-template-columns: repeat(3, 1fr);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
3.3.2 column-gap: 用于定义行间距
可取值有长度单位、百分比
下面代码指定了一个三行三列的网格并设置了列间距 10px
.container {
width: 300px;
height: 300px;
display: grid;
column-gap: 10px;
grid-template-rows: repeat(3, 1fr);
grid-template-columns: repeat(3, 1fr);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
3.3.3 gap 是 row-gap、 column-gap 的简写属性
- 语法:
gap: <row-gap> <column-gap>
- 注意: 如果只给定一个值, 则表示列间距和行间距相同
下面代码指定了一个三行三列的网格并设置了行间距 10px
、列间距 20px
.container {
width: 300px;
height: 300px;
display: grid;
gap: 10px 20px;
grid-template-rows: repeat(3, 1fr);
grid-template-columns: repeat(3, 1fr);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
3.4 项目排列规则: grid-auto-flow
grid-auto-flow 属性决定容器内子元素排列顺序
3.4.1 可取值: row
该值为默认值, 即 先行后列
, 子元素将先填满第一行, 再开始放入第二行
.container {
display: grid;
grid-auto-flow: row;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 100px);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
3.4.2 可取值: column
按列进行排序, 子元素将先填满第一列, 再开始放入第二列
.container {
display: grid;
grid-auto-flow: column;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 100px);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
3.4.3 可取值: row dense
按行进行排序, 即 先行后列
并且尽可能紧密填满, 尽量不出现空单元格
- 在默认情况下即
grid-auto-flow: row
当第一第二个子元素占用两个单元格将产生下面这样的布局
.container {
width: 300px;
display: grid;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 100px);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
// 为元素设置属性: 后续将会详细说明
.project {
&:nth-child(1),
&:nth-child(2) {
grid-column-end: 3;
grid-column-start: 1;
}
}
- 这种情况下可以使用
row dense
进行排序, 让布局尽可能的紧密、填满所有单元格
.container {
width: 300px;
display: grid;
grid-auto-flow: row dense;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 100px);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
// 为元素设置属性: 后续将会详细说明
.project {
&:nth-child(1),
&:nth-child(2) {
grid-column-end: 3;
grid-column-start: 1;
}
}
3.4.4 可取值: column dense
按列进行排序, 并且尽可能紧密填满, 尽量不出现空单元格
- 使用
column
当第一第二个子元素占用两个单元格将产生下面这样的布局
.container {
width: 300px;
display: grid;
grid-auto-flow: column;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 100px);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
// 为元素设置属性: 后续将会详细说明
.project {
&:nth-child(1),
&:nth-child(2) {
grid-row-end: 3;
grid-row-start: 1;
}
}
- 这种情况下可以使用
column dense
进行排序, 让布局尽可能的紧密、填满所有单元格
.container {
width: 300px;
display: grid;
grid-auto-flow: column dense;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 100px);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
// 为元素设置属性: 后续将会详细说明
.project {
&:nth-child(1),
&:nth-child(2) {
grid-row-end: 3;
grid-row-start: 1;
}
}
3.5 网格系统在容器内布局: justify-content、align-content、place-content
3.5.1 justify-content 在水平方向上的布局
设置网格系统在容器内水平方向上的布局, 可取值有:
-
start(默认值): 水平方向上向左进行靠拢
-
end: 水平方向上向右进行靠拢
-
center: 居中对齐
-
stretch: 自适应拉伸
-
space-around: 单元格周围具有相同空白
-
space-between: 单元格向两端靠齐并且单元格中间具有等比例的空白, 单元格和边界不存在空白
-
space-evenly: 单元格向两端靠齐并且单元格中间具有等比例的空白, 单元格和边界同样具有空白
-
下面代码实现单元格的水平居中对齐
.container {
width: 300px;
height: 300px;
display: inline-grid;
justify-content: center;
grid-template-rows: repeat(3, 50px);
grid-template-columns: repeat(3, 50px);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
- 下面是不用属性所呈现出来的布局
3.5.2 align-content 在垂直方向上的布局
设置网格系统在容器内垂直方向上的布局, 可取值有:
-
start(默认值): 垂直方向上向上进行靠拢
-
end: 垂直方向上向下进行靠拢
-
center: 居中对齐
-
stretch: 自适应拉伸
-
space-around: 单元格周围具有相同空白
-
space-between: 单元格向两端靠齐并且单元格中间具有等比例的空白, 单元格和边界不存在空白
-
space-evenly: 单元格向两端靠齐并且单元格中间具有等比例的空白, 单元格和边界同样具有空白
-
下面代码实现单元格的垂直居中对齐
.container {
width: 300px;
height: 300px;
display: inline-grid;
align-content: center;
grid-template-rows: repeat(3, 50px);
grid-template-columns: repeat(3, 50px);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
- 下面是不用属性所呈现出来的布局
3.5.3 place-content 简写属性
- place-content 属性是 justify-content、align-content 的简写属性
- 语法:
place-content: <align-content> <justify-content>
- 注意: 如果只给定一个值, 则表示水平、垂直方向上单元格具有相同的布局
下面代码实现单元格水平垂直居中布局
.container {
width: 300px;
height: 300px;
display: inline-grid;
place-content: center;
grid-template-rows: repeat(3, 50px);
grid-template-columns: repeat(3, 50px);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
3.6 单元格内项目布局: justify-items、align-items、place-items
3.6.1 justify-items 水平布局
设置单元格内项目在水平方向上的布局
- start(默认值): 水平方向上向左靠拢
- end: 水平方向上向右靠拢
- center: 居中对齐
- stretch: 自适应拉伸
下面代码实现单元格内项目水平居中布局
.container {
width: 300px;
display: grid;
justify-items: center;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 100px);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
width: 50px;
height: 50px;
background: rgb(random(255), random(255), random(255));
}
}
3.6.2 align-items 垂直布局
设置单元格内项目在垂直方向上的布局
- start(默认值): 垂直方向上向上靠拢
- end: 垂直方向上向下靠拢
- center: 居中对齐
- stretch: 自适应拉伸
下面代码实现单元格内项目垂直居中布局
.container {
width: 300px;
display: grid;
align-items: center;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 100px);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
width: 50px;
height: 50px;
background: rgb(random(255), random(255), random(255));
}
}
3.6.3 place-items 简写属性
- place-items 属性是 justify-items、align-items 的简写属性
- 语法:
place-items: <align-items> <justify-items>
- 注意: 如果只给定一个值, 则表示水平、垂直方向上具有相同的布局
下面代码实现单元格内项目水平垂直居中布局
.container {
width: 300px;
display: grid;
place-items: center;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 100px);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
width: 50px;
height: 50px;
background: rgb(random(255), random(255), random(255));
}
}
3.7 容器自动划分网格设置 grid-auto-columns、grid-auto-rows
grid-template-columns
属性和grid-template-rows
属性用用于定义容器网格行和列的数目和宽度- 在网格有限的情况下, 如果项目过多系统将自动创建新的行或列,
grid-auto-columns
grid-auto-rows
则用于定义系统自动创建网格时网格的列宽和行宽 grid-auto-columns
grid-auto-rows
属性值和grid-template-columns
类似
下面代码指定了一个二行三列的网格, 多余的项目将自动创建单元格并设置行宽为 50x
.container {
width: 300px;
display: grid;
grid-template-rows: repeat(2, 100px);
grid-template-columns: repeat(3, 100px);
background: rgba($color: #000, $alpha: 0.04);
grid-auto-rows: 50px;
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
3.8 设置网格区域 grid-template-areas
grid-template-areas
为网格中单元格划分区域,一个区域可包含一个或多个单元格- 如果某些单元格不需要利用, 则使用点
.
表示 - 划分好的区域, 可用于项目布局
下面代码定义了区域 a
和区域 b
, 每个区域都包含两个单元格, 其余单元格不被利用
.container {
width: 300px;
display: grid;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 100px);
background: rgba($color: #000, $alpha: 0.04);
grid-template-areas:
'a a .'
'b b .'
'. . .';
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
3.9 grid-template、grid 简写属性
-
grid-template
属性是grid-template-columns
grid-template-rows
和grid-template-areas
这三个属性的合并简写形式 -
grid
属性是grid-template-rows
grid-template-columns
grid-template-areas
grid-auto-rows
grid-auto-columns
grid-auto-flow
这六个属性的合并简写形式。
四、 项目属性
4.1 设置项目边界 grid-column-start、grid-column-end、grid-row-start、grid-row-end
四个属性用于定义项目的位置, 属性值可以是网格线索引、网格线名称、关键词 span
- grid-column-start: 决定项目左边框所在的垂直网格线
- grid-column-end: 决定项目右边框所在的垂直网格线
- grid-row-start: 决定项目上边框所在的水平网格线
- grid-row-end: 决定项目下边框所在的水平网格线
下面代码, 使用网格线索引为第一个项目设置左右边框位置, 使用网格线名称设置第一个项目上下边框位置
.container {
width: 300px;
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: [a1] 100px [a2] 100px [a3] 100px [a4];
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
.project:nth-child(1) {
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: a1;
grid-row-end: a3;
}
下面代码使用 span
关键字为第一个项目设置边框位置, span
关键字定义项目跨度
.container {
width: 300px;
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: [a1] 100px [a2] 100px [a3] 100px [a4];
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
.project:nth-child(1) {
grid-column-start: span 2;
grid-row-start: span 2;
}
4.2 两个简写属性 grid-column、grid-row
grid-column
属性是grid-column-start
和grid-column-end
简写形式, 两个属性值间用/
分隔grid-row
属性是grid-row-start
属性和grid-row-end
简写形式, 两个属性值间用/
分隔
.container {
width: 300px;
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: [a1] 100px [a2] 100px [a3] 100px [a4];
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
.project:nth-child(1) {
grid-row: 1 / 3; // 等价于 grid-row: 1 / span 2;
grid-column: 1 / 3; // 等价于 grid-column: 1 / span 2;
}
4.3 指定项目所处区域 grid-area
grid-area 指定项目所处的区域
.container {
width: 300px;
display: grid;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 100px);
background: rgba($color: #000, $alpha: 0.04);
grid-template-areas:
'a a .'
'a a .'
'. . .';
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
background: rgb(random(255), random(255), random(255));
}
}
.project:nth-child(1) {
grid-area: a;
}
4.4 项目在单元格内布局 justify-self、align-self、place-self
4.4.1 justify-self 水平布局
定义当前项目在单元格内水平方向上的布局
- start(默认值): 水平方向上向左靠拢
- end: 水平方向上向右靠拢
- center: 居中对齐
- stretch: 自适应拉伸
下面代码实现项目在其单元格内水平居中
.container {
width: 300px;
display: grid;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 100px);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
width: 50px;
height: 50px;
background: rgb(random(255), random(255), random(255));
}
}
.project:nth-child(1) {
justify-self: center;
}
4.4.2 align-self 垂直布局
定义当前项目在单元格内垂直方向上的布局
- start(默认值): 垂直方向上向上靠拢
- end: 垂直方向上向下靠拢
- center: 居中对齐
- stretch: 自适应拉伸
下面代码实现项目在其单元格内垂直居中
.container {
width: 300px;
display: grid;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 100px);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
width: 50px;
height: 50px;
background: rgb(random(255), random(255), random(255));
}
}
.project:nth-child(1) {
align-self: center;
}
4.4.3 place-self 简写属性
place-self
属性是 align-self
属性和 justify-self
属性的简写, 语法: place-self: <align-self> <justify-self>
。
注意: 如果省略第二个值, place-self
属性则表示水平垂直具有相同布局
下面代码实现项目在其单元格内水平、垂直居中
.container {
width: 300px;
display: grid;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 100px);
background: rgba($color: #000, $alpha: 0.04);
}
@for $index from 1 to 10 {
.project:nth-child(#{$index}) {
width: 50px;
height: 50px;
background: rgb(random(255), random(255), random(255));
}
}
.project:nth-child(1) {
place-self: center;
}