Vue.js Attribute Binding
Double curly braces {{ }} place data into the text of an element. But HTML attributes — like href, src, class, and disabled — live inside the opening tag, not in the content area. Vue's attribute binding connects your data to these attributes using the v-bind directive.
Why {{ }} Does Not Work in Attributes
This code does not work:
<!-- WRONG: Curly braces inside an attribute -->
<a href="{{ url }}">Visit Page</a>
<!-- Vue will not process this. The browser literally shows: -->
<a href="{{ url }}">Visit Page</a>
For attributes, you must use v-bind:
<!-- CORRECT --> <a v-bind:href="url">Visit Page</a>
Diagram: Text Interpolation vs Attribute Binding
Element structure:
<tagname attribute="value"> content </tagname>
│ │
│ └── Use {{ }} here
└── Use v-bind: here
Example:
<a v-bind:href="url">{{ linkText }}</a>
│ │
│ └── {{ }} fills in the text
└── v-bind: fills in the attribute value
Basic v-bind Usage
<div id="app">
<a v-bind:href="websiteUrl">Go to Website</a>
<img v-bind:src="imageUrl" v-bind:alt="imageCaption">
</div>
<script>
Vue.createApp({
data() {
return {
websiteUrl: "https://example.com",
imageUrl: "https://example.com/photo.jpg",
imageCaption: "A sample photo"
};
}
}).mount("#app");
</script>
Vue replaces the attribute values with the actual data from data(). When the data changes, the attribute updates instantly.
The Shorthand — Using Colon Only
Writing v-bind: for every attribute is repetitive. Vue provides a shorthand: just use a colon : instead of v-bind:.
<!-- Full syntax --> <a v-bind:href="url">Link</a> <!-- Shorthand (same result) --> <a :href="url">Link</a>
Most Vue developers use the colon shorthand. Both work the same way.
Binding the class Attribute
The class attribute is special in Vue because you can bind it dynamically using an object or an array.
Object Syntax — Turn Classes On and Off
Use an object where each key is a class name and the value is a true/false condition. Vue adds the class when the value is true and removes it when false.
<div id="app">
<p :class="{ active: isActive, error: hasError }">
Status message
</p>
<button @click="isActive = !isActive">Toggle Active</button>
</div>
<script>
Vue.createApp({
data() {
return {
isActive: false,
hasError: true
};
}
}).mount("#app");
</script>
Diagram: Class Object Binding
:class="{ active: isActive, error: hasError }"
isActive = false, hasError = true
→ class="error" (active removed, error added)
isActive = true, hasError = true
→ class="active error" (both added)
isActive = true, hasError = false
→ class="active" (error removed)
isActive = false, hasError = false
→ class="" (no classes)
Array Syntax — Always Apply Multiple Classes
Use an array to apply a fixed list of classes from data properties.
data() {
return {
baseClass: "card",
themeClass: "dark-theme"
};
}
<div :class="[baseClass, themeClass]">Content</div>
<!-- Renders as: <div class="card dark-theme"> -->
Mixing Static and Dynamic Classes
You can combine a fixed class attribute with a dynamic :class binding on the same element. Vue merges them.
<div class="box" :class="{ highlight: isHighlighted }">
Content
</div>
<!-- When isHighlighted = true: -->
<div class="box highlight">Content</div>
<!-- When isHighlighted = false: -->
<div class="box">Content</div>
Binding the style Attribute
You can bind inline styles using an object. The object keys are CSS property names (in camelCase) and the values come from your data.
<div id="app">
<p :style="{ color: textColor, fontSize: textSize + 'px' }">
Styled Text
</p>
</div>
<script>
Vue.createApp({
data() {
return {
textColor: "blue",
textSize: 20
};
}
}).mount("#app");
</script>
Diagram: Style Binding Mapping
data:
textColor = "blue"
textSize = 20
Template:
:style="{ color: textColor, fontSize: textSize + 'px' }"
Rendered attribute:
style="color: blue; font-size: 20px;"
Binding Boolean Attributes
Some HTML attributes are boolean — they either exist on the element or they don't. Examples: disabled, checked, readonly. Vue handles these correctly when you bind them.
<div id="app">
<button :disabled="isButtonDisabled">Submit</button>
</div>
<script>
Vue.createApp({
data() {
return { isButtonDisabled: true };
}
}).mount("#app");
</script>
Diagram: Boolean Attribute Behavior
isButtonDisabled = true → <button disabled>Submit</button> (button is grayed out) isButtonDisabled = false → <button>Submit</button> (disabled attribute removed)
Vue removes the attribute entirely when the value is false, null, or undefined. It adds it when the value is truthy.
Binding Multiple Attributes at Once
You can bind an entire object of attributes to an element using v-bind without specifying an argument.
data() {
return {
linkAttrs: {
href: "https://example.com",
target: "_blank",
title: "Open in new tab"
}
};
}
<a v-bind="linkAttrs">External Link</a>
<!-- Renders as: -->
<a href="https://example.com" target="_blank" title="Open in new tab">
External Link
</a>
Dynamic Attribute Names
In Vue 3, you can also make the attribute name itself dynamic by wrapping it in square brackets.
data() {
return {
attrName: "title",
attrValue: "This is a tooltip"
};
}
<p :[attrName]="attrValue">Hover over me</p>
<!-- Renders as: -->
<p title="This is a tooltip">Hover over me</p>
Practical Example: Product Card
Here is a real-world example combining multiple types of attribute binding:
<div id="app">
<div class="product-card" :class="{ 'out-of-stock': !inStock }">
<img :src="imageUrl" :alt="productName">
<h3>{{ productName }}</h3>
<p :style="{ color: inStock ? 'green' : 'red' }">
{{ inStock ? 'Available' : 'Out of Stock' }}
</p>
<button :disabled="!inStock">Add to Cart</button>
</div>
</div>
<script>
Vue.createApp({
data() {
return {
productName: "Wireless Mouse",
imageUrl: "mouse.jpg",
inStock: false
};
}
}).mount("#app");
</script>
Diagram: Product Card Output When Out of Stock
inStock = false ┌──────────────────────────────────────────┐ │ class="product-card out-of-stock" │ │ ┌───────────────────────────┐ │ │ │ [image of Wireless Mouse] │ │ │ └───────────────────────────┘ │ │ Wireless Mouse │ │ Out of Stock (red color) │ │ [Add to Cart] ← button is disabled │ └──────────────────────────────────────────┘
Summary
Attribute binding uses v-bind: (or the shorthand :) to connect data to HTML attributes. You bind href, src, alt, and other standard attributes directly to data values. The class binding accepts objects (for toggling) and arrays (for combining). The style binding accepts a CSS property object. Boolean attributes like disabled appear or disappear automatically based on the truthy or falsy value of the bound data.
