DEV Community

Alex Spinov
Alex Spinov

Posted on

Alpine.js Has a Free API: Add Interactivity to HTML Without a Build Step

You don't need React for a dropdown menu. You don't need Vue for a tab component. You need Alpine.js.

What Is Alpine.js?

Alpine.js is a lightweight JavaScript framework for composing behavior directly in HTML. Think of it as Tailwind for JavaScript.

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>

<div x-data="{ open: false }">
  <button @click="open = !open">Toggle</button>
  <div x-show="open" x-transition>
    Hello! I'm a dropdown.
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

That's a complete interactive component. No npm. No build. No bundler.

Core Directives

<!-- Reactive data -->
<div x-data="{ count: 0 }">
  <span x-text="count"></span>
  <button @click="count++">+</button>
</div>

<!-- Conditional rendering -->
<div x-data="{ show: false }">
  <div x-show="show" x-transition>Visible when show=true</div>
  <template x-if="show"><p>Rendered conditionally</p></template>
</div>

<!-- Loops -->
<div x-data="{ items: ['Apple', 'Banana', 'Cherry'] }">
  <template x-for="item in items" :key="item">
    <li x-text="item"></li>
  </template>
</div>

<!-- Two-way binding -->
<div x-data="{ search: '' }">
  <input x-model="search" placeholder="Search...">
  <p>You typed: <span x-text="search"></span></p>
</div>
Enter fullscreen mode Exit fullscreen mode

Real Example: Tabs Component

<div x-data="{ tab: 'home' }">
  <nav>
    <button @click="tab = 'home'" :class="{ 'active': tab === 'home' }">Home</button>
    <button @click="tab = 'about'" :class="{ 'active': tab === 'about' }">About</button>
    <button @click="tab = 'contact'" :class="{ 'active': tab === 'contact' }">Contact</button>
  </nav>
  <div x-show="tab === 'home'">Home content</div>
  <div x-show="tab === 'about'">About content</div>
  <div x-show="tab === 'contact'">Contact content</div>
</div>
Enter fullscreen mode Exit fullscreen mode

In React, this would be a component file, useState, onClick handlers, conditional rendering, CSS modules. In Alpine: one HTML block.

Fetching Data

<div x-data="{ users: [] }" x-init="users = await (await fetch('/api/users')).json()">
  <template x-for="user in users" :key="user.id">
    <div x-text="user.name"></div>
  </template>
</div>
Enter fullscreen mode Exit fullscreen mode

Why Alpine.js

  • 7KB gzipped (React + ReactDOM = 172KB)
  • Zero build step — CDN script tag and go
  • Perfect with server-rendered HTML — Django, Rails, Laravel, Go templates
  • Tailwind CSS companion — same philosophy: utility-first, in your HTML
  • Learn in 15 minutes — 15 directives, 6 properties, 2 methods. That's the whole API.

Building web tools or need data solutions? Check out my developer toolkit or email spinov001@gmail.com.

Top comments (0)