Vue CSS Binding
Vue lets you toggle CSS classes and inline styles reactively by binding :class and :style directly to objects and arrays in your component data.
Why Dynamic Class and Style Binding Matters
In plain JavaScript, toggling a class based on state usually means building a string by hand, such as className = isActive ? 'item active' : 'item'. As the number of conditions grows, that string concatenation becomes hard to read and easy to break. Vue's :class and :style bindings replace manual string-building with objects and arrays, so class names and style properties turn on and off automatically whenever the underlying reactive data changes.
Object Syntax for :class
The most common form of :class binding passes an object whose keys are class names and whose values are boolean expressions. Vue adds a key to the element's class list only when its value is truthy, and removes it the moment the value becomes falsy - no manual DOM manipulation required.
Object syntax for :class
<div id="app">
<p :class="{ active: isActive, 'text-danger': hasError }">
Status message
</p>
<button @click="isActive = !isActive">Toggle Active</button>
<button @click="hasError = !hasError">Toggle Error</button>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const app = Vue.createApp({
data() {
return {
isActive: true,
hasError: false
}
}
})
app.mount('#app')
</script>Array Syntax for :class
Sometimes you want to apply a list of class names - some static, some conditional - without writing one large object literal. The array syntax lets you mix plain strings, data properties, and even object-syntax entries inside the same array, combining the flexibility of a list with the conditional power of objects.
Array syntax mixed with an object entry
<div id="app">
<p :class="[baseClass, sizeClass, { active: isActive }]">
Card content
</p>
<button @click="isActive = !isActive">Toggle</button>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const app = Vue.createApp({
data() {
return {
baseClass: 'card',
sizeClass: 'card-large',
isActive: false
}
}
})
app.mount('#app')
</script>- The static class attribute on an element is merged with the :class binding, not replaced by it.
- Object keys that contain a hyphen, like 'text-danger', must be written as quoted strings.
- Array entries can themselves be objects, letting you combine list order with conditional toggles.
- Both syntaxes work on components with a single root element, and Vue merges the resulting classes onto that root.
Binding Inline Styles with :style
:style accepts an object whose keys are CSS properties, written in camelCase (fontSize instead of font-size) or as quoted kebab-case strings. Vue writes each property directly onto the element's style attribute and updates it whenever the underlying value changes, without needing a dedicated CSS class for every possible visual state.
Style object, style array, and a computed style
<div id="app">
<p :style="titleStyle">Resizable heading</p>
<p :style="[baseStyle, { color: highlightColor }]">Combined styles</p>
<button @click="fontSize += 4">Increase Font Size</button>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const app = Vue.createApp({
data() {
return {
fontSize: 16,
highlightColor: 'crimson',
baseStyle: { padding: '8px', border: '1px solid #ccc' }
}
},
computed: {
titleStyle() {
return {
fontSize: this.fontSize + 'px',
fontWeight: 'bold'
}
}
}
})
app.mount('#app')
</script>Exercise: Vue CSS Binding
In Vue's object syntax for class binding (:class="{ active: isActive }"), when is the 'active' class applied?