Skip to main content
Vuetify0 is now in alpha!
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.

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

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

<template>
  <!-- Wrapper mode (default) -->
  <Theme theme="dark">
    <div>Dark-scoped content</div>
  </Theme>

  <!-- Polymorphic rendering -->
  <Theme theme="dark" as="section">
    <div>Renders as section element</div>
  </Theme>

  <!-- Renderless mode -->
  <Theme theme="dark" renderless v-slot="{ attrs }">
    <section v-bind="attrs">Custom element</section>
  </Theme>
</template>

Examples

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>

API Reference

The following API details are for all variations of the Theme component.

Theme

Props

namespace

string | undefined

Default: "v0:theme"

Slots

default

ThemeSlotProps
Was this page helpful?

Ctrl+/