JAVASCRIPT
Dynamic CSS Variable Binding for Theming in Vue 3
Control component styling dynamically by binding Vue 3 reactive data to CSS variables, enabling easy theme switching like dark mode without reloading the page.
<template>
<div class="theme-switcher" :style="cssVariables">
<h2>Dynamic Theming Example</h2>
<p>Current theme: {{ currentTheme }}</p>
<button @click="toggleTheme">Toggle Theme</button>
<div class="themed-box">
This box's background and text color change with the theme.
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const currentTheme = ref('light');
const themes = {
light: {
'--bg-color': '#ffffff',
'--text-color': '#2c3e50',
'--box-bg': '#f0f0f0',
'--box-text': '#333333',
},
dark: {
'--bg-color': '#2c3e50',
'--text-color': '#ffffff',
'--box-bg': '#3a536b',
'--box-text': '#e0e0e0',
},
};
const cssVariables = computed(() => {
return themes[currentTheme.value];
});
function toggleTheme() {
currentTheme.value = currentTheme.value === 'light' ? 'dark' : 'light';
// For persistent theme, you would save currentTheme.value to localStorage here.
// Example: localStorage.setItem('theme', currentTheme.value);
}
</script>
<style scoped>
.theme-switcher {
padding: 20px;
background-color: var(--bg-color);
color: var(--text-color);
transition: background-color 0.3s ease, color 0.3s ease;
border-radius: 8px;
text-align: center;
}
.themed-box {
margin-top: 20px;
padding: 15px;
border-radius: 5px;
background-color: var(--box-bg);
color: var(--box-text);
transition: background-color 0.3s ease, color 0.3s ease;
border: 1px solid var(--box-text);
}
button {
margin-top: 15px;
padding: 10px 20px;
background-color: #42b983;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
}
</style>
How it works: This snippet demonstrates how to leverage dynamic CSS variable binding in Vue 3 for flexible theming. It defines two themes (light and dark) as objects mapping CSS variable names to their values. A `computed` property, `cssVariables`, dynamically returns the appropriate theme object based on `currentTheme`. This object is then bound to the `:style` attribute of the root element. Any descendant elements using `var(--css-variable)` will automatically react to the theme change, providing a smooth and efficient way to implement features like dark mode without re-rendering components.