※本記事には広告(楽天アフィリエイト)リンクが含まれる場合があります。

「ページ全体はサーバーサイドで描画したい。でも、モーダルやタブ、フォームの動的な挙動はJavaScriptで実現したい……」そんな時に重宝するのがAlpine.jsです。

Alpine.jsは15KB程度の軽量JavaScriptライブラリで、HTMLの属性にディレクティブを書くだけで、ReactやVueのようなリアクティブなUIを実装できます。ビルド不要でCDNから読み込むだけで動くため、個人開発のWebサイトや、先日紹介したHTMXと併用することで、フロントエンドの複雑化を避けながら動的な体験を提供できます。

本記事では、Alpine.jsの基本ディレクティブから、コンポーネント化、HTMXとの組み合わせ方、実践テクニックまでを、実際のコード付きで完全解説します。

広告・楽天アフィリエイト

プログラミング技術書

実践寄りの技術書・参考書を探す。

楽天ポイント還元

技術書を楽天で見る →

1. Alpine.jsとは?React・Vue・HTMXとの違い

Alpine.jsは、2020年に登場した「スプレッドシート並みにシンプルなReactの代替」をコンセプトとしたライブラリです。HTMLのタグに直接ディレクティブ(属性)を書くことで、状態管理・イベント処理・DOM操作を実現します。

項目 Alpine.js React / Vue HTMX
サイズ 約15KB(gzip) 100KB〜数MB 約14KB
ビルド 不要(CDNでOK) 必須(バンドラー) 不要(CDNでOK)
主な役割 クライアント側の状態・UI操作 SPA全体の構築 サーバーとのやり取り(AJAX)
書き方 HTML属性(x-data, x-show等) JSX / テンプレート構文 HTML属性(hx-get等)
学習コスト 低(HTML知識でOK)

ポイントは、HTMXとAlpine.jsは競合ではなく補完関係だということです。HTMXは「サーバーからHTMLを取得して差し替える」のが得意で、Alpine.jsは「クライアント側の状態を管理して表示を切り替える」のが得意です。この2つを組み合わせるのが、2026年の軽量フロントエンド構成の定番になりつつあります。

2. セットアップ:CDNでたった1行

Alpine.jsの導入は非常に簡単です。HTMLの<head>に1行追加するだけです。

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

npmで管理する場合は、以下のようにインストールしてimportします。

npm install alpinejs
# or
yarn add alpinejs
# or
pnpm add alpinejs
import Alpine from 'alpinejs'

window.Alpine = Alpine
Alpine.start()

使ってみた感想: 本当にCDNの1行で動きます。ビルド設定やトランスパイルが不要なので、静的サイトやWordPress、既存のレガシーなサーバーサイトにもそのまま差し込めるのが最大の魅力です。

3. 基本ディレクティブをマスターする

Alpine.jsの中心となるのは、x-datax-showx-bindx-onx-modelx-forx-textなどのディレクティブです。1つずつ見ていきましょう。

3.1 x-data:コンポーネントの状態を定義

x-dataでコンポーネントの状態(データ)を定義します。ここがAlpine.jsの「コンポーネントの境界」になります。

<div x-data="{ count: 0 }">
  <button x-on:click="count++">+1</button>
  <span x-text="count"></span>
</div>

3.2 x-text / x-html:テキストをバインド

x-textはテキストを、x-htmlはHTMLとして値を表示します。

<div x-data="{ name: 'TechTools' }">
  <p x-text="'ようこそ、' + name + 'さん'"></p>
</div>
<!-- 表示: ようこそ、TechToolsさん -->

3.3 x-show / x-if:表示・非表示の切り替え

x-showはCSSのdisplayで切り替え、x-ifはDOMから要素ごと削除します。頻繁に切り替えるものはx-show、条件に応じて作り分けたいものはx-ifを使うのがおすすめです。

<div x-data="{ open: false }">
  <button x-on:click="open = !open">メニュー</button>
  <div x-show="open" x-transition>
    ここが開閉します
  </div>
</div>

3.4 x-bind:属性を動的バインド

x-bindはHTML属性(class、style、disabledなど)を状態に応じて切り替えます。省略形は:です。

<div x-data="{ dark: false }">
  <button :class="dark ? 'btn-dark' : 'btn-light'" @click="dark = !dark">
    ダークモード切替
  </button>
</div>

上の例では、x-bind:class:classに、x-on:click@clickに省略しています。2026年現在、この省略記法が主流です。

3.5 x-model:フォームとの双方向バインディング

x-modelは、入力欄と状態を自動で同期させます。フォームを作るなら必須のディレクティブです。

<div x-data="{ email: '' }">
  <input type="email" x-model="email" placeholder="メールアドレス">
  <p x-text="'入力中: ' + email"></p>
</div>

チェックボックスやラジオ、セレクトにも対応しています。

<div x-data="{ plan: 'free', notice: true }">
  <select x-model="plan">
    <option value="free">Free</option>
    <option value="pro">Pro</option>
  </select>
  <label><input type="checkbox" x-model="notice"> 通知を受け取る</label>
  <p x-text="plan + ' / ' + (notice ? '通知ON' : '通知OFF')"></p>
</div>

3.6 x-for:リストをループ描画

x-forで配列をループしてリストを描画します。キー(:key)の指定を忘れないようにしましょう。

<div x-data="{ items: ['HTML', 'CSS', 'Alpine.js'] }">
  <ul>
    <template x-for="(item, i) in items" :key="i">
      <li x-text="i + 1 + '. ' + item"></li>
    </template>
  </ul>
</div>

4. イベント処理と非同期(fetch)連携

x-onでイベントを処理します。@click@submit@keydown.enterなど、イベント修飾子も豊富に用意されています。

<div x-data="{ keyword: '', results: [], loading: false }">
  <form @submit.prevent="search()">
    <input x-model="keyword" placeholder="検索ワード">
    <button type="submit" :disabled="loading" x-text="loading ? '検索中...' : '検索'"></button>
  </form>

  <ul>
    <template x-for="(r, i) in results" :key="i">
      <li x-text="r.title"></li>
    </template>
  </ul>

  <script>
    function search() {
      this.loading = true
      fetch('/api/search?q=' + encodeURIComponent(this.keyword))
        .then(r => r.json())
        .then(data => {
          this.results = data
          this.loading = false
        })
    }
  </script>
</div>

使ってみた感想: この書き方がAlpine.jsの真骨頂です。Reactで書けばstate管理やフックが必要なところが、x-data内のメソッド呼び出しだけで完結します。@submit.preventでフォームのデフォルト送信を止めるのも直感的です。

async/awaitを使った書き方も可能です。

<div x-data="{
  async load() {
    const res = await fetch('/api/users')
    this.users = await res.json()
  }
}" x-init="load()">
  <template x-for="u in users" :key="u.id">
    <p x-text="u.name"></p>
  </template>
</div>

5. コンポーネント化:Alpine.dataと$store

同じロジックを複数箇所で使う場合は、Alpine.data()で再利用可能なコンポーネントを定義できます。

document.addEventListener('alpine:init', () => {
  Alpine.data('counter', () => ({
    count: 0,
    increment() { this.count++ },
    decrement() { this.count-- }
  }))
})
<div x-data="counter">
  <button @click="decrement">-</button>
  <span x-text="count"></span>
  <button @click="increment">+</button>
</div>

また、Alpine.store()を使うと、複数のコンポーネントで共有するグローバルな状態を管理できます。ログイン状態やテーマ設定などに便利です。

document.addEventListener('alpine:init', () => {
  Alpine.store('app', {
    user: null,
    theme: 'light',
    toggleTheme() {
      this.theme = this.theme === 'light' ? 'dark' : 'light'
    }
  })
})
<div x-data>
  <span x-text="$store.app.user ? $store.app.user.name : 'ログインしていません'"></span>
  <button @click="$store.app.toggleTheme()">
    現在: <span x-text="$store.app.theme"></span>
  </button>
</div>

広告・楽天アフィリエイト

メカニカルキーボード

打鍵感で選ぶ開発者向けキーボード。

楽天ポイント還元

キーボードを楽天で見る →

6. HTMXとAlpine.jsを組み合わせる実践例

ここが本記事の目玉です。HTMX(詳細はHTMX完全ガイドを参照)とAlpine.jsを組み合わせると、サーバーから取得したHTMLに対してクライアント側の状態管理を追加できます。

代表的なパターンは「HTMXでコンテンツをロード → Alpine.jsでUI操作」です。

<!DOCTYPE html>
<html lang="ja">
<head>
  <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
  <script src="https://unpkg.com/htmx.org@2.0.0"></script>
</head>
<body>
  <div x-data="{ open: false }">
    <!-- HTMX: サーバーからHTMLを取得して差し替え -->
    <button hx-get="/api/items" hx-target="#items" hx-swap="innerHTML">
      最新アイテムを読み込む
    </button>

    <ul id="items"></ul>

    <!-- Alpine.js: クライアント側で表示を切り替え -->
    <button @click="open = !open">詳細を表示</button>
    <div x-show="open" x-transition>
      HTMXが取得したHTMLに対して、Alpineの状態管理を適用できます。
    </div>
  </div>
</body>
</html>

また、HTMXのレスポンスとして返すHTML側にもAlpine.jsのディレクティブを埋め込んでおけば、ロード後の要素もそのままAlpineで操作できます。

<!-- サーバーが返す部分テンプレート例 -->
<div x-data="{ expanded: false }">
  <h3>アイテム名</h3>
  <p x-show="expanded">ここはクリックで開閉する詳細説明</p>
  <button @click="expanded = !expanded" x-text="expanded ? '閉じる' : '開く'"></button>
</div>

このように、ページ全体の遷移やサーバーとの通信はHTMX、個々のUIの状態管理はAlpine.jsという分担が、2026年の軽量Web開発では非常に理にかなっています。

7. Alpine.jsのメリット・デメリット

✅ メリット

  • 導入が超簡単 — CDN 1行で動作、ビルド不要
  • 学習コストが低い — HTMLの属性を覚えるだけ
  • 軽量 — 約15KBで既存サイトに影響が少ない
  • HTMXとの相性抜群 — 補完関係を築ける
  • テンプレートがHTMLのまま — デザイナーとも共有しやすい

❌ デメリット

  • 大規模SPAには不向き — 複雑な状態管理は辛い
  • ディレクティブが増えるとHTMLが煩雑に
  • エコシステムが小さい — ライブラリや記事が少ない
  • 型安全性は低い — TypeScriptの恩恵を受けにくい

8. 実践テクニック3選

8.1 モーダル・ドロップダウンをシンプルに実装

<div x-data="{ show: false }" @keydown.escape.window="show = false">
  <button @click="show = true">モーダルを開く</button>
  <div x-show="show" x-transition.opacity class="modal-backdrop" @click.self="show = false">
    <div class="modal">
      <p>モーダルの中身</p>
      <button @click="show = false">閉じる</button>
    </div>
  </div>
</div>

8.2 入力のデバウンス(遅延検索)

<div x-data="{
  query: '',
  get filtered() {
    return allItems.filter(i => i.includes(this.query))
  }
}">
  <input x-model="query" @input.debounce.500ms="search()">
</div>

@input.debounce.500msのようにイベント修飾子を組み合わせるだけで、500msのデバウンス(連続入力をまとめて処理)を実現できます。

8.3 x-effectで副作用を監視

<div x-data="{ count: 0 }" x-effect="document.title = 'カウント: ' + count">
  <button @click="count++">増やす</button>
</div>
<!-- countが変わるたびにページタイトルが更新される -->

x-effectは、中で参照している状態が変わるたびに自動で再実行されるため、ウォッチャーとして使えます。

9. まとめ:Alpine.jsは「軽量Webの相棒」

Alpine.jsは、ReactやVueのような重厚なフレームワークに踏み込む前に、手軽に動的なUIを追加できる頼れる選択肢です。

  1. CDN 1行で導入 — ビルド環境の整備が不要で、既存サイトへ即組み込み可能
  2. 基本ディレクティブ7つを覚えればOK — x-data / x-text / x-show / x-bind / x-on / x-model / x-for
  3. HTMXと併用するのが2026年の定番 — サーバー通信はHTMX、UI状態はAlpine.js
  4. Alpine.data / $storeで再利用性を確保 — コンポーネントも作れる
  5. 個人開発のサイトやブログ、管理画面に最適 — 大規模SPAには不向き

特に、既存のサーバーサイドレンダリングのサイトに少しだけ動きを足したいというケースでは、Alpine.jsはReact導入を検討するよりはるかに低コストで成果を出せます。まずはCDNで読み込んで、モーダルやタブから試してみてください。

関連記事として、HTMX完全ガイドAstro.js完全ガイドTailwind CSS v4完全ガイドもあわせてどうぞ。軽量な技術を組み合わせて、シンプルで高速なWebサイトを作っていきましょう。