如何在Vuetify项目中动态全局修改字体样式/字重等非颜色属性?
如何在Vuetify中动态切换全局字体(无需逐个加类)
这个问题我之前踩过坑——直接修改variables.scss里的SCSS变量根本行不通,因为SCSS是预编译阶段就把变量替换成固定值了,运行时没法动态更新。不过我们可以用CSS自定义属性(也就是CSS变量)来绕开这个限制,配合Vuetify的主题配置,实现全局字体的实时切换,完全不用在组件里到处加类,维护性拉满!
核心思路
把Vuetify依赖的字体相关属性(比如font-family、字重)替换成运行时可修改的CSS变量,然后通过JavaScript动态修改这些变量的值,就能让整个应用的字体自动更新。
具体步骤
1. 配置Vuetify使用CSS变量
在你的Vuetify初始化文件(一般是src/plugins/vuetify.js)里,把主题的字体相关变量改成引用CSS变量:
import { createVuetify } from 'vuetify' export default createVuetify({ theme: { defaultTheme: 'light', themes: { light: { variables: { // 用CSS变量替代SCSS变量 fontFamily: 'var(--v-font-family)', fontWeightRegular: 'var(--v-font-weight-regular)', fontWeightMedium: 'var(--v-font-weight-medium)', fontWeightBold: 'var(--v-font-weight-bold)', }, // 你的颜色主题配置... }, }, }, })
2. 定义全局CSS变量并加载字体
在全局样式文件(比如src/styles/main.scss或者App.vue的<style>标签里),定义默认的CSS变量,同时确保你要切换的字体已经加载(比如用Google Fonts或者本地字体):
/* 根元素定义默认CSS变量 */ :root { --v-font-family: 'Roboto', sans-serif; --v-font-weight-regular: 400; --v-font-weight-medium: 500; --v-font-weight-bold: 700; } /* 加载可选字体(这里以Google Fonts为例) */ @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&family=Raleway:wght@300;400;600&display=swap');
3. 实现动态切换逻辑
在你的设置组件(比如一个字体选择器页面)里,用v-select提供可选字体,然后通过JavaScript修改根元素的CSS变量:
<template> <v-container> <v-select v-model="selectedFont" :items="availableFonts" label="选择全局字体" variant="outlined" class="mb-4" /> <!-- 可以再加一个字重选择器,逻辑类似 --> <v-select v-model="selectedWeight" :items="availableWeights" label="选择全局常规字重" variant="outlined" /> </v-container> </template> <script setup> import { ref, watch } from 'vue' // 可选字体列表 const availableFonts = [ { text: 'Roboto', value: "'Roboto', sans-serif" }, { text: 'Raleway', value: "'Raleway', sans-serif" }, // 可以添加更多字体 ] // 可选字重列表 const availableWeights = [ { text: '常规(400)', value: '400' }, { text: '轻量(300)', value: '300' }, { text: '中等(500)', value: '500' }, ] // 初始化选中值,优先从localStorage读取(可选,实现刷新保留设置) const selectedFont = ref(localStorage.getItem('app-font') || "'Roboto', sans-serif") const selectedWeight = ref(localStorage.getItem('app-font-weight') || '400') // 监听字体变化,动态更新CSS变量 watch(selectedFont, (newFont) => { document.documentElement.style.setProperty('--v-font-family', newFont) localStorage.setItem('app-font', newFont) }) // 监听字重变化,动态更新CSS变量 watch(selectedWeight, (newWeight) => { document.documentElement.style.setProperty('--v-font-weight-regular', newWeight) localStorage.setItem('app-font-weight', newWeight) }) </script>
为什么这个方案可行?
- CSS变量是运行时生效的,只要修改根元素的变量值,所有引用该变量的地方都会自动更新。
- 我们是在Vuetify的主题
variables里配置的这些CSS变量,Vuetify的所有组件都会继承这些设置,所以是真正的全局生效,不用给每个组件加类。 - 可以轻松扩展到其他全局属性(比如行高、字间距),只需要在Vuetify主题变量里对应替换成CSS变量即可。
内容的提问来源于stack exchange,提问作者Aagam Vadecha




