Switching Themes in Vuetify 3: A Practical Guide to CSS‑Variable Theming
Learn how Vuetify 3’s CSS‑variable theme system lets you toggle dark and light modes, create custom palettes, and keep every component in sync with minimal effort.
26 Feb 2026, 13:21 UTC

What’s the real problem?
In a modern Vue application you often need a single source of truth for colors. Switching between light and dark modes, or tweaking a brand color, should ripple through every Vuetify component without hunting down hard‑coded CSS. Without a clean solution you end up with duplicated styles, brittle overrides, and a maintenance nightmare.
Why Vuetify’s CSS‑variable theme system matters
Vuetify 3 introduces a dedicated theme plugin that injects CSS variables for the core color slots: primary, secondary, accent, error, warning, info, success, and background. Because these are real CSS variables, they can be read and overridden anywhere in the stylesheet or component style block. The plugin also manages the light/dark palettes automatically – toggle a flag and every component updates.
Step 1 – Install and bootstrap the theme plugin
Assuming you already have a Vue 3 project, add Vuetify 3 and its CLI helper:
npm i vuetify@next
npx vuetify install
During installation you’ll be prompted to enable the theme plugin. If you skip it, add it manually in src/plugins/vuetify.js:
import { createVuetify } from 'vuetify'
import { aliases, mdi } from 'vuetify/iconsets/mdi'
export default createVuetify({
icons: { defaultSet: 'mdi', aliases, sets: { mdi } },
theme: {
defaultTheme: 'light', // start in light mode
themes: {
light: {
colors: {
primary: '#1976D2',
secondary: '#424242',
accent: '#82B1FF',
error: '#FF5252',
warning: '#FFC107',
info: '#2196F3',
success: '#4CAF50',
background: '#FFFFFF',
},
},
dark: {
colors: {
primary: '#90CAF9',
secondary: '#BDBDBD',
accent: '#FF4081',
error: '#FF5252',
warning: '#FF9800',
info: '#03A9F4',
success: '#8BC34A',
background: '#121212',
},
},
},
},
})
Place this file in src/plugins and import it in main.js:
import vuetify from './plugins/vuetify'
app.use(vuetify)
Step 2 – Toggle the theme at runtime
Vuetify exposes the theme instance via useTheme(). In a component you can switch between light and dark with a simple button:
import { useTheme } from 'vuetify'
export default {
setup() {
const theme = useTheme()
const toggle = () => {
theme.global.name.value = theme.global.name.value === 'light' ? 'dark' : 'light'
}
return { toggle }
},
}
In the template:
<v-btn @click="toggle">Toggle Theme</v-btn>
When theme.global.name.value changes, Vuetify automatically swaps the CSS variables for the selected palette, and every component that uses the theme colors updates instantly.
Step 3 – Use theme variables inside component styles
Because the colors are CSS variables, you can reference them directly in style blocks. This is handy for custom components that need to stay in sync with the theme:
<template>
<div class="card">Hello</div>
</template>
<style scoped>
.card {
background: var(--v-theme-background);
color: var(--v-theme-primary);
padding: 1rem;
border-radius: 4px;
}
</style>
Notice the --v-theme-* prefix – these are injected by the plugin. If you need a component‑specific override, simply set the variable in the component’s style block or use a style attribute with var(--v-theme-primary) as a fallback.
Trade‑off: Browser support and fallback strategy
CSS variables are well supported in all evergreen browsers, but older browsers (IE11 and earlier) do not understand them. In those environments the theme will fall back to the default static styles defined in Vuetify’s source. If you must support such browsers, consider:
- Polyfilling CSS variables with
css-vars-ponyfill(though this adds runtime overhead). - Providing a static light theme as the baseline and only enabling dynamic switching on modern browsers.
- Using feature detection in JavaScript:
if (CSS.supports('color', 'var(--foo)')) { /* enable dynamic theme */ }
Practical check: Verify theme changes in the browser
After toggling the button, inspect the body element in DevTools. You should see a data-theme attribute set to light or dark, and the CSS variables under --v-theme-* will reflect the selected palette. Additionally, any Vuetify component that uses the color prop (e.g., color="primary") will automatically adopt the new primary color.
Conclusion – One configuration, endless consistency
Vuetify 3’s CSS‑variable theme system turns a handful of configuration lines into a single source of truth for your entire UI. By defining light and dark palettes, toggling via useTheme(), and referencing var(--v-theme-*) in component styles, you can keep every element in sync without manual CSS overrides. Just remember the browser limitation and plan a fallback if you need to support legacy environments. Happy theming!
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.