Theme Configuration
Vuetify’s theme system allows you to customize colors, enable dark mode, and configure CSS variables that can be changed at runtime. Unlike SASS variables, theme configuration is dynamic and can be modified after your application is built.
Basic Setup
Configure themes when creating your Vuetify instance:
import { createVuetify } from 'vuetify'
const vuetify = createVuetify ({
theme: {
defaultTheme: 'light' ,
themes: {
light: {
dark: false ,
colors: {
primary: '#1867C0' ,
secondary: '#48A9A6' ,
error: '#B00020' ,
info: '#2196F3' ,
success: '#4CAF50' ,
warning: '#FB8C00' ,
},
},
},
},
})
Theme Options
ThemeOptions Interface
Configuration
Variations
Theme Definition
interface ThemeOptions {
cspNonce ?: string
defaultTheme ?: 'light' | 'dark' | 'system' | string
variations ?: false | VariationsOptions
themes ?: Record < string , ThemeDefinition >
stylesheetId ?: string
scope ?: string
utilities ?: boolean
}
Default Theme
Specify which theme to use by default:
createVuetify ({
theme: {
defaultTheme: 'light' , // 'light' | 'dark' | 'system'
},
})
Setting defaultTheme: 'system' automatically detects the user’s OS preference: theme : {
defaultTheme : 'system' , // Respects prefers-color-scheme
}
Vuetify listens to changes in the system preference and updates automatically.
Color System
Base Colors
Every theme must define these base colors:
colors : {
background : '#FFFFFF' ,
surface : '#FFFFFF' ,
primary : '#1867C0' ,
secondary : '#48A9A6' ,
success : '#4CAF50' ,
warning : '#FB8C00' ,
error : '#B00020' ,
info : '#2196F3' ,
}
On-Colors
On-colors are automatically generated for text/icons on colored backgrounds:
colors : {
primary : '#1867C0' ,
'on-primary' : '#FFFFFF' , // Auto-generated if not specified
background : '#FFFFFF' ,
'on-background' : '#000000' , // Auto-generated based on luminance
}
Vuetify calculates on-colors automatically using luminance detection. Only override them if you need custom values.
Custom Colors
Add custom colors beyond the base palette:
themes : {
light : {
colors : {
// Base colors
primary : '#1867C0' ,
secondary : '#48A9A6' ,
// Custom colors
accent : '#82B1FF' ,
brand : '#FF6B9D' ,
'surface-variant' : '#EEEEEE' ,
'surface-bright' : '#FFFFFF' ,
},
},
}
Color Variations
Automatically generate lighten/darken variations:
theme : {
variations : {
colors : [ 'primary' , 'secondary' ],
lighten : 3 , // Generates primary-lighten-1, primary-lighten-2, primary-lighten-3
darken : 3 , // Generates primary-darken-1, primary-darken-2, primary-darken-3
},
themes : {
light : {
colors : {
primary : '#1867C0' ,
secondary : '#48A9A6' ,
},
},
},
}
Use generated variations in components:
< v-btn color = "primary-darken-1" > Darker Primary </ v-btn >
< v-card color = "primary-lighten-2" > Lighter Primary </ v-card >
Multiple Themes
Define multiple themes and switch between them:
const vuetify = createVuetify ({
theme: {
defaultTheme: 'light' ,
themes: {
light: {
dark: false ,
colors: {
primary: '#1867C0' ,
secondary: '#48A9A6' ,
},
},
dark: {
dark: true ,
colors: {
primary: '#2196F3' ,
secondary: '#54B6B2' ,
},
},
custom: {
dark: false ,
colors: {
primary: '#6200EE' ,
secondary: '#03DAC6' ,
},
},
},
},
})
Theme Variables
Customize CSS variables that control opacity, shadows, and other properties:
themes : {
light : {
dark : false ,
colors : { /* ... */ },
variables : {
'border-color' : '#000000' ,
'border-opacity' : 0.12 ,
'shadow-color' : '#000000' ,
'high-emphasis-opacity' : 0.87 ,
'medium-emphasis-opacity' : 0.60 ,
'disabled-opacity' : 0.38 ,
'idle-opacity' : 0.04 ,
'hover-opacity' : 0.04 ,
'focus-opacity' : 0.12 ,
'selected-opacity' : 0.08 ,
'activated-opacity' : 0.12 ,
'pressed-opacity' : 0.12 ,
'dragged-opacity' : 0.08 ,
'theme-kbd' : '#EEEEEE' ,
'theme-on-kbd' : '#000000' ,
'theme-code' : '#F5F5F5' ,
'theme-on-code' : '#000000' ,
},
},
dark : {
dark : true ,
colors : { /* ... */ },
variables : {
'border-color' : '#FFFFFF' ,
'border-opacity' : 0.12 ,
'high-emphasis-opacity' : 1 ,
'medium-emphasis-opacity' : 0.70 ,
'disabled-opacity' : 0.50 ,
'hover-opacity' : 0.04 ,
'pressed-opacity' : 0.16 ,
},
},
}
Advanced Configuration
CSP Nonce
Add a nonce for Content Security Policy:
theme : {
cspNonce : 'your-nonce-here' ,
}
Scoped Themes
Scope themes to specific containers:
theme : {
scope : '#app' , // Limit theme to elements within #app
}
Disable Utilities
Disable automatic generation of utility classes:
theme : {
utilities : false , // Don't generate .bg-primary, .text-secondary, etc.
}
Custom Stylesheet ID
Change the ID of the injected style element:
theme : {
stylesheetId : 'my-custom-theme-stylesheet' ,
}
Using the Theme
In Components
Composition API
Options API
< script setup >
import { useTheme } from 'vuetify'
const theme = useTheme ()
// Change theme
function switchTheme ( name ) {
theme . change ( name )
}
// Toggle between light and dark
function toggleTheme () {
theme . toggle ([ 'light' , 'dark' ])
}
// Cycle through all themes
function cycleTheme () {
theme . cycle ()
}
// Check current theme
console . log ( theme . name . value ) // Current theme name
console . log ( theme . current . value ) // Current theme definition
console . log ( theme . isSystem . value ) // Is using system theme?
</ script >
Theme Methods
const theme = useTheme ()
// Change to specific theme
theme . change ( 'dark' )
// Toggle between two themes
theme . toggle ([ 'light' , 'dark' ]) // Defaults to ['light', 'dark']
// Cycle through themes
theme . cycle () // All themes
theme . cycle ([ 'light' , 'dark' , 'custom' ]) // Specific themes
Theme Properties
theme . name // Ref<string> - Current theme name
theme . current // DeepReadonly<Ref<ThemeDefinition>>
theme . themes // Ref<Record<string, ThemeDefinition>>
theme . isSystem // Readonly<Ref<boolean>>
theme . isDisabled // boolean
theme . prefix // string (default: 'v-')
theme . themeClasses // Readonly<Ref<string | undefined>>
theme . styles // Readonly<Ref<string>> - Generated CSS
Default Themes
Vuetify includes default light and dark themes:
light : {
dark : false ,
colors : {
background : '#FFFFFF' ,
surface : '#FFFFFF' ,
'surface-bright' : '#FFFFFF' ,
'surface-light' : '#EEEEEE' ,
'surface-variant' : '#424242' ,
'on-surface-variant' : '#EEEEEE' ,
primary : '#1867C0' ,
'primary-darken-1' : '#1F5592' ,
secondary : '#48A9A6' ,
'secondary-darken-1' : '#018786' ,
error : '#B00020' ,
info : '#2196F3' ,
success : '#4CAF50' ,
warning : '#FB8C00' ,
},
variables : {
'border-color' : '#000000' ,
'border-opacity' : 0.12 ,
'high-emphasis-opacity' : 0.87 ,
'medium-emphasis-opacity' : 0.60 ,
'disabled-opacity' : 0.38 ,
'hover-opacity' : 0.04 ,
'focus-opacity' : 0.12 ,
'selected-opacity' : 0.08 ,
'activated-opacity' : 0.12 ,
'pressed-opacity' : 0.12 ,
},
}
dark : {
dark : true ,
colors : {
background : '#121212' ,
surface : '#212121' ,
'surface-bright' : '#ccbfd6' ,
'surface-light' : '#424242' ,
'surface-variant' : '#c8c8c8' ,
'on-surface-variant' : '#000000' ,
primary : '#2196F3' ,
'primary-darken-1' : '#277CC1' ,
secondary : '#54B6B2' ,
'secondary-darken-1' : '#48A9A6' ,
error : '#CF6679' ,
info : '#2196F3' ,
success : '#4CAF50' ,
warning : '#FB8C00' ,
},
variables : {
'border-color' : '#FFFFFF' ,
'border-opacity' : 0.12 ,
'high-emphasis-opacity' : 1 ,
'medium-emphasis-opacity' : 0.70 ,
'disabled-opacity' : 0.50 ,
'hover-opacity' : 0.04 ,
'focus-opacity' : 0.12 ,
'selected-opacity' : 0.08 ,
'activated-opacity' : 0.12 ,
'pressed-opacity' : 0.16 ,
},
}
Best Practices
Use semantic color names
Define colors by purpose (primary, secondary) rather than by appearance (blue, green).
Provide both light and dark themes
Most users expect dark mode support in modern applications.
Let Vuetify generate on-colors
The automatic luminance-based generation works well for most cases.
Test color contrast
Ensure sufficient contrast between colors and their on-colors for accessibility.
Theme colors are applied via CSS variables. If you need compile-time color modifications, use SASS variables instead.