Vuetify 系列 - 关于的栅格系统

概述

Vuetify 的栅格系统主要由 3 个组件实现,分别是 v-containerv-layoutv-flex,将 viewport 分成了 12 块,并且根据不同的设备分辨率,预设了多种属性,比如 xs、xl,给内容在不同分辨率下的显示尺寸进行便捷地设置。

栅格系统中还有一个 v-spacer 组件,用于在组件间加入”很宽的”间隔,比如我要在顶栏左侧显示标题,右侧显示按钮,中间的宽度不定,这时候就可以使用 v-spacer 进行占位。要注意的是,v-spacer 必须在 flex 容器中使用才能起到占位的效果,否则他的效果会是换行

Viewport Breakpoints

直译是视口断点,但我觉得应该翻译成视口别名,内容为:

设备尺寸 别名 尺寸范围
更小的设备(手机) xs < 600px
小型设备(平板) sm 600px 至 960px
中型设备(笔记本) md 960px 至 1264px(1280 - 16)
大型设备(台式显示器) lg 1264px 至 1904px(1920 - 16)
更大的设备(4k或宽显示器) xl > 1904px

这个属性用于设置 item 在不同设备下的表现,比如 xs4 表示在手机等更小的设备中,item 应该占容器的 1/3,因为容器要分成 12 块。

Gutter

指的是元素的间距基准 gutter 为 24px,根据 viewport breakpoints 的不同,Vuetify 预设了 5 个与其相对应的 gutter,分别是:

Viewport breakpoints 间距
xs 2px(基准值 / 12)
sm 4px(基准值 / 6)
md 8px(基准值 / 3)
lg 16px(基准值 * 2 / 3)
xl 24px

参考链接

API

官网的 API 只有英文版,中文文档已经很久没更新了,就在这里简单翻译一下吧。

v-container

Props 说明 类型 默认值
align-baseline 一条轴线的交叉轴基线对齐,align-items: baseline Boolean false
align-center 一条轴线的交叉轴居中对齐,align-items: center Boolean false
align-content-center 多条轴线的交叉轴居中对齐,align-content: center Boolean false
align-content-end 多条轴线的交叉轴末尾对齐,align-content: end Boolean false
align-content-space-around 多条轴线的交叉轴空格环绕,align-content: space-around Boolean false
align-content-space-between 多条轴线的交叉轴空格相间,align-content: space-between Boolean false
align-content-start 多条轴线的交叉轴开头对齐,align-content: start Boolean false
align-end 一条轴线的交叉轴末尾对齐,align-items: end Boolean false
align-start 一条轴线的交叉轴开头对齐,align-items: start Boolean false
d-{type} 设置 container 的 display,比如 d-flex Boolean false
fill-height 设置 flex 定位,将高度调整为 100%,一条轴线时,让交叉轴居中 Boolean false
fluid 设置最大宽度为 100% Boolean false
grid-list-{xs through xl} 用于设置子代 v-layout 中 v-flex 的外边距,规则参考下文 Boolean false
id 通过组件设置 DOM 的 id String undefined
justify-center 主轴居中对齐,justify-content: center Boolean false
justify-end 主轴末尾对齐,justify-content: end Boolean false
justify-space-around 主轴空格环绕,justify-content: space-around Boolean false
justify-space-between 主轴空格相间,justify-content: space-between Boolean false
justify-start 主轴开头对齐,justify-content: start Boolean false
tag 指定根元素的标签名 String div

grid-list 规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
&.grid-list
@each $size, $gutter in $grid-gutters
&-#{$size}
.layout
.flex
padding: $gutter / 2

.layout:only-child
margin: -$gutter / 2

.layout:not(:only-child)
margin: auto (-$gutter / 2)

*:not(:only-child)
.layout:first-child
margin-top: -$gutter / 2

.layout:last-child
margin-bottom: -$gutter / 2

v-layout

Props 说明 类型 默认值
align-baseline 一条轴线的交叉轴基线对齐,align-items: baseline Boolean false
align-center 一条轴线的交叉轴居中对齐,align-items: center Boolean false
align-content-center 多条轴线的交叉轴居中对齐,align-content: center Boolean false
align-content-end 多条轴线的交叉轴末尾对齐false,align-content: end Boolean false
align-content-space-around 多条轴线的交叉轴空格环绕,align-content: space-around Boolean false
align-content-space-between 多条轴线的交叉轴空格相间,align-content: space-between Boolean false
align-content-start 多条轴线的交叉轴开头对齐,align-content: start Boolean false
align-end 一条轴线的交叉轴末尾对齐,align-items: end Boolean false
align-start 一条轴线的交叉轴开头对齐,align-items: start Boolean false
column 将垂直方向设为主轴,flex-direction: column Boolean false
d-{type} 设置 container 的 display,比如 d-flex Boolean false
fill-height 设置 flex 定位,将高度调整为 100%,一条轴线时,让交叉轴居中 Boolean false
id 通过组件设置 DOM 的 id String undefined
justify-center 主轴居中对齐,justify-content: center Boolean false
justify-end 主轴末尾对齐,justify-content: end Boolean false
justify-space-around 主轴空格环绕,justify-content: space-around Boolean false
justify-space-between 主轴空格相间,justify-content: space-between Boolean false
justify-start 主轴开头对齐,justify-content: start Boolean false
reverse 将主轴方向反转,flex-direction: xxx-reverse Boolean false
row 将水平方向设为主轴,flex-direction: row Boolean true
tag 指定根元素的标签名 String div
wrap 当内容宽度超过 100% 时自动换行,flex-wrap: wrap Boolean false

v-flex

Props 说明 类型 默认值
(size)(1-12) 在不同的 viewport breakpoint 下所占的格子 Boolean false
align-self-baseline flex item 基线对齐,align-self: baseline Boolean false
align-self-center flex item 居中对齐,align-self: center Boolean false
align-self-end flex item 末尾对齐,align-self: end Boolean false
align-self-start flex item 开头对齐,align-self: start Boolean false
grow 设置拉伸比例,flex-grow Boolean false
id 通过组件设置 DOM 的 id String undefined
offset-(size)(0-12) 在指定 vb* 下,向右偏移 n 格,通过 margin-left 实现 Boolean false
order-(size)(1-12) 在指定 vb* 下,flex item 的位置,通过 order 实现 Boolean false
shrink 设置缩放比例,flex-shrink Boolean false
tag 指定根元素的标签名 String div

vb 为 viewport breakpoint 缩写。

如何理解

网格系统将页面分成了 12 格,v-container 作为一个容器根元素,v-layout 表示容器内的一行或一列,在设置行或列后可以通过 v-flex 填充网格内容。

如果把网格系统看作是表格的话,v-container 相当于 table,v-layout 相当于 tr,而 v-flex 则相当于 td。

从样式的角度来看,v-container 本身不是 flex 容器,他只是一个普通的 block 元素(默认情况),只声明了 margin: autowidth: 100%

v-layout 才是一个 flex 容器,并且设置了 nowrap,也就是说在子项空间不够时也不会换行显示

v-flex 是一个 flex item,设置了 flex: 1 1 auto存在剩余空间时会拉伸,剩余空间不足时会缩放,每个 v-flex 占用的格子通过 {viewpoint breakpoint}{point} 的格式设置,比如 xs4 表示在小于 600px 的设备上占用 4 格(css 上通过 max-width 实现)。

问题来了

  1. 为什么 v-container 不是 flex 容器,却存在 align-baseline 这样的 prop 呢?

    答:确实,v-container 只是网格系统的容器,这些 prop 不是必须的,但通过 d-flex 强制设置 display后,他也能成为 flex 容器(这些 props 还是用在 v-layout 上比较多)。

  2. 默认情况(无 props)下 v-flex 会独占一行吗?

    答:在 v-layout 中,一个默认 v-flex 的最大宽度为 100%,确实是独占一行,但是当行内存在多个默认的 v-flex 时,他们会平分空间,因为虽然确定了最大宽度,但是具体宽度还是可以调整的。当有两个 v-flex,且其中一个设置了 xs3 时,xs3 那个会占 25%,另一个占 75%,因为 xs3 确定了新的 max-width,另一个元素的宽度会自己做调整。

  3. v-flex 在 nowrap 时的行为是怎么样的。

    网格系统分成了 12 格,flex 占用为 xs4 xs4 xs4 时完美占用一行,占用为 xs3 xs3 xs3 时(不设置 grow),不足一行,会留空,占用为 xs5 xs5 xs5 时,明显超过一行,但不会换行(设置了 nowrap),结果会按比例 5:5:5 进行分配。

  4. v-container fluid 的意义是什么?默认情况下不是 100% 宽度?

    默认情况下加上 margin 会是 100% 宽度,且 margin 会根据 viewport breakpoint 发生改变,如果希望内容能尽可能靠近边缘,应该加上 fluid,去除 margin。

  5. v-spacer 是怎么实现的?

    v-spacer 通过 flex-grow: 1 实现,因此前文才注明需要在 flex 容器中使用。否则 flex-grow 不生效且 v-spacer 将会回退为 div,由于 display: block 导致换行。