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>
Note: Tip: when a class or style condition depends on more than one piece of data, move the logic into a computed property that returns the object or array. Templates stay readable, and Vue still caches the result until a dependency changes.
SituationRecommended syntaxExample
Toggling one or two classes on/offObject syntax:class="{ active: isActive }"
Combining static classes with conditionsArray syntax:class="[baseClass, { active: isActive }]"
Setting several CSS properties at onceStyle object:style="{ color: 'red', fontSize: '14px' }"
Merging shared styles with one-off overridesStyle array:style="[baseStyle, overrideStyle]"
Note: Warning: CSS property names in style objects must be camelCase or quoted kebab-case. An unquoted kebab-case key like background-color is invalid JavaScript object syntax and will fail to compile.

Exercise: Vue CSS Binding

In Vue's object syntax for class binding (:class="{ active: isActive }"), when is the 'active' class applied?