Skip to main content
Vuetify0 v1.0 is here
Vuetify0 Logo
Theme
Mode
Palettes
Accessibility
Vuetify One
Sign in to Vuetify One

Access premium tools across the Vuetify ecosystem — Bin, Play, Studio, and more.

Not a subscriber? See what's included

Theme

Scopes a theme to a component subtree for independently themed sections of your app.

Edit this page
Report a Bug
Open issues
View on GitHub
Copy Markdown

StableRenderlessIntermediateJul 19, 2026

Usage

Wrap any section of your template in <Theme> to override the active theme for that subtree. Children calling useTheme() will see the scoped theme as the current selection. When no theme prop is provided, it inherits the parent theme — useful for wrapping content that needs the data-theme attribute without changing the active theme.

vue
<script setup lang="ts">
  import { Theme } from '@vuetify/v0'
</script>

<template>
  <Theme theme="dark">
    <!-- Everything here sees "dark" as the active theme -->
    <slot />
  </Theme>
</template>

Anatomy

vue
<script setup lang="ts">
  import { Theme } from '@vuetify/v0'
</script>

<template>
  <Theme />
</template>

Examples

Scoped Override

Theme wraps a subtree in a scoped theme context. Descendant calls to useTheme() resolve to the overridden theme without affecting anything outside the wrapper. The component applies a data-theme attribute to its wrapper element, which CSS variable declarations can target to inject the correct token values.

This example sets up a light root context via createThemeContext, then places two independent <Theme theme="dark"> overrides alongside it. The second override nests a <Theme theme="light"> inside — demonstrating that nesting is arbitrary-depth and each level sees only its nearest ancestor’s scope, not the global default.

Reach for this pattern when a page section, card, sidebar, or marketing block needs a different theme from the surrounding app — dark headers, promotional banners, or inverted footers are common cases. The ThemeCard helper renders the active theme’s color swatches, making it easy to confirm the correct scope is resolved at each level.

FileRole
ThemeCard.vueDisplays the color palette for a given theme — used as a visual probe at each scope level
scoped-override.vueEntry — bootstraps the theme context and nests scoped overrides at multiple levels

Root context (light)

lightlight
primary
secondary
surface
background
Scoped to dark
darkdark
primary
secondary
surface
background
Nested back to light
lightlight
primary
secondary
surface
background
Independent dark scope
darkdark
primary
secondary
surface
background

Recipes

Polymorphic Rendering

Theme extends Atom, so it accepts the as prop to render as any HTML element:

vue
<template>
  <Theme theme="dark" as="section">
    <!-- renders as <section data-theme="dark"> -->
  </Theme>
</template>

Renderless Mode

Set renderless to skip the wrapper element. The slot exposes attrs (including data-theme) for you to bind to your own element:

vue
<template>
  <Theme theme="dark" renderless v-slot="{ attrs }">
    <section v-bind="attrs">
      No extra wrapper div
    </section>
  </Theme>
</template>

Isolated Context

By default, <Theme> provides its context under the 'v0:theme' key — the same key used by useTheme(). If you’re building a component that needs its own theme scope that doesn’t interfere with the app’s global theme, pass a custom namespace:

vue
<template>
  <!-- Isolated: useTheme() in descendants won't affect the global theme -->
  <Theme theme="dark" namespace="my-widget:theme">
    <slot />
  </Theme>
</template>
Tip

The namespace prop is only needed when building reusable components that must be theme-isolated. Most apps don’t need it.

Slot Props

The default slot exposes theme (the active ID), isDark (boolean), and attrs for conditional rendering:

vue
<template>
  <Theme v-slot="{ theme, isDark }" theme="dark">
    <span>{{ theme }} — dark: {{ isDark }}</span>
  </Theme>
</template>

Accessibility

Theme is a headless context provider. It scopes theme state to a subtree and writes a data-theme attribute on its wrapper element for CSS variable targeting; it adds no ARIA attributes, roles, or keyboard behavior, and it introduces no interactive elements of its own.

Theme selection is a visual concern, not a semantic one — a scoped theme changes token values, not the accessibility tree. Ensure the color choices in every theme you expose meet WCAG contrast requirements↗︎; the component does not enforce contrast for you.

FAQ

Discord
Need help? Join our community for support and discussions ↗

API Reference

The following API details are for all variations of the Theme component.
Was this page helpful?

© 2016-1970 Vuetify, LLC
Services
Ctrl+/