: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.
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" />