Alpinejs Plugins
In this tutorial, you'll learn about Alpine.js plugins. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
Alpine.js plugins extend the framework with additional directives and magic properties, enabling features like data persistence, input masking, focus trapping, and scroll-based animations.
What You'll Learn
By the end of this tutorial, you'll use the Persist plugin for localStorage, Mask for input formatting, Focus for modals, Intersect for scroll animations, and Collapse for expandable sections.
Why It Matters
Alpine's core is intentionally minimal. Plugins add production-ready features without bloating every project. You install only what you need, keeping your pages fast and your code clean.
Real-World Use
Durga Antivirus Pro's settings page uses the Persist plugin to remember user preferences across sessions. The Focus plugin traps keyboard focus inside modal dialogs for Accessibility. The Collapse plugin animates expandable threat report sections.
Where This Fits in Your Learning Path
flowchart LR
A["Magics & Store"] --> B["**Alpine Plugins**"]
B --> C["Alpine Project"]
C --> D["Real Alpine Apps"]
style B fill:#f97316,stroke:#c2410c,color:#fff
style A fill:#e5e7eb,stroke:#9ca3af,color:#374151
style D fill:#22c55e,stroke:#16a34a,color:#fff
Installing Plugins
Plugins are loaded via separate script tags after the main Alpine script.
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/persist@3.x.x/dist/cdn.min.js"></script>
Persist Plugin
The $persist magic property saves values to localStorage automatically.
<div x-data="{ count: $persist(0), theme: $persist('light') }">
<p>Count: <span x-text="count"></span></p>
<p>Theme: <span x-text="theme"></span></p>
<button @click="count++">Increment</button>
<button @click="theme = theme === 'light' ? 'dark' : 'light'">Toggle Theme</button>
</div>
Expected output: Refresh the page. The count and theme persist across page loads.
Mask Plugin
The Mask plugin formats input values as the user types.
<div x-data>
<input x-mask="999-999-9999" placeholder="Phone: 123-456-7890" class="w-full p-2 border rounded">
<input x-mask="99/99/9999" placeholder="Date: MM/DD/YYYY" class="w-full p-2 border rounded mt-2">
</div>
Expected output: As the user types, the input is automatically formatted with dashes and slashes.
Focus Plugin
The Focus plugin traps keyboard focus inside an element, essential for accessible modals.
<div x-data="{ open: false }">
<button @click="open = true">Open Modal</button>
<div x-show="open"
@keydown.escape.window="open = false"
x-trap.noscroll="open"
class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center">
<div class="bg-white p-6 rounded-lg">
<h2>Modal Title</h2>
<p>Tab stays inside this modal.</p>
<button @click="open = false">Close</button>
</div>
</div>
</div>
Expected output: When the modal opens, Tab and Shift+Tab cycle through elements inside the modal only. The body scroll is disabled.
Intersect Plugin
The Intersect plugin triggers actions when elements enter the viewport, perfect for Lazy Loading and scroll animations.
<div x-data="{ visible: false }">
<div style="height: 100vh"></div>
<div x-intersect="visible = true" class="p-8 bg-blue-50 rounded">
<p x-show="visible" x-transition>This content fades in when you scroll to it</p>
</div>
</div>
Expected output: Scrolling down triggers the intersect event, making the content fade in.
Collapse Plugin
The Collapse plugin animates elements expanding and collapsing with smooth height transitions.
<div x-data="{ expanded: false }">
<button @click="expanded = !expanded">Toggle Details</button>
<div x-show="expanded" x-collapse.duration.300ms class="p-4 bg-gray-50 rounded mt-2">
<p>This content animates its height when shown and hidden.</p>
</div>
</div>
Expected output: Clicking the toggle smoothly animates the expansion and collapse of the content area.
Common Mistakes
1. Loading plugins but forgetting to install them via script tag
Each plugin requires its own CDN script tag. Missing plugins silently fail.
2. Using $persist without the Persist plugin loaded
$persist is undefined if the Persist plugin is not included. Always check the browser console for errors.
3. Applying x-mask after the user has already typed
Mask works on initial keystrokes. Applying it to an existing value may not format retroactively.
4. Using x-trap without noscroll on modals
Without .noscroll, the page behind the modal still scrolls, which is disorienting for users.
5. Not cleaning up Intersect observers
Alpine handles cleanup automatically for its plugins, but custom IntersectionObserver code in x-init needs manual cleanup.
Practice Questions
What does the Persist plugin do? It saves Alpine component state to localStorage so it survives page refreshes.
How do you prevent background scrolling when a modal is open? Use x-trap.noscroll on the modal container with the Focus plugin.
What is the Mask plugin used for? Formatting input values as the user types, like phone numbers, dates, and credit card numbers.
When would you use the Intersect plugin? For lazy-loading images, triggering animations on scroll, or loading content when it enters the viewport.
What does x-collapse animate? The height transition of an element when x-show toggles its visibility.
Challenge
Build a form with Persist (auto-save drafts), Mask (formatted phone and date inputs), and a confirmation dialog with Focus (trapped focus for accessibility). The form should restore its state on page reload.
FAQ
Mini Project
Build a settings panel that uses Persist for all preferences (theme, notifications, language), Mask for a phone number field, Focus for a confirmation dialog when resetting settings, and Collapse for expandable setting groups.
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/persist@3.x.x/dist/cdn.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/mask@3.x.x/dist/cdn.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/focus@3.x.x/dist/cdn.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/collapse@3.x.x/dist/cdn.min.js"></script>
<div x-data="{ settings: $persist({ theme: 'light', phone: '', lang: 'en', notifications: true }), confirmReset: false }" class="max-w-md mx-auto p-6 space-y-4">
<div x-data="{ open: true }">
<button @click="open = !open" class="font-bold">Appearance</button>
<div x-show="open" x-collapse>
<select x-model="settings.theme" class="w-full p-2 border rounded mt-2">
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</div>
</div>
<div x-data="{ open: false }">
<button @click="open = !open" class="font-bold">Contact</button>
<div x-show="open" x-collapse>
<input x-mask="(999) 999-9999" x-model="settings.phone" placeholder="(555) 123-4567" class="w-full p-2 border rounded mt-2">
</div>
</div>
<button @click="confirmReset = true" class="px-4 py-2 bg-red-500 text-white rounded">Reset All Settings</button>
<div x-show="confirmReset" x-trap.noscroll="confirmReset" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center">
<div class="bg-white p-6 rounded-lg">
<p class="mb-4">Are you sure?</p>
<button @click="settings = { theme: 'light', phone: '', lang: 'en', notifications: true }; confirmReset = false" class="px-4 py-2 bg-red-500 text-white rounded mr-2">Yes, Reset</button>
<button @click="confirmReset = false" class="px-4 py-2 bg-gray-200 rounded">Cancel</button>
</div>
</div>
</div>
What's Next
Build a complete application:
| Tutorial | What You'll Learn |
|---|---|
| Alpine Project | Build a complete real-world application with all Alpine features |
| Transitions and Plugins | Advanced animation patterns with x-transition |
Related topics: localStorage API, Intersection Observer.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro