Skip to main content
Nuxt UI integrates with the @nuxtjs/color-mode module to provide seamless dark mode and light mode support. The useColorMode composable gives you access to the current color mode and methods to change it.

Installation

The @nuxtjs/color-mode module is automatically installed with Nuxt UI. No additional setup is required.

Usage

<script setup>
const colorMode = useColorMode()
</script>

Return Value

The composable returns an object with the following properties:
preference
Ref<'light' | 'dark' | 'system'>
User’s color mode preference. Can be set to change the theme.
value
Ref<'light' | 'dark'>
Current active color mode (computed from preference and system settings).
forced
boolean
Whether the color mode is forced for the current page.

Examples

Display Current Color Mode

<script setup>
const colorMode = useColorMode()
</script>

<template>
  <div>
    <p>Preference: {{ colorMode.preference }}</p>
    <p>Current mode: {{ colorMode.value }}</p>
  </div>
</template>

Toggle Color Mode

<script setup>
const colorMode = useColorMode()

function toggleColorMode() {
  colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark'
}
</script>

<template>
  <button @click="toggleColorMode">
    {{ colorMode.value === 'dark' ? '🌙' : '☀️' }}
  </button>
</template>

Color Mode Selector

<script setup>
const colorMode = useColorMode()

const modes = [
  { value: 'light', label: 'Light', icon: 'i-lucide-sun' },
  { value: 'dark', label: 'Dark', icon: 'i-lucide-moon' },
  { value: 'system', label: 'System', icon: 'i-lucide-monitor' }
]
</script>

<template>
  <div>
    <button
      v-for="mode in modes"
      :key="mode.value"
      @click="colorMode.preference = mode.value"
      :class="{ active: colorMode.preference === mode.value }"
    >
      <Icon :name="mode.icon" />
      {{ mode.label }}
    </button>
  </div>
</template>

Using Nuxt UI Color Mode Components

Nuxt UI provides pre-built components for color mode management:

ColorModeButton

<template>
  <UColorModeButton />
</template>

ColorModeSwitch

<template>
  <UColorModeSwitch />
</template>

ColorModeSelect

<template>
  <UColorModeSelect />
</template>

ColorModeAvatar

<template>
  <UColorModeAvatar />
</template>

Conditional Rendering Based on Color Mode

<script setup>
const colorMode = useColorMode()
</script>

<template>
  <div>
    <img v-if="colorMode.value === 'dark'" src="/logo-dark.png" alt="Logo" />
    <img v-else src="/logo-light.png" alt="Logo" />
  </div>
</template>

Custom Theme Toggle with Icon

<script setup>
import { useColorMode } from '#ui'

const colorMode = useColorMode()

const isDark = computed(() => colorMode.value === 'dark')

function toggle() {
  colorMode.preference = isDark.value ? 'light' : 'dark'
}
</script>

<template>
  <UButton
    :icon="isDark ? 'i-lucide-moon' : 'i-lucide-sun'"
    color="neutral"
    variant="ghost"
    :aria-label="isDark ? 'Switch to light mode' : 'Switch to dark mode'"
    @click="toggle"
  />
</template>

Watching Color Mode Changes

<script setup>
const colorMode = useColorMode()

watch(() => colorMode.value, (newMode) => {
  console.log('Color mode changed to:', newMode)
  // Perform actions on color mode change
  if (newMode === 'dark') {
    // Enable dark mode features
  }
})
</script>

Force Color Mode on Specific Page

<script setup>
definePageMeta({
  colorMode: 'dark'
})
</script>

System Preference Detection

<script setup>
const colorMode = useColorMode()

const isSystem = computed(() => colorMode.preference === 'system')
const systemPreference = computed(() => {
  if (import.meta.client) {
    return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
  }
  return 'light'
})
</script>

<template>
  <div>
    <p v-if="isSystem">
      Using system preference: {{ systemPreference }}
    </p>
  </div>
</template>

Configuration

Configure the color mode module in your nuxt.config.ts:
export default defineNuxtConfig({
  colorMode: {
    preference: 'system', // default value of $colorMode.preference
    fallback: 'light', // fallback value if not system preference found
    hid: 'nuxt-color-mode-script',
    globalName: '__NUXT_COLOR_MODE__',
    componentName: 'ColorScheme',
    classPrefix: '',
    classSuffix: '',
    storageKey: 'nuxt-color-mode'
  }
})

Configuration Options

preference
'light' | 'dark' | 'system'
default:"'system'"
Default color mode preference.
fallback
'light' | 'dark'
default:"'light'"
Fallback color mode when system preference cannot be detected.
storageKey
string
default:"'nuxt-color-mode'"
Local storage key for persisting user preference.
classPrefix
string
default:"''"
Prefix for the color mode class added to <html>.
classSuffix
string
default:"''"
Suffix for the color mode class. For example, with suffix -mode, classes become light-mode and dark-mode.

Styling with Color Mode

Nuxt UI uses semantic color tokens that automatically adapt to the color mode:
<template>
  <div class="bg-elevated text-default">
    This background and text automatically adapt to light/dark mode
  </div>
</template>
Common semantic tokens:
  • text-default, text-muted, text-inverted
  • bg-default, bg-elevated, bg-inverted
  • border-default, border-muted

TypeScript

import type { BasicColorMode, ColorMode } from '#color-mode'
import { useColorMode } from '#imports'

const colorMode = useColorMode()

// Type-safe preference setting
colorMode.preference = 'dark' // 'light' | 'dark' | 'system'

// Type-safe value access
const current: 'light' | 'dark' = colorMode.value

Learn More

Build docs developers (and LLMs) love