Vue.js: Class & Style Binding

Last updated: 2026-10-20

:class and :style are Vue's two most-used bindings — they let you switch CSS class names and inline styles dynamically based on data. They are really two special forms of v-bind; because they are used so often, they were wrapped up as "syntactic sugar".

Five forms cover 95% of cases: object syntax, array syntax, ternaries, computed properties, and string concatenation.

1. What You'll Learn


2. A Style Problem with Order Status Badges

(1) The Pain: 5 Statuses, 5 if Checks

Alice needs to show 5 order statuses in different colors in the admin:

HTML
<!-- ❌ The broken version: five v-if branches adding classes -->
<span v-if="status === 'pending'" class="badge yellow">Pending</span>
<span v-else-if="status === 'paid'" class="badge green">Paid</span>
<span v-else-if="status === 'shipped'" class="badge blue">Shipped</span>
<span v-else-if="status === 'delivered'" class="badge gray">Delivered</span>
<span v-else class="badge red">Cancelled</span>

Product manager Charlie:

"Alice, this is ugly. What happens when we add 3 more statuses next month? You can't keep copy-pasting. We need a clean dynamic approach."

(2) The Vue :class Solution: 1 Line for 5 Statuses

(3) The Payoff


3. :class: 5 Syntax Forms

(1) String Syntax

(2) Object Syntax (Most Common)

(3) Array Syntax

(4) Coexisting with a Static class

(5) class on Components

▶ Example: 5 :class Syntax Forms

▶ Try it Yourself

Output:

TEXT
Five lines, each a different class combination: badge, active, active error, active (the disabled class is absent because canEdit is true), and active from the computed object.
TEXT
1. String              → class="badge"
2. Object              → class="active"
3. Array               → class="active error"
4. Array + object      → class="active"
5. Computed property   → class="active"

4. :style: 5 Syntax Forms

(1) Object Syntax

(2) CSS Property Name Conversion

Vue converts JS naming to CSS naming automatically:

(3) Array Syntax (Merging Objects)

(4) Automatic Prefixing

Vue 3 adds browser prefixes to CSS properties automatically (decided by the browser engine):

JS
// You write:
{ transform: 'rotate(45deg)' }

// Vue adds:
{
  -webkit-transform: 'rotate(45deg)',
  transform: 'rotate(45deg)'
}

▶ Example: 5 :style Syntax Forms

▶ Try it Yourself

Output:

TEXT
Five stacked rows. Row 1 is red 16px text; row 2 has a green background and 20px padding;
row 3 merges to white text on a green background; row 4 exposes --theme-color: #35495e;
row 5 renders white text on a dark blue background with 20px padding.
TEXT
1. Basic object          red, 16px
2. Multiple properties   #42b883 background, 20px padding
3. Array merge           white text, #42b883 background
4. CSS variable          --theme-color: #35495e
5. Computed property     white text on #35495e, 20px padding

5. Complete Example: Dynamic Order Status

▶ Example: Order Status Badge (5-State Toggle)

▶ Try it Yourself

Output:

TEXT
A yellow Pending badge appears by default.
Clicking each button swaps both the label and the background color: Paid green, Shipped blue, Delivered gray, Cancelled red.
TEXT
[ Pending ]   ← yellow background
[ Paid ]      ← green background
[ Shipped ]   ← blue background
[ Delivered ] ← gray background
[ Cancelled ] ← red background

(1) 📊 5 Common Mistakes

Mistake Symptom Fix
String class does not react Hard-coded class never switches Bind it with :class
Misspelled array classes Duplicate classes override each other Use object syntax
Missing style units The number 16 is not treated as 16px Write the string '16px'
Wrong CSS property name font-size needs to be fontSize Use camelCase or quotes
:class conflicts Static + dynamic share a name Vue merges them, so it is fine

(2) 📊 5 Performance Comparisons

Form Compiled output Performance Good for
String Direct string concatenation ⭐⭐⭐⭐⭐ Simple
Object Static analysis ⭐⭐⭐⭐ Medium
Array String concatenation ⭐⭐⭐⭐ Multiple classes
Array + object Mixed processing ⭐⭐⭐ Complex
Computed property Cached value ⭐⭐⭐⭐⭐ Complex logic

(3) 📊 class vs style, 5 Key Differences

Dimension class style
Recommendation ⭐⭐⭐⭐⭐ ⭐⭐⭐
CSS reuse Easy (reuse class names) Hard (styles scatter)
Performance Higher (browser optimizations) Slightly lower
Priority Depends on the selector Inline (highest)
Theme switching Easy (swap classes) Easy (swap CSS variables)

❓ FAQ

Q Can class and style bindings coexist?
A Yes. A static class="x" plus a dynamic :class="{active: y}" merges automatically (the final class is "x active" or "x").
Q Why should style be an object instead of a CSS string?
A You can use a string: <div style="color: red"> is native HTML, and <div :style="'color: red'"> also works. But an object like :style="{ color: 'red' }" can bind variables dynamically. Objects are recommended.
Q How do CSS variables work?
A Put {'--my-var': value} in :style and use var(--my-var) in CSS. Vue 3 recommends CSS variables for theming because they are more efficient than binding styles directly — only one variable changes and the DOM does not reflow.
Q How does a component receive an external class?
A A single-root component inherits the class attribute automatically (Vue 3 default). For multi-root components, bind $attrs.class to a specific element explicitly.
Q What order do classes from array syntax follow?
A They are concatenated in array order, but the order does not affect CSS priority (priority comes from selector specificity).
Q Can I use :class with v-if?
A Yes. With <div v-if="show" :class="{ active: isActive }">, the element is not rendered at all when show is false, so isActive has no effect either.
Q How do I implement dynamic theme switching?
A CSS variables are the recommendation. Bind :style="{ '--primary': theme.primary }" and use color: var(--primary) everywhere. Switching themes changes a single variable instead of 100 classes.

📖 Summary


📝 Exercises

  1. Basic (⭐) Use :class object syntax to implement 3 button states:

    • primary: blue background, white text
    • success: green background, white text
    • danger: red background, white text

    Data: const variant = ref('primary')

  2. Intermediate (⭐⭐) Build an order list where each row shows a colored badge based on the order status:

    • 5 statuses (pending/paid/shipped/delivered/cancelled)
    • Use a computed property to return the class object
    • Use :style to set the icon color for each status
  3. Challenge (⭐⭐⭐) Build a complete theme-switching system:

    1. 3 themes (light/dark/high-contrast)
    2. Bind the theme colors with CSS variables (primary/secondary/background/text)
    3. Switch the theme class name with :class
    4. Remember the user's choice in localStorage
    5. Switch themes without reloading the page (reactive updates)
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏