alpine
Alpine.jsは、HTMLに手軽にインタラクティブ性をもたらす軽量なJavaScriptフレームワークで、宣言的な構文を通じて、データの反応性やイベント処理、DOM操作などを実現し、現代的なjQueryの代替として活用できるSkill。
📜 元の英語説明(参考)
Alpine.js is a lightweight JavaScript framework for adding interactivity to HTML markup. It provides reactive data, event handling, and DOM manipulation through HTML attributes — like a modern jQuery replacement with declarative syntax.
🇯🇵 日本人クリエイター向け解説
Alpine.jsは、HTMLに手軽にインタラクティブ性をもたらす軽量なJavaScriptフレームワークで、宣言的な構文を通じて、データの反応性やイベント処理、DOM操作などを実現し、現代的なjQueryの代替として活用できるSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o alpine.zip https://jpskill.com/download/14626.zip && unzip -o alpine.zip && rm alpine.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/14626.zip -OutFile "$d\alpine.zip"; Expand-Archive "$d\alpine.zip" -DestinationPath $d -Force; ri "$d\alpine.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
alpine.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
alpineフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
Alpine.js
Alpine.js は、x- 属性を使用して、リアクティブな振る舞いを HTML マークアップに直接追加します。これは、ビルドステップや SPA フレームワークなしで、サーバーでレンダリングされたページにインタラクティビティを追加するのに最適です。
インストール
<!-- index.html — CDN 経由で Alpine を追加 -->
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<!-- または: npm install alpinejs -->
// main.js — npm モジュールのセットアップ
import Alpine from 'alpinejs';
window.Alpine = Alpine;
Alpine.start();
コアディレクティブ
<!-- templates/basics.html — 基本的な Alpine ディレクティブ -->
<div x-data="{ open: false, count: 0 }">
<!-- 可視性の切り替え -->
<button @click="open = !open">Toggle</button>
<div x-show="open" x-transition>
<p>このコンテンツは切り替え可能です</p>
</div>
<!-- リアクティブカウンター -->
<p>Count: <span x-text="count"></span></p>
<button @click="count++">Increment</button>
<!-- 条件付きレンダリング (DOM から削除) -->
<template x-if="count > 5">
<p>Count is greater than 5!</p>
</template>
</div>
データバインディング
<!-- templates/binding.html — 双方向バインディングと属性バインディング -->
<div x-data="{ name: '', color: 'blue' }">
<!-- 双方向バインディング -->
<input x-model="name" placeholder="Your name" />
<p>Hello, <span x-text="name || 'stranger'"></span>!</p>
<!-- 属性バインディング -->
<div :class="{ 'text-red': color === 'red', 'text-blue': color === 'blue' }">
Colored text
</div>
<select x-model="color">
<option value="blue">Blue</option>
<option value="red">Red</option>
</select>
<!-- スタイルバインディング -->
<div :style="{ color: color, fontWeight: name ? 'bold' : 'normal' }">
Dynamic styles
</div>
</div>
ループ
<!-- templates/loops.html — データに対するイテレーション -->
<div x-data="{ items: ['Apples', 'Bananas', 'Cherries'], newItem: '' }">
<ul>
<template x-for="(item, index) in items" :key="index">
<li>
<span x-text="item"></span>
<button @click="items.splice(index, 1)">×</button>
</li>
</template>
</ul>
<form @submit.prevent="items.push(newItem); newItem = ''">
<input x-model="newItem" placeholder="Add item" />
<button type="submit">Add</button>
</form>
</div>
イベント処理
<!-- templates/events.html — イベント修飾子とカスタムイベント -->
<div x-data="{ count: 0 }">
<!-- 修飾子 -->
<button @click.prevent="count++">Prevent default</button>
<button @click.once="alert('Only once!')">Click once</button>
<input @keydown.enter="submitForm()" @keydown.escape="cancel()" />
<!-- Debounce -->
<input @input.debounce.300ms="search($event.target.value)" placeholder="Search..." />
<!-- window からのイベントをリッスン -->
<div @custom-event.window="count++">
Count: <span x-text="count"></span>
</div>
<!-- カスタムイベントを発行 -->
<button @click="$dispatch('custom-event')">Dispatch</button>
</div>
コンポーネントパターン
<!-- templates/dropdown.html — ドロップダウンコンポーネント -->
<div x-data="{ open: false }" @click.outside="open = false">
<button @click="open = !open">
Menu
<span :class="{ 'rotate-180': open }" x-text="open ? '▲' : '▼'"></span>
</button>
<div x-show="open" x-transition.origin.top.left
@keydown.escape.window="open = false"
class="dropdown-menu">
<a href="/profile">Profile</a>
<a href="/settings">Settings</a>
<button @click="$dispatch('logout')">Logout</button>
</div>
</div>
<!-- templates/tabs.html — タブコンポーネント -->
<div x-data="{ activeTab: 'general' }">
<nav>
<button @click="activeTab = 'general'" :class="{ active: activeTab === 'general' }">General</button>
<button @click="activeTab = 'security'" :class="{ active: activeTab === 'security' }">Security</button>
</nav>
<div x-show="activeTab === 'general'">General settings...</div>
<div x-show="activeTab === 'security'">Security settings...</div>
</div>
Alpine.data による再利用可能なデータ
<!-- templates/reusable.html — 再利用可能なコンポーネントの抽出 -->
<script>
// 再利用可能なコンポーネントを登録
document.addEventListener('alpine:init', () => {
Alpine.data('todoList', () => ({
items: [],
newItem: '',
add() {
if (this.newItem.trim()) {
this.items.push({ text: this.newItem, done: false });
this.newItem = '';
}
},
remove(index) {
this.items.splice(index, 1);
},
get remaining() {
return this.items.filter(i => !i.done).length;
},
}));
});
</script>
<!-- どこでも使用可能 -->
<div x-data="todoList">
<form @submit.prevent="add">
<input x-model="newItem" placeholder="New todo" />
<button type="submit">Add</button>
</form>
<p x-text="`${remaining} remaining`"></p>
<template x-for="(item, i) in items" :key="i">
<div>
<input type="checkbox" x-model="item.done" />
<span x-text="item.text" :class="{ 'line-through': item.done }"></span>
<button @click="remove(i)">×</button>
</div>
</template>
</div>
htmx との連携
<!-- templates/alpine-htmx.html — Alpine + htmx の連携 -->
<div x-data="{ editing: false }" id="article-42">
<div x-show="!editing">
<h2>Article Title</h2>
<button @click="editing = true">Edit</button>
<button hx-delete="/articles/42" hx-target="#article-42" hx-swap="outerHTML">Delete</button>
</div>
<form x-show="editing" hx-put="/articles/42" hx-target="#article-42" hx-swap="outerHTML">
<input name="title" value="Article Title" />
<button type="submit">Save</button>
<button type="button" @click="editing = false">Cancel</button>
</form>
</div>
ストア (グローバルステート)
<!-- templates/stores.html — 共有ステートのための Alpine ストア -->
<script>
document.addEventListener('alpine:init', () => {
Alpine.store('notifications', {
items: [],
add(msg) { this.items.push({ text: msg, id: Date.now() }) },
remove(id) { this.item 📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
Alpine.js
Alpine.js adds reactive behavior directly in HTML markup using x- attributes. It's ideal for adding interactivity to server-rendered pages without a build step or SPA framework.
Installation
<!-- index.html — add Alpine via CDN -->
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<!-- Or: npm install alpinejs -->
// main.js — npm module setup
import Alpine from 'alpinejs';
window.Alpine = Alpine;
Alpine.start();
Core Directives
<!-- templates/basics.html — fundamental Alpine directives -->
<div x-data="{ open: false, count: 0 }">
<!-- Toggle visibility -->
<button @click="open = !open">Toggle</button>
<div x-show="open" x-transition>
<p>This content can be toggled</p>
</div>
<!-- Reactive counter -->
<p>Count: <span x-text="count"></span></p>
<button @click="count++">Increment</button>
<!-- Conditional rendering (removes from DOM) -->
<template x-if="count > 5">
<p>Count is greater than 5!</p>
</template>
</div>
Data Binding
<!-- templates/binding.html — two-way binding and attribute binding -->
<div x-data="{ name: '', color: 'blue' }">
<!-- Two-way binding -->
<input x-model="name" placeholder="Your name" />
<p>Hello, <span x-text="name || 'stranger'"></span>!</p>
<!-- Attribute binding -->
<div :class="{ 'text-red': color === 'red', 'text-blue': color === 'blue' }">
Colored text
</div>
<select x-model="color">
<option value="blue">Blue</option>
<option value="red">Red</option>
</select>
<!-- Style binding -->
<div :style="{ color: color, fontWeight: name ? 'bold' : 'normal' }">
Dynamic styles
</div>
</div>
Loops
<!-- templates/loops.html — iterating over data -->
<div x-data="{ items: ['Apples', 'Bananas', 'Cherries'], newItem: '' }">
<ul>
<template x-for="(item, index) in items" :key="index">
<li>
<span x-text="item"></span>
<button @click="items.splice(index, 1)">×</button>
</li>
</template>
</ul>
<form @submit.prevent="items.push(newItem); newItem = ''">
<input x-model="newItem" placeholder="Add item" />
<button type="submit">Add</button>
</form>
</div>
Event Handling
<!-- templates/events.html — event modifiers and custom events -->
<div x-data="{ count: 0 }">
<!-- Modifiers -->
<button @click.prevent="count++">Prevent default</button>
<button @click.once="alert('Only once!')">Click once</button>
<input @keydown.enter="submitForm()" @keydown.escape="cancel()" />
<!-- Debounce -->
<input @input.debounce.300ms="search($event.target.value)" placeholder="Search..." />
<!-- Listen to events from window -->
<div @custom-event.window="count++">
Count: <span x-text="count"></span>
</div>
<!-- Dispatch custom event -->
<button @click="$dispatch('custom-event')">Dispatch</button>
</div>
Component Patterns
<!-- templates/dropdown.html — dropdown component -->
<div x-data="{ open: false }" @click.outside="open = false">
<button @click="open = !open">
Menu
<span :class="{ 'rotate-180': open }" x-text="open ? '▲' : '▼'"></span>
</button>
<div x-show="open" x-transition.origin.top.left
@keydown.escape.window="open = false"
class="dropdown-menu">
<a href="/profile">Profile</a>
<a href="/settings">Settings</a>
<button @click="$dispatch('logout')">Logout</button>
</div>
</div>
<!-- templates/tabs.html — tabs component -->
<div x-data="{ activeTab: 'general' }">
<nav>
<button @click="activeTab = 'general'" :class="{ active: activeTab === 'general' }">General</button>
<button @click="activeTab = 'security'" :class="{ active: activeTab === 'security' }">Security</button>
</nav>
<div x-show="activeTab === 'general'">General settings...</div>
<div x-show="activeTab === 'security'">Security settings...</div>
</div>
Reusable Data with Alpine.data
<!-- templates/reusable.html — extracting reusable components -->
<script>
// Register reusable component
document.addEventListener('alpine:init', () => {
Alpine.data('todoList', () => ({
items: [],
newItem: '',
add() {
if (this.newItem.trim()) {
this.items.push({ text: this.newItem, done: false });
this.newItem = '';
}
},
remove(index) {
this.items.splice(index, 1);
},
get remaining() {
return this.items.filter(i => !i.done).length;
},
}));
});
</script>
<!-- Use anywhere -->
<div x-data="todoList">
<form @submit.prevent="add">
<input x-model="newItem" placeholder="New todo" />
<button type="submit">Add</button>
</form>
<p x-text="`${remaining} remaining`"></p>
<template x-for="(item, i) in items" :key="i">
<div>
<input type="checkbox" x-model="item.done" />
<span x-text="item.text" :class="{ 'line-through': item.done }"></span>
<button @click="remove(i)">×</button>
</div>
</template>
</div>
Working with htmx
<!-- templates/alpine-htmx.html — Alpine + htmx together -->
<div x-data="{ editing: false }" id="article-42">
<div x-show="!editing">
<h2>Article Title</h2>
<button @click="editing = true">Edit</button>
<button hx-delete="/articles/42" hx-target="#article-42" hx-swap="outerHTML">Delete</button>
</div>
<form x-show="editing" hx-put="/articles/42" hx-target="#article-42" hx-swap="outerHTML">
<input name="title" value="Article Title" />
<button type="submit">Save</button>
<button type="button" @click="editing = false">Cancel</button>
</form>
</div>
Stores (Global State)
<!-- templates/stores.html — Alpine stores for shared state -->
<script>
document.addEventListener('alpine:init', () => {
Alpine.store('notifications', {
items: [],
add(msg) { this.items.push({ text: msg, id: Date.now() }) },
remove(id) { this.items = this.items.filter(n => n.id !== id) },
});
});
</script>
<div x-data @click="$store.notifications.add('Button clicked!')">Click me</div>
<div x-data>
<template x-for="n in $store.notifications.items" :key="n.id">
<div class="toast" x-text="n.text" @click="$store.notifications.remove(n.id)"></div>
</template>
</div>
Magic Properties
<!-- templates/magic.html — Alpine magic properties -->
<div x-data="{ items: [] }">
<!-- $refs — reference DOM elements -->
<input x-ref="input" />
<button @click="$refs.input.focus()">Focus input</button>
<!-- $nextTick — run after DOM update -->
<button @click="items.push('new'); $nextTick(() => $refs.list.scrollTo(0, 99999))">
Add & scroll
</button>
<div x-ref="list" style="max-height:200px;overflow:auto">
<template x-for="item in items"><p x-text="item"></p></template>
</div>
<!-- $watch — react to data changes -->
<div x-init="$watch('items', (val) => console.log('items changed:', val))"></div>
</div>
Key Patterns
- Use
x-dataon a parent element to define reactive scope — everything inside shares that state - Use
x-showfor toggling visibility (CSS),x-iffor conditional DOM insertion - Use
x-modelfor two-way binding on inputs, selects, checkboxes - Use event modifiers (
.prevent,.stop,.debounce,.outside) to reduce boilerplate - Use
Alpine.data()to extract reusable components with methods and computed properties - Use
Alpine.store()for global state shared across components - Pairs excellently with htmx: Alpine handles UI state, htmx handles server communication