Controlling Vuetify 3 Theme State with useVuetify()
Use Vuetify 3's useVuetify() composable to read and toggle theme state reactively instead of manually swapping dark classes.
10 Oct 2026, 06:53 UTC

The Dark Toggle That Does Nothing
You add a dark-mode button to a Vuetify 3 app, wire it to a local boolean, and click it. Nothing happens. The app stays light, or the theme snaps back after a refresh. The problem is usually not your CSS. It is that the component is tracking theme preference in a local variable instead of Vuetify's reactive theme instance.
Vuetify 3 keeps theme state inside the Vuetify instance, which is created with createVuetify(). A composable is a function that uses Vue's Composition API to expose reactive state and lifecycle hooks. Vuetify's useVuetify() composable returns that instance so any component can read or write theme, locale, and icons without prop drilling or dependency injection.
Reading and Writing Theme State
Assume you are using Vuetify 3.x with Vue 3 and the Composition API plugin already installed. In a component, call useVuetify() inside setup() or <script setup>. The returned object exposes theme.global.name, which holds values such as 'light' or 'dark'.
<script setup lang="ts">
import { useVuetify } from 'vuetify'
const vuetify = useVuetify()
function toggleTheme() {
const current = vuetify.theme.global.name
vuetify.theme.global.name = current === 'light' ? 'dark' : 'light'
}
</script>
<template>
<VBtn
@click="toggleTheme"
:color="vuetify.theme.global.name === 'dark' ? 'dark' : 'primary'"
>
Switch to {{ vuetify.theme.global.name === 'light' ? 'dark' : 'light' }}
</VBtn>
</template>
Because theme.global.name is reactive, changing it updates every component that reads Vuetify theme classes. You do not need to manually toggle a theme--dark class on the root element; Vuetify applies theme classes automatically when the instance state changes.
Local State vs. useVuetify()
| Approach | Theme updates globally | Requires manual class toggling |
|---|---|---|
| Local component boolean | No | Yes |
useVuetify().theme.global.name |
Yes | No |
Verification and Practical Checks
- Open your project in a terminal and run
npx vue-tsc --noEmitto confirm TypeScript accepts the property assignment. - Start the dev server, open browser developer tools, and inspect the root element.
- Click the toggle and verify the root element's theme class changes and component colors invert.
- Refresh the page and confirm the theme resets to the default unless you persist the preference yourself.
To scaffold a baseline project, run npm create vuetify@latest from your project root. No special permissions are required, but the command downloads packages from the registry and may overwrite existing files in the target directory.
Limitations
- Global scope: Theme state is application-wide. A toggle in one route changes colors everywhere Vuetify theme classes are used.
- No automatic persistence:
useVuetify()does not write the user's choice tolocalStorage. You must wire that logic separately if the preference should survive a reload. - SSR hydration: On server-rendered pages, theme set on the client can mismatch the server HTML, causing a hydration warning or flash. Set the initial theme from a cookie or user preference before rendering when possible.
- Version assumptions: This pattern assumes Vuetify 3.x. Early 3.x releases had incomplete type definitions for some components, so you may need explicit type assertions if your IDE flags
theme.global.name.
Actionable Takeaway
Stop managing Vuetify theme with local component state. Import useVuetify(), mutate theme.global.name directly, and let Vuetify apply theme classes automatically. Verify with npx vue-tsc --noEmit and a browser refresh, then add your own persistence layer if users expect their choice to be remembered.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.