💤
前言
本文示例使用UnoCSS,在阅读之前最好对 UnoCSS 有一定了解。
使用了presetUno
和presetWind
两个预设,presetUno
是 UnoCSS 的默认预设,presetWind
是 TailwindCSS 的预设,书写方法及功能更加丰富。
概念
二维网格布局,随意指定网格元素大小位置,比 flex 粒度更细,更适合复杂布局。
网格容器(Grid container)
通过在元素上声明display: grid
或 display: inline-grid
来创建一个网格容器。网格容器中的所有子元素都会成为网格元素。看起来和常规块元素无二致,其实已经能精准随意摆布网格元素
<template>
<div
class="
common-wrapper
grid <!-- [!code ++] -->
">
<div class="common-item">1</div>
<div class="common-item">2</div>
<div class="common-item">3</div>
<div class="common-item">4</div>
<div class="common-item">5</div>
</div>
</template>
<style>
/* style标签上没有使用scope和module,该SFC定义如下两个style全局适用。 /* */
/* 其它SFC文件将不再声明直接引用 /* */
.common-wrapper {
@apply bg-soft-e b-rd-8px py-20px px-24px;
}
.common-item {
@apply b-rd-8px bg-soft-a;
}
</style>
网格轨道(Grid tracks)
网格轨道是网格上任意两条相邻线之间的空间。使用grid-template-columns
和grid-template-rows
属性或简写的grid
属性来定义网格的行和列。
基本示例
为上边示例添加grid-template-columns: 150px 150px 150px;
属性,将网格容器中的子元素被分成了三列,每列宽度为 150px。还能得到的信息:
- 仅指定网格元素宽度,网格元素的高度就由内容决定(其实就是隐式轨道)
- 若网格元素的总宽度小于网格容器的宽度,那么剩余空间将会被留白
<template>
<div
class="
common-wrapper
grid grid-cols-[150px_150px_150px] <!-- [!code ++] -->
">
<div class="common-item">1</div>
<div class="common-item">2</div>
<div class="common-item">3</div>
<div class="common-item">4</div>
<div class="common-item">5</div>
</div>
</template>
fr 单位 (fraction)
grid-template-columns
和grid-template-rows
属性值可以是你知道的任何 CSS 长度单位,此外还有一个特殊的单位fr
,它表示一个网格轨道的剩余空间。 fr
只会和其他fr
按比例分配固额(px rem vw vh %...)之外的剩余空间。
网格容器中的子元素被分成了三列,每列宽度为 1fr,即三列等宽。
<template>
<div
class="
common-wrapper
grid grid-cols-3 <!-- [!code ++] -->
">
<div class="common-item">1</div>
<div class="common-item">2</div>
<div class="common-item">3</div>
<div class="common-item">4</div>
<div class="common-item">5</div>
</div>
</template>
不同比例
网格容器中的子元素被分成了三列,宽度分别为 1fr 2fr 1fr。
<template>
<div
class="
common-wrapper
grid grid-cols-[1fr_2fr_1fr] <!-- [!code ++] -->
">
<div class="common-item">1</div>
<div class="common-item">2</div>
<div class="common-item">3</div>
<div class="common-item">4</div>
<div class="common-item">5</div>
</div>
</template>
绝对单位和 fr 单位混用
正如前边所说,fr
只会和其他fr
按比例分配固额(px rem vw vh %...)之外的剩余空间。
网格容器中的子元素被分成了三列,宽度分别为 1fr 100px 1fr。
<template>
<div
class="
common-wrapper
grid grid-cols-[1fr_100px_1fr] <!-- [!code ++] -->
">
<div class="common-item">1</div>
<div class="common-item">2</div>
<div class="common-item">3</div>
<div class="common-item">4</div>
<div class="common-item">5</div>
</div>
</template>
repeat()函数
repeat()
函数可以重复部分或整个轨道列表。
repeat()
函数重复整个轨道列表,如下两个示例等价。
.example1 {
grid-template-columns: 1fr 1fr 1fr;
}
.example2 {
grid-template-columns: repeat(3, 1fr);
}
repeat()
函数重复部分轨道列表,如下两个示例等价。
.example1 {
grid-template-columns: 100px 1fr 1fr 1fr 100px 1fr 1fr 1fr 1fr;
}
.example2 {
grid-template-columns: 100px repeat(3, 1fr) 100px repeat(4, 1fr);
}
repeat()
函数可以创建一个多轨道模式的重复轨道列表。如下两个示例等价。
.example1 {
grid-template-columns: 1fr 2fr 1fr 2fr 1fr 2fr 1fr 2fr;
}
.example2 {
grid-template-columns: repeat(4, 1fr 2fr);
}
/* 你也可以将示例2中`example1`改成如下写法,依然可行 */
.example3 {
grid-template-columns: repeat(2, 100px 1fr 1fr 1fr) 1fr;
}
显式和隐式网格轨道
grid-template-columns
和grid-template-rows
属性定义的是显式网格轨道,它们定义了网格的结构。如上示例,我们使用grid-template-columns
显式定义了列轨道,但是网格容器会自行创建行轨道,这些行轨道称为 隐式网格轨道。
默认隐式轨道会自动调整大小,取决于它们轨道内的内容
也可以通过grid-auto-rows
和grid-auto-columns
属性来定义隐式网格轨道的大小。
使用grid-auto-rows: 50px
来定义隐式网格轨道的高度为 50px。
<template>
<div
class="
common-wrapper
grid grid-cols-3
grid-auto-rows-50px <!-- [!code ++] -->
">
<div class="common-item">1</div>
<div class="common-item">2</div>
<div class="common-item">3</div>
<div class="common-item">4</div>
<div class="common-item">5</div>
</div>
</template>
minmax()函数
minmax()函数定义一个长宽范围的闭区间。在设置显式网格或定义自动创建的行或列的大小时,可以为其设置一个最小值和最大值。
- 设置显示网格的大小。缩放浏览器,第二列轨道的宽度会在 150px 和 1fr 之间变化。浏览器宽度足够时,第二列与其他两列等宽。反之,第二列最小宽度为 150px。
<template>
<div
class="
common-wrapper
grid
explicit <!-- [!code ++] -->
">
<div class="common-item">1</div>
<div class="common-item">2</div>
<div class="common-item">3</div>
<div class="common-item">4</div>
<div class="common-item">5</div>
</div>
</template>
<style>
.explicit {
grid-template-columns: 1fr minmax(150px, 1fr) 1fr;
}
</style>
- 设置自动创建的行的大小。根据内容多少,自动创建的行高度最小为 50px,最大会根据内容多少自动调整
<template>
<div
class="
grid
implicit <!-- [!code ++] -->
">
<div class="common-item">
1
<div class="h-50px implicit-item">高50px的内容</div>
</div>
<div class="common-item">
2
<div class="h-80px implicit-item">高80px的内容</div>
</div>
<div class="common-item">
3
<div class="h-120px implicit-item">高120px的内容</div>
</div>
<div class="common-item">4</div>
<div class="common-item">5</div>
</div>
</template>
<style>
.implicit {
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(50px, auto);
}
.implicit-item {
@apply b-1 b-solid b-soft-d b-rd-8px;
}
</style>
网格线(Grid lines)
我们先前定义网格时,定义的是网格轨道,不是网格线。网格布局为我们创建带编号的网格线,精确地控制每一个网格元素。如下三列两行网格中,包含四纵和三横网格线。
网格线的编号顺序取决于文章的书写模式,我们是自左到右,编号 1 的网格线在最左边。
根据网格线定位元素
使用grid-column-start
、grid-column-end
和grid-row-start
、grid-row-end
属性配合网格线,可以精确地控制每一个网格元素。
col-start-1
和col-end-3
表示从纵 1 到纵 3,即common-item-1
占用 2 条纵轨道的宽度
row-start-1
和row-end-3
表示从横 1 到横 3,即common-item-1
占用 2 条横轨道的高度
<template>
<div class="common-wrapper grid grid-cols-3 grid-auto-rows-50px">
<div
class="common-item <!-- -->
col-start-1 col-end-3 row-start-1 row-end-3 <!-- [!code ++] -->
">
1
</div>
<div class="common-item">2</div>
<div class="common-item">3</div>
<div
class="common-item <!-- -->
col-start-1 col-end-2 row-start-3 row-end-5 <!-- [!code ++] -->
">
4
</div>
<div
class="common-item
col-start-2 col-end-4 row-start-3 row-end-5 <!-- [!code ++] -->
">
5
</div>
</div>
</template>
简写
/* 以下两个示例等价 */
.example1 {
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 1;
grid-row-end: 3;
}
.example2 {
grid-column: 1/3;
grid-row: 1/3;
}
记录在UnoCSS
中的使用,注意presetUno
预设中不支持中括号语法。需要导入presetWind
预设。
<template>
<div class="common-wrapper grid grid-cols-3 grid-auto-rows-50px">
<div class="common-item">1</div>
<div
class="common-item <!-- -->
col-[2/3] row-[1/3] <!-- [!code ++] -->
">
2
</div>
<div class="common-item">3</div>
<div class="common-item">4</div>
<div class="common-item">5</div>
</div>
</template>
默认跨度(default spans)
上边示例都指明了grid-*-end
,但实际上如果一个元素只延伸一个轨道,可以省略grid-*-end
属性,元素默认延伸一个轨道
如下四种写法完全一致
.example1 {
grid-column-start: 1;
grid-column-end: 2;
}
.example2 {
grid-column-start: 1;
}
.example3 {
grid-column: 1/2;
}
.example4 {
grid-column: 1;
}
总结,你的grid-*-start: x;
和grid-*-end: y;
中如果符合 y - x === 1
,那么可以省略grid-*-end: y;
。
grid-area 属性
可以更进一步,使用grid-area
属性来同时指定grid-*-start
和grid-*-end
四个属性。
grid-area
分别指定grid-row-start
、grid-column-start
、grid-row-end
和grid-column-end
属性的值。
上 左 下 右 的顺序,与常见的padding
、margin
、border
等属性的简写(上 右 下 左)顺序相反
如下两个示例等价
.example1 {
grid-row-start: 1;
grid-row-end: 3;
grid-column-start: 1;
grid-column-end: 3;
}
.example2 {
grid-area: 1/1/3/3;
}
负数网格线
我们可以从最右端的列线和底端的行线开始计数,这两条线会被记为-1
,倒数第 2 条线记为-2
,以此类推。注意,最后一条线是指显示定义的最后一条线,即grid-template-columns
和grid-template-rows
定义的网格,隐式定义的网格不会被考虑在内。
网格间距
网格元素间的列间距和行间距可以使用column-gap
和row-gap
或者简写gap
属性来设置。
gap
属性值可以是任何单位,除了fr
。
row-gap:10px; column-gap:20px;
等价于gap:10px 20px;
表示行间距为 10px,列间距为 20px。
<template>
<div
class="common-wrapper grid grid-cols-3
gap-[10px_20px] <!-- [!code ++] -->
">
<div class="common-item">1</div>
<div class="common-item">2</div>
<div class="common-item">3</div>
<div class="common-item">4</div>
<div class="common-item">5</div>
</div>
</template>
网格区域
// TODO