Vuetify 组件尺寸与密度(Size Density)完全指南
2026/9/19 21:53:19 网站建设 项目流程

Vuetify 组件尺寸与密度(Size & Density)完全指南

【免费下载链接】vuetify🐉 Vue Component Framework项目地址: https://gitcode.com/gh_mirrors/vu/vuetify

本文基于 Vuetify 官方文档《Density and sizing》展开,系统讲解sizedensity两个核心布局属性的取值语义、适用组件、底层实现原理与组合使用技巧。读完本文,你将掌握如何用size精确控制组件的宽高与字号、用density压缩垂直内边距以适配密集型界面(如工具栏、数据表格),并能结合源码理解这两个属性在 Vuetify 内部是如何生成 CSS 类与样式变量的。原文档与配套可运行示例位于 density-and-sizing.md。

Size:控制组件的宽、高与字号

size属性用于增大或缩小组件整体占用的宽度和高度,同时会影响font-size(字号)。它通常应用于按钮、Chip、图标、头像、评分等具有明显尺寸比例的组件。

支持的取值

size提供了一套五档的预定义标尺:

  • x-small(特小)
  • small(小)
  • default(默认)
  • large(大)
  • x-large(特大)

从源码看,这套预定义值定义在 size.ts 中:

const predefinedSizes = ['x-small', 'small', 'default', 'large', 'x-large']

自定义数值尺寸

值得注意的一点是:size的 prop 类型是String | Number,默认值为'default'。也就是说,除了使用上述五档预设值,你还可以直接传入任意数字或长度字符串,将其作为组件的像素宽高:

<v-avatar :size="64"></v-avatar> <v-avatar size="6rem"></v-avatar>

对应 size.ts 的实现逻辑:

if (includes(predefinedSizes, size)) { sizeClasses = `${name}--size-${size}` } else if (size) { sizeStyles = { width: convertToUnit(size), height: convertToUnit(size), } }

即:命中预设值时输出形如v-btn--size-large的类名;传入自定义值时则通过convertToUnit转换为 CSS 单位,直接以内联样式(width/height)作用于组件。

实操示例

官方示例 size.vue 通过一个v-btn-toggle在五档尺寸间切换,并同步应用到按钮、Chip、评分与头像上:

<v-btn :size="size" class="me-2 mb-2" text="Export" ></v-btn> <v-chip :size="size" class="me-2 mb-2" text="Completed" ></v-chip> <v-rating :size="size" label="Customer Satisfaction" length="3" ></v-rating> <v-avatar :size="size" class="mb-2 me-2" image="https://cdn.vuetifyjs.com/docs/images/avatars/dark.png" ></v-avatar>

其中size为绑定在切换按钮上的响应式变量(默认'default'):

const size = shallowRef('default')

Density:压缩垂直空间

density属性用于减少组件的垂直内边距(vertical padding),部分组件还会同步缩小字号。对于方形或圆形组件(如图标),它同时会减少水平内边距。这是让密集列表、表格、工具栏等高信息量界面更紧凑的主要手段。

支持的取值

density提供三档密度:

  • default(默认)
  • comfortable(舒适)
  • compact(紧凑)

对应的类型定义与校验逻辑位于 density.ts:

const allowedDensities = [null, 'default', 'comfortable', 'compact'] as const export type Density = null | 'default' | 'comfortable' | 'compact' export const makeDensityProps = propsFactory({ density: { type: String as PropType<Density>, default: 'default', validator: (v: any) => allowedDensities.includes(v), }, }, 'density')

可以看到,Vuetify 对传入值做了白名单校验(validator),不合法的取值会被框架拒绝。

类名生成机制

useDensity组合式函数会基于组件实例名与当前密度值生成一个响应式类名:

export function useDensity (props: DensityProps, name = getCurrentInstanceName()) { const densityClasses = toRef(() => { return `${name}--density-${props.density}` }) return { densityClasses } }

因此,一个v-btndensity="compact"时会得到v-btn--density-compact类,Sass 样式据此调整内边距与高度。

实操示例

官方示例 density.vue 演示了密度对按钮、Chip、工具栏与文本输入框的影响:

<v-btn :density="density" class="me-2 mb-2" text="Submit" ></v-btn> <v-chip :density="density" class="me-2 mb-2" text="In Progress" ></v-chip> <v-toolbar :density="density" class="mb-2" elevation="1" title="Daily Reports" ></v-toolbar> <v-text-field :density="density" label="Search Query" model-value="Data tables" prepend-inner-icon="mdi-magnify" variant="solo" ></v-text-field>

组合使用:Size × Density

sizedensity两个正交的属性size决定整体尺度(宽、高、字号),density决定内部留白密度。二者可以自由组合,一次性调整组件的整体观感,例如「大尺寸 + 紧凑密度」可以在保持醒目字号的同时尽量减少占用的垂直空间。

官方示例 density-and-size.vue 使用两个滑块分别驱动sizedensity,并同时应用到按钮、Chip 与头像上:

<v-btn :density="densities[density]" :size="sizes[size]" class="me-2 mb-2" prepend-icon="$vuetify" text="Default Button" ></v-btn>

对应脚本中的取值映射:

const size = shallowRef(2) const density = shallowRef(2) const densities = ['compact', 'comfortable', 'default'] const sizes = ['x-small', 'small', 'default', 'large', 'x-large']

这种「双滑块 + 组件实时预览」的模式非常适合在设计阶段快速比对不同组合的视觉密度。

底层原理:Sass 混入如何计算尺寸与密度

从源码层面看,sizedensity的最终效果由各组件自身的 Sass 混入(mixin)实现。以按钮为例,VBtn/_mixins.scss 中:

@mixin button-sizes ($map: $button-sizes, $immediate: false) { @each $sizeName, $multiplier in settings.$size-scales { $size: map.get($map, 'font-size') + math.div(2 * $multiplier, 16); $height: map.get($map, 'height') + (settings.$size-scale * $multiplier); $selector: '.v-btn--size-#{$sizeName}'; #{$selector} { --v-btn-size: #{$size}; --v-btn-height: #{$height}; font-size: var(--v-btn-size); min-width: tools.roundEven($height * map.get($map, 'width-ratio')); padding: 0 tools.roundEven(math.div($height, map.get($map, 'padding-ratio'))); } } }

可以看到,每一档size都会依据全局尺寸标尺(settings.$size-scalessettings.$size-scale)计算并暴露--v-btn-size--v-btn-height两个 CSS 变量,再派生font-sizemin-width与水平padding

密度部分则基于高度变量做增量计算:

@mixin button-density ($properties, $densities) { @each $density, $multiplier in $densities { $value: calc(var(--v-btn-height) + #{$multiplier * settings.$spacer}); &.v-btn--density-#{$density} { // 将 $value 应用到 height / padding 等属性 } } }

即:density通过「基础高度 + 密度增量 × 全局 spacer」的公式得到最终高度与内边距,compact对应负增量,default为零增量,comfortable为正增量。同样的模式也出现在 Chip(见 VChip/_mixins.scss)等组件中,只是各自维护一套$size-scales$densities映射。

注意事项

  • 并非所有组件都有高度过渡动画:官方文档明确提示——当动态切换density时,不是所有组件都带有默认的「高度变化过渡」动画。这意味着在运行时切换密度可能出现高度瞬间跳变,若需要平滑动画,应自行添加transition样式。
  • density的覆盖范围density主要作用于内边距与字号,不改变组件的整体宽度与字体排版的水平尺度;comfortablecompact之间的差异通常为几个像素的垂直留白,请根据界面信息密度按需选用。
  • 自定义size的局限:传入数值/长度字符串时,size以等宽等高(正方形)方式生成内联样式,适用于头像、图标、评分等方形组件;对按钮等需要保持宽高比例的组件,建议使用五档预设值。

相关组件与继续探索

sizedensity被大量组件以组合式函数方式复用。通过makeDensityProps/makeSizeProps的引用关系(见 composables 与 size.ts),可以看到支持这两个属性的组件包括但不限于:VBtnVChipVAvatarVRatingVTabsVTableVListVInput/VTextFieldVToolbarVAlertVCardVPaginationVTimelineVTreeview等(具体组件实现分布在 packages/vuetify/src/components 下各自的*.tsx文件中)。

如果需要为某个具体组件查看可用的密度档位与尺寸标尺,可直接阅读该组件目录下的_mixins.scssvariables.scss,例如按钮的样式入口为 VBtn.sass。官方文档中与本节主题强相关的组件还包括按钮、Chip、列表等,可在文档导航的对应组件页中找到更多组合示例。

【免费下载链接】vuetify🐉 Vue Component Framework项目地址: https://gitcode.com/gh_mirrors/vu/vuetify

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询