Class and Style Bindings

Beginner
10 min

Class and Style Bindings

Changing CSS classes and inline styles in response to state is one of the most common things a UI does. Because manipulating class strings by hand is error-prone, v-bind gives class and style special treatment: they accept objects and arrays, and Vue merges them with any static values. After this lesson you will toggle classes, build class lists from data, and set inline styles safely.

Object Syntax for Classes

Pass an object whose keys are class names and whose values are booleans. A class is applied when its value is truthy:

vue
<script setup> import { ref } from 'vue' const isActive = ref(true) const hasError = ref(false) </script> <template> <div class="card" :class="{ active: isActive, 'text-danger': hasError }"> Order #1042 </div> </template>

Rendered output: <div class="card active">. The static class="card" is kept and the dynamic classes are appended. When hasError becomes true, the element gets text-danger too; when isActive becomes false, active is removed. Class names containing hyphens must be quoted as object keys.

For anything beyond two or three conditions, move the object into a computed property so the template stays readable and the object is cached:

javascript
const cardClass = computed(() => ({ active: isActive.value, 'text-danger': hasError.value, 'is-loading': status.value === 'loading' }))

Then bind it with :class="cardClass".

Array Syntax for Classes

An array applies every class it contains. This is convenient when the class names themselves come from data, and you can mix in objects or ternaries for conditional entries:

vue
<template> <button :class="[variant, size, { disabled: isDisabled }]">Save</button> <p :class="[isUrgent ? 'text-red' : 'text-gray', 'mt-2']">Reminder</p> </template>

With variant = 'btn-primary' and size = 'btn-lg', the button renders as class="btn-primary btn-lg", plus disabled when isDisabled is true.

Binding Inline Styles

:style accepts an object of CSS properties. Use camelCase keys (fontSize) or quoted kebab-case keys ('font-size'). Values that are numbers do not receive units automatically, so add them yourself:

vue
<script setup> import { ref } from 'vue' const size = ref(18) const color = ref('#1a73e8') </script> <template> <p :style="{ fontSize: size + 'px', color: color }">Styled text</p> <p :style="[baseStyles, overrides]">Merged styles</p> </template>

The array form merges several style objects, later entries winning. Vue also handles vendor prefixes automatically and accepts an array of values for a property (display: ['-webkit-box', 'flex']) so the browser can pick the last one it supports.

Inline styles are best for values that are genuinely computed at runtime, such as a progress-bar width or a user-chosen color. For anything static, prefer a class.

Class Bindings on Components

When you set class or :class on a component tag, the classes are added to the component's root element and merged with the classes that element already has. If the component has multiple root nodes, you must tell it which one should receive them via $attrs.class:

vue
<!-- Child with two roots --> <template> <p :class="$attrs.class">Title</p> <p>Body</p> </template>

Fallthrough attributes are covered in more detail in the component library lesson.

Tips

  • Prefer object syntax for toggling and array syntax for lists of names coming from data.
  • Keep the class expression short; if it needs logic, use a computed.
  • CSS custom properties can be bound too: :style="{ '--accent': accent }" lets your stylesheet use var(--accent).
  • Use CSS transitions on the classes you toggle to animate state changes without JavaScript.
Quick Quiz
Question 1 of 2

What does `<div class="card" :class="{ active: isActive }">` render when `isActive` is `false`?

Key Takeaways

  • :class accepts an object ({ name: condition }) or an array of names; static class is always merged in.
  • Move complex class logic into a computed property.
  • :style takes an object with camelCase keys; include units in the value.
  • Style arrays merge multiple objects, later ones overriding earlier ones.
  • Classes set on a component tag land on its root element, or on $attrs.class for multi-root components.

Next lesson: Handling Events — respond to clicks, keyboard input and form events with v-on and its modifiers.

Class and Style Bindings - Vue.js | CodeYourCraft | CodeYourCraft