Description: The x-bind directive in AlpineJS is your primary tool for dynamically setting HTML attributes. It allows you to link an attribute's value directly to a property in your component's data or to the result of a JavaScript expression. This is fundamental for creating responsive and interactive user interfaces by controlling attributes such as class, style, disabled, src, or value based on reactive data.
x-bind:attributeNameThe basic syntax is x-bind:attributeName="propertyNameOrExpression". For example, to bind an image's src attribute to an imageUrl data property:
<img x-bind:src="imageUrl" alt="Dynamic Image">
:attributeNameAlpineJS offers a convenient shorthand for x-bind. You can simply prefix the attribute name with a colon (:):
<img :src="imageUrl" alt="Dynamic Image">
This shorthand is widely used and makes templates cleaner and more readable.
:class):Binding classes conditionally is a common task. Alpine provides a powerful object syntax for :class. Keys are class names (as strings), and values are boolean expressions. If an expression evaluates to true, the corresponding class is applied. If false, it's removed (if it was previously added by this binding).
<div :class="{ 'text-red-500': hasError, 'bg-blue-200': isActive, 'font-bold': user.isAdmin }">
This text might be red, have a blue background, or be bold.
</div>
You can also mix this with static classes: <div class="base-styles" :class="{ 'active': isActive }">...</div>. Alpine can also handle arrays of classes or objects: <div :class="['p-4', { 'text-red-500': hasError }]">...</div>.
style Attribute (:style):You can bind an object to the style attribute to dynamically set inline CSS styles. Property names in the object can be camelCased (e.g., backgroundColor) or kebab-cased in quotes (e.g., 'background-color').
<p :style="{ color: textColor, fontSize: textSize + 'px', 'font-weight': isImportant ? 'bold' : 'normal' }">
Dynamic styles applied here.
</p>
In this example, textColor, textSize, and isImportant would be reactive properties in your Alpine component's data.
x-bind:value and x-model:
x-bind:value="myProperty" sets an input's value attribute based on myProperty. This is a one-way binding: changes to myProperty in your Alpine data will update the input's displayed value. However, if the user types into the input, myProperty will not automatically update.
If you need two-way binding for form inputs (where user input also updates the Alpine data property, and changes to the property update the input), you should use x-model="myProperty" instead. x-model is specifically designed for form elements like <input>, <select>, and <textarea>.
<!-- One-way: data -> input value -->
<input type="text" :value="message">
<!-- Two-way: data <-> input value -->
<input type="text" x-model="message">
The object syntax for conditional classes (:class="{ 'my-class': condition }") is powerful but requires correct syntax. The condition must be a JavaScript expression that evaluates to a boolean (true or false).
A common mistake is trying to use a colon inside the class attribute value differently, like class="my-class: condition" or trying to put the condition directly in the class string without the object syntax. These are incorrect and will not work as expected.
<!-- Correct object syntax -->
<div :class="{ 'is-active': user.active, 'has-error': form.errors.length > 0 }">...</div>
<!-- Incorrect (common mistakes) -->
<!-- <div class="is-active: user.active">...</div> -->
<!-- <div class="{if (user.active) 'is-active'}">...</div> -->
Always use the curly braces {} for the object, class names as string keys (quoted if they contain hyphens or other special characters), and boolean values/expressions as values.
disabled, required, readonly) not working as expected:
For HTML boolean attributes, AlpineJS follows the standard behavior: if the bound value is true (or any truthy value), Alpine will add the attribute to the element (e.g., <button disabled>).
If the bound value is false, null, or undefined (i.e., falsy values), Alpine will remove the attribute entirely from the element. For example, <button :disabled="false"> becomes <button>, not <button disabled="false">.
This is usually the desired behavior, as the mere presence of an attribute like disabled (regardless of its value) often enables it. However, it can be confusing if you're expecting to see disabled="false" literally in the DOM. The key is that the absence of the attribute means it's not active.
<button :disabled="isLoading">Submit</button>
<!-- If isLoading is true, button becomes: <button disabled>Submit</button> -->
<!-- If isLoading is false, button becomes: <button>Submit</button> -->
Loading item data...
:srcImage URL:
:class:style(Featured!)
:valueThis input uses :value="customMessage" and is readonly. It only reflects changes to customMessage from the component's data.
This input binds :value="customMessage" and uses @input="customMessage = $event.target.value" to update the data. This is how you'd manually create two-way binding; x-model="customMessage" does this automatically.
:disabledIf the checkbox is checked (isButtonDisabled is true), the button gets a disabled attribute. If unchecked (false), the attribute is removed.
:id, :title, :aria-*)div has several dynamically bound attributes:
data-custom-attribute: