Description: The x-bind directive in AlpineJS allows you to dynamically set HTML element attributes. This is incredibly useful for making your UI responsive to your component's data. You can bind attributes like class, style, disabled, src, value, href, alt, and many more, based on reactive data properties or JavaScript expressions.
x-bind:attributeName="propertyNameOrExpression"
This is the explicit way to bind an attribute. For example, to bind an image's src attribute to a data property named imageUrl, you would write:
<img x-bind:src="imageUrl" alt="Dynamic Image">
:attributeName="propertyNameOrExpression"
For conciseness, AlpineJS offers a shorthand, similar to Vue.js. The colon (:) prefixing the attribute name indicates it's bound. The previous example can be written as:
<img :src="imageUrl" alt="Dynamic Image">
:class="{ 'css-class-name': booleanCondition, ... }"
This is a powerful way to conditionally apply CSS classes. The object's keys are class names, and their values are boolean expressions. If an expression evaluates to true, the class is applied; otherwise, it's not.
<div :class="{ 'text-red-500': hasError, 'bg-blue-200 p-4': isActive }">Message</div>
You can also mix this with static classes:
<div class="base-styles" :class="{ 'active': isActive }">...</div>
And use an array for more complex scenarios:
<div :class="['base-class', { 'active': isActive }, statusClass]">...</div>
(where statusClass is a data property holding a class name string).
style Attribute: :style="{ cssProperty: 'value', ... }"
You can bind an object to the style attribute to dynamically set inline styles. CSS property names can be camelCased (e.g., fontSize) or kebab-cased in quotes (e.g., 'font-size').
<p :style="{ color: textColor, fontSize: textSize + 'px' }">Styled Text</p>
x-bind:value and x-model:
x-bind:value="dataProperty" sets up one-way data binding from your Alpine component's data to an input element's value attribute. If dataProperty changes, the input's value updates. However, user typing into the input field will not automatically update dataProperty.
For two-way data binding on form inputs (<input>, <textarea>, <select>), where user interaction updates the data property and vice-versa, you should use x-model="dataProperty" instead.
<!-- One-way binding: data -> input -->
<input type="text" :value="message">
<!-- Two-way binding: data <-> input -->
<input type="text" x-model="message">
The object syntax :class="{ 'my-class': condition }" is the correct way for conditional classes. A common mistake is trying to use a colon within the class attribute value like class="my-class: condition" or some other non-standard format. Always use the JavaScript object syntax where keys are class names and values are boolean conditions.
<!-- Correct -->
<div :class="{ 'is-active': isActive, 'has-error': anErrorOccurred }">...</div>
<!-- Incorrect -->
<!-- <div class="is-active: isActive has-error: anErrorOccurred">...</div> -->
disabled, required, readonly) not working as expected:
For boolean HTML attributes, AlpineJS follows the HTML standard behavior. If the bound expression evaluates to true (or any truthy value), the attribute is added to the element (e.g., <button disabled>). If the expression evaluates to false, null, or undefined, the attribute is removed from the element entirely. This is usually what you want.
For example, <button :disabled="isLoading"> will become <button disabled> if isLoading is true, and just <button> if isLoading is false.
It might be confusing if you expect to see disabled="false" literally in the HTML, but browsers interpret the mere presence of a boolean attribute (like disabled) as true and its absence as false.
<!-- If 'isProcessing' is true, button becomes: <button disabled>Submit</button> -->
<!-- If 'isProcessing' is false, button becomes: <button>Submit</button> -->
<button :disabled="isProcessing">Submit</button>
:src and :alt for an ImageCurrent image:
:classCurrent classes object:
:styleThis text's style is bound to the inputs above.
Current style object:
:disabled)Button is . Attribute disabled is .
:valueThis input's value is bound one-way from the profileName data. Typing in it won't change profileName. Use x-model for two-way binding.
profileName data: ""