JAVASCRIPT
Implement Dynamic Theming with Dark Mode Toggle in Vue 3
Enable dynamic theme switching, such as dark mode, in your Vue 3 application using CSS custom properties (variables) controlled by a Vue component.
// src/App.vue
<template>
<div :class="['theme-wrapper', currentTheme]">
<h1>Dynamic Theming in Vue 3</h1>
<p>This content changes based on the active theme.</p>
<button @click="toggleTheme">
Switch to {{ currentTheme === 'light-theme' ? 'Dark' : 'Light' }} Mode
</button>
<div class="card">
<h3>A Card Element</h3>
<p>This card also respects the theme.</p>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const currentTheme = ref(localStorage.getItem('theme') || 'light-theme');
const toggleTheme = () => {
currentTheme.value = currentTheme.value === 'light-theme' ? 'dark-theme' : 'light-theme';
localStorage.setItem('theme', currentTheme.value);
applyTheme(currentTheme.value);
};
const applyTheme = (theme) => {
const root = document.documentElement;
if (theme === 'dark-theme') {
root.style.setProperty('--bg-color', '#282c34');
root.style.setProperty('--text-color', '#f0f2f5');
root.style.setProperty('--card-bg', '#3a404c');
root.style.setProperty('--button-bg', '#61dafb');
root.style.setProperty('--button-text', '#282c34');
} else {
root.style.setProperty('--bg-color', '#f0f2f5');
root.style.setProperty('--text-color', '#282c34');
root.style.setProperty('--card-bg', '#ffffff');
root.style.setProperty('--button-bg', '#42b983');
root.style.setProperty('--button-text', '#ffffff');
}
};
onMounted(() => {
// Apply initial theme on mount
applyTheme(currentTheme.value);
});
</script>
<style>
/* Define default (light) theme variables */
:root {
--bg-color: #f0f2f5;
--text-color: #282c34;
--card-bg: #ffffff;
--button-bg: #42b983;
--button-text: #ffffff;
}
body {
margin: 0;
font-family: Arial, sans-serif;
background-color: var(--bg-color);
color: var(--text-color);
transition: background-color 0.3s ease, color 0.3s ease;
}
.theme-wrapper {
padding: 20px;
min-height: 100vh;
}
.card {
background-color: var(--card-bg);
color: var(--text-color);
padding: 20px;
margin-top: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
transition: background-color 0.3s ease, color 0.3s ease;
}
button {
background-color: var(--button-bg);
color: var(--button-text);
border: none;
padding: 10px 15px;
border-radius: 5px;
cursor: pointer;
margin-top: 10px;
transition: background-color 0.3s ease, color 0.3s ease;
}
button:hover {
opacity: 0.9;
}
</style>
How it works: This snippet demonstrates how to implement a dynamic theme switcher, like dark mode, in a Vue 3 application. It leverages CSS custom properties (variables) defined on the `:root` element. The `currentTheme` reactive reference stores the active theme, persisted in `localStorage`. The `applyTheme` function programmatically updates the CSS variables on `document.documentElement` to switch between light and dark modes, ensuring a consistent look across the application. The `onMounted` hook applies the initial theme, and the `toggleTheme` function handles the switching logic.