Alpine.js
Alpine.js cheat sheet with directives, x-data, x-bind, x-on, transitions, and code examples for building lightweight interactive UIs.
6 min read
alpinejsjavascriptfrontendreactivedirectivesuiframeworklightweight
Loading your progress
Getting Started
Add Alpine.js to your project via CDN or npm
html
<!-- CDN (Recommended for quick start) -->
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<!-- NPM Installation -->
npm install alpinejs
// Import in your bundle
import Alpine from 'alpinejs'
Alpine.start()✅ Use defer attribute to ensure Alpine loads after DOM
💡 CDN is perfect for prototyping and small projects
🔍 NPM install gives you more control and build optimization
⚡ Minified CDN version is only ~15KB gzipped
installationsetupcdnnpm
Define reactive data for your Alpine component
html
<div x-data="{ open: false, count: 0 }">
<button @click="open = !open">Toggle</button>
<button @click="count++">Increment</button>
<div x-show="open">
Content is visible! Count: <span x-text="count"></span>
</div>
</div>✅ x-data creates a new Alpine component scope
💡 All child elements can access the reactive data
🔍 Use functions for reusable component logic
⚡ Changes to data automatically update the DOM
x-datastatereactivecomponent
Directives - Data Display
Set text content of an element reactively
html
<div x-data="{ message: 'Hello Alpine!' }">
<p x-text="message"></p>
<!-- Output: Hello Alpine! -->
</div>✅ x-text sets innerText, automatically escaping HTML
💡 Safer than x-html for user-generated content
🔍 Supports any JavaScript expression
⚡ Updates automatically when data changes
x-textdata-bindingdisplay
Set HTML content of an element
html
<div x-data="{
content: '<strong>Bold text</strong>'
}">
<div x-html="content"></div>
<!-- Output: Bold text (rendered as HTML) -->
</div>⚠️ Only use x-html with trusted content - XSS risk
💡 Prefer x-text unless you specifically need HTML
✅ Useful for rendering rich content from CMS
🔍 Sets innerHTML, so all HTML tags are parsed
x-htmlhtmlrendersecurity
Show or hide elements based on conditions
html
<div x-data="{ open: false }">
<button @click="open = !open">Toggle</button>
<div x-show="open">
This content toggles visibility
</div>
</div>✅ Uses CSS display property (element stays in DOM)
💡 Better for frequently toggled content than x-if
🔍 Combine with x-transition for smooth animations
⚡ Element is hidden but still rendered in HTML
x-showvisibilitytoggleconditional
Directives - User Interaction
Attach event listeners to elements (shorthand: @)
html
<div x-data="{ count: 0 }">
<!-- Longhand syntax -->
<button x-on:click="count++">Increment</button>
<!-- Shorthand @ syntax (recommended) -->
<button @click="count++">Increment</button>
<p x-text="count"></p>
</div>✅ @ is shorthand for x-on: (use @ for cleaner code)
💡 Modifiers like .prevent, .stop work like Vue.js
🔍 Access event object with $event magic property
⚡ Built-in modifiers: .debounce, .throttle, .once, .outside
x-oneventsclicklisteners@
Bind form inputs to data with automatic sync
html
<div x-data="{ message: 'Hello' }">
<input type="text" x-model="message">
<p x-text="message"></p>
</div>✅ Two-way binding: input changes update data and vice versa
💡 Works with text, checkbox, radio, select elements
🔍 Modifiers: .lazy (on change), .number, .debounce
⚡ Automatically handles different input types correctly
x-modelformsbindinginput
Dynamically bind HTML attributes (shorthand: :)
html
<div x-data="{ isActive: true }">
<!-- Longhand -->
<div x-bind:class="isActive ? 'active' : ''">Content</div>
<!-- Shorthand : (recommended) -->
<div :class="isActive ? 'active' : ''">Content</div>
</div>✅ : is shorthand for x-bind: (use : for cleaner code)
💡 Class binding accepts object syntax for multiple classes
🔍 Can bind any HTML attribute: href, src, disabled, etc.
⚡ Use x-bind (no attribute) to spread multiple attributes
x-bindattributesclassstyle:
Directives - Control Flow
Conditionally add/remove elements from DOM
html
<div x-data="{ show: false }">
<template x-if="show">
<div>This is conditionally rendered</div>
</template>
</div>✅ Must be used on <template> tag
💡 Completely removes element from DOM when false
🔍 Use for expensive components that rarely show
⚡ x-show is better for frequently toggled content
x-ifconditionaltemplaterendering
Render lists of elements from arrays
html
<div x-data="{
items: ['Apple', 'Banana', 'Cherry']
}">
<template x-for="item in items" :key="item">
<li x-text="item"></li>
</template>
</div>✅ Must be used on <template> tag
💡 Always provide :key for optimal performance
🔍 Access index with (item, index) in items syntax
⚡ Automatically updates when array changes
x-forlooplistsiterationtemplate
Advanced Features
Reference DOM elements within your component
html
<div x-data>
<input x-ref="username" type="text">
<button @click="$refs.username.focus()">
Focus Input
</button>
</div>✅ Access elements via $refs magic property
💡 No need for getElementById or querySelector
🔍 Scoped to component - no global pollution
⚡ Useful for focusing inputs, measuring elements, etc.
x-refrefsdomelements
Add smooth transitions when elements appear/disappear
html
<div x-data="{ open: false }">
<button @click="open = !open">Toggle</button>
<div x-show="open" x-transition>
Animated content
</div>
</div>✅ Works seamlessly with x-show and x-if
💡 Default transition is a simple fade
🔍 Modifiers: .opacity, .scale, .duration.XXXms
⚡ Use detailed classes for complete control over animation
x-transitionanimationstransitionseffects
Access special Alpine.js magic properties
html
<div x-data>
<!-- $el - Current element -->
<button @click="$el.remove()">
Remove This Button
</button>
<!-- $refs - Element references -->
<input x-ref="email">
<button @click="$refs.email.focus()">
Focus
</button>
</div>✅ $el references the current component root element
💡 $refs accesses all elements with x-ref
🔍 Other magic: $watch, $dispatch, $nextTick, $store
⚡ Use $ prefix for all Alpine magic properties
magic-properties$el$refs$watch$dispatch
Prevent flash of unstyled content before Alpine loads
html
<!-- Add to your CSS -->
<style>
[x-cloak] {
display: none !important;
}
</style>
<!-- Use on Alpine components -->
<div x-data="{ message: 'Hello' }" x-cloak>
<p x-text="message"></p>
</div>✅ Prevents template syntax from showing before Alpine loads
💡 Add CSS rule [x-cloak] { display: none !important; }
🔍 Alpine removes x-cloak attribute when initialized
⚡ Essential for production to avoid flickering
x-cloakloadingfoucinitialization