Dynamic class and inline style bindings let your UI respond visually to component state. Instead of stitching class strings together manually, Vue extends :class and :style to accept objects, arrays, and computed properties.
When reactive state changes, Vue merges dynamic classes cleanly with static classes on the same element. This keeps your templates clean and prevents messy string interpolation bugs.
flowchart LR
State["Reactive State"] --> Computed["Computed Class or Style Object"]
Computed --> Element["DOM Element with Merged Classes"]
:class="{ active: isActive, 'text-danger': hasError }".:class="[baseClass, { active: isActive }]".:style="{ fontSize: size + 'px', color: textColor }".<script setup> for better readability.This example combines static classes with computed :class and :style objects inside <script setup>.
<script setup>
import { ref, computed } from 'vue';
const isActive = ref(true);
const status = ref('warning');
const fontSize = ref(16);
const containerClasses = computed(() => ({
'card-active': isActive.value,
[`status-${status.value}`]: true
}));
const dynamicStyles = computed(() => ({
fontSize: `${fontSize.value}px`,
color: status.value === 'error' ? '#b91c1c' : '#0f172a'
}));
function toggleStatus() {
status.value = status.value === 'warning' ? 'error' : 'warning';
}
</script>
<template>
<div class="demo-wrapper">
<div class="card" :class="containerClasses" :style="dynamicStyles">
Dynamic Styled Content Block
</div>
<div class="controls">
<button @click="isActive = !isActive">Toggle Active</button>
<button @click="toggleStatus">Toggle Status</button>
<button @click="fontSize += 2">Increase Font</button>
</div>
</div>
</template>
<style scoped>
.card {
padding: 1rem;
border: 2px solid #cbd5e1;
transition: all 0.2s ease;
}
.card-active {
border-color: #42b883;
}
.status-warning {
background-color: #fef3c7;
}
.status-error {
background-color: #fee2e2;
}
</style>
:class or :style, keys with hyphens like 'font-size' or 'text-danger' must be wrapped in quotes. Unquoted hyphens cause a JavaScript syntax error.:style: Writing fontSize: 18 without 'px' is ignored by browsers for length properties. Always include units like fontSize.value + 'px'.:style for Static Rules: Put static layout rules in <style scoped> CSS classes and reserve :style for truly dynamic numbers like coordinates, widths, or theme colors.class and dynamic :class on one element?Yes. Vue merges <div class="card" :class="{ active: isActive }"> automatically so card stays on the element even when isActive becomes false.
:style properties?Yes. When you bind a CSS property in :style that needs a browser prefix, Vue checks support at runtime and applies the right prefix automatically.
:style objects?CamelCase like backgroundColor works without quotes and feels natural in JavaScript. Quoted kebab-case like 'background-color' also works if you prefer standard CSS names.
Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.
Quick Access With