v-bind — Class, Style & Attributes

:class & :style — Conditional CSS, Built-In

v-bind — Class, Style & Attributes

v-bind (shorthand :) binds any attribute to a dynamic value. Class and style get extra ergonomic syntax for objects and arrays.

4 min read Level 1/5 #vue#directives#binding
What you'll learn
  • Bind a string attribute
  • Use :class with object/array syntax
  • Use :style with camelCase keys

v-bind connects an HTML attribute to a JavaScript expression. The colon shorthand is what you will see most often in real codebases.

Binding Attributes

<script setup lang="ts">
import { ref } from 'vue'
const url = ref('/logo.png')
const disabled = ref(true)
</script>

<template>
  <img :src="url" alt="" />
  <button :disabled="disabled">Submit</button>
</template>

Boolean attributes (disabled, checked, readonly) are removed entirely when the bound value is falsy, which is what you want.

Class Binding

The :class binding accepts a string, an object (key is a class, value is a boolean), or an array mixing both.

<div :class="{ active: isActive, error: hasError }" />

<div :class="['btn', isPrimary ? 'btn-primary' : 'btn-secondary']" />

<div :class="['card', { selected: isSelected }]" />

Static classes coexist peacefully: <div class="card" :class="{ active }"> produces both classes.

Style Binding

:style takes an object with camelCase keys. Values can be strings or numbers (Vue does not auto-append px, you do).

<script setup lang="ts">
import { ref } from 'vue'
const color = ref('crimson')
const size = ref(18)
</script>

<template>
  <p :style="{ color, fontSize: size + 'px' }">Styled text</p>
</template>

Spread Binding

Without an argument, v-bind spreads an object across all attributes. Combined with $attrs this is how you forward props to a child element:

<input v-bind="$attrs" />
Slots — Let Parents Pass Markup →