htmxとは
記事情報: 2026年1月12日初出。本文のAPIと公式資料は2026年7月25日に再確認しています。
htmxは、HTML属性を使ってHTTPリクエストを送り、サーバーが返したHTMLで画面の一部を更新するライブラリです。
ReactやVueのように、ブラウザ側で大きな状態管理を行うことを主目的にしていません。サーバーがHTMLを生成する従来の構成を保ちながら、フォーム送信、検索結果、一覧の追加読み込みなどをページ遷移なしで更新できます。
この記事では、htmxの設計と向いている用途を確認します。
最小の例
公式ドキュメントでは、CDNから読み込む例が案内されています。本番では使用するバージョンを固定し、公式ページに掲載されたintegrity値を使うか、自分のサイトから配信してください。
<script
src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.10/dist/htmx.min.js"
></script>
ボタンにhx-getを付けると、クリック時に指定URLへGETリクエストを送ります。
<button
hx-get="/greeting"
hx-target="#result"
hx-swap="innerHTML"
>
あいさつを表示
</button>
<div id="result"></div>
サーバーはJSONではなくHTML fragmentを返します。
<p>こんにちは、htmxです。</p>
htmxはレスポンスを#resultの中へ挿入します。
よく使う属性
| 属性 | 役割 |
|---|---|
hx-get | GETリクエストを送る |
hx-post | POSTリクエストを送る |
hx-put | PUTリクエストを送る |
hx-delete | DELETEリクエストを送る |
hx-trigger | リクエストを送るイベントを決める |
hx-target | 更新対象の要素を決める |
hx-swap | レスポンスを挿入する方法を決める |
hx-include | 追加で送信するinputを指定する |
hx-indicator | 通信中に表示する要素を指定する |
属性の数を増やす前に、リクエスト先、更新対象、置換方法の3点を確認すると理解しやすくなります。
フォーム送信
検索フォームを例にします。
<form
hx-get="/users"
hx-target="#user-list"
hx-swap="innerHTML"
>
<label>
名前
<input name="query" />
</label>
<button type="submit">検索</button>
</form>
<section id="user-list" aria-live="polite"></section>
サーバーは検索結果のHTMLを返します。
<ul>
<li>佐藤</li>
<li>佐々木</li>
</ul>
JavaScriptでfetch、JSON変換、DOM生成を個別に書かなくても更新できます。一方、HTMLを生成する責務はサーバー側にあります。
入力に合わせて検索する
hx-triggerを使うと、入力イベントの条件を指定できます。
<input
type="search"
name="query"
hx-get="/users"
hx-trigger="input changed delay:300ms"
hx-target="#user-list"
/>
delay:300msは、入力のたびに即座に通信せず、入力が止まってからリクエストを送るための指定です。
検索語が空の場合、短すぎる場合、連続リクエストの順序が前後した場合にサーバーがどう応答するかも決めてください。
hx-swapの違い
hx-swapはレスポンスをどの位置へ入れるかを指定します。
| 値 | 動作 |
|---|---|
innerHTML | targetの中身を置き換える |
outerHTML | target自体を置き換える |
beforeend | targetの末尾へ追加する |
afterbegin | targetの先頭へ追加する |
delete | targetを削除する |
none | DOMを置き換えない |
outerHTMLでtarget自体を交換すると、次の更新で同じIDや属性が存在しなくなることがあります。サーバーが返すfragmentにも、次の操作に必要な属性を含めます。
サーバー側で必要なこと
htmxを使っても、認証、認可、入力検証、CSRF対策は不要になりません。
特にPOST・PUT・DELETEでは次を確認します。
- ログイン中の利用者が操作できる対象か
- CSRF tokenを送信・検証しているか
- 同じ操作を再送しても問題ないか
- validation errorをHTMLとして返せるか
- HTTP statusを適切に返しているか
クライアント側でボタンを隠すだけでは認可になりません。サーバー側で必ず判定します。
アクセシビリティ
一部更新では、画面が変わったことを支援技術へ伝える必要があります。検索結果などにはaria-liveを検討し、エラー時は入力欄との関連を示します。
読み込み中のindicatorを表示するだけでなく、キーボードフォーカスが不自然に失われないか、履歴を使う画面で戻る操作が期待通りかも確認してください。
重要なページ遷移をすべて部分更新へ変える必要はありません。通常のリンクとフォーム送信は、JavaScriptが動かない場合の基礎にもなります。
URLと履歴
検索条件やページ番号など、再読み込みや共有が必要な状態はURLへ反映します。hx-push-urlを使うと、成功したリクエストのURLをブラウザ履歴へ追加できます。
<a
href="/articles?page=2"
hx-get="/articles?page=2"
hx-target="#article-list"
hx-push-url="true"
>
次のページ
</a>
hrefも残しておけば、htmxが読み込まれない場合は通常のページ遷移として動作できます。戻る・進む操作、直接URLを開いた場合、サーバーがfull pageとfragmentをどう返し分けるかを確認してください。
エラー処理
通信失敗時に画面が無反応に見えないよう、htmxのeventを使ってメッセージを表示できます。
const errorMessages = {
"htmx:responseError": "サーバーがエラーを返しました。",
"htmx:sendError": "サーバーへ接続できませんでした。",
"htmx:timeout": "通信がタイムアウトしました。",
};
for (const [eventName, text] of Object.entries(errorMessages)) {
document.body.addEventListener(eventName, () => {
const message = document.querySelector("#error-message");
if (message) {
message.textContent = `${text} もう一度お試しください。`;
}
});
}
responseErrorはHTTP error response、sendErrorは送信・接続の失敗、timeoutはtimeoutとして分けて扱います。利用者向けには再試行できる案内を出し、開発者向けにはHTTP status、request ID、サーバーログで原因を追えるようにします。validation errorとserver errorを同じ表示にせず、入力を修正できる場合は該当項目の近くへ説明を表示します。
networkを切った状態や、serverが400・401・403・500を返す場合も実際の端末で確認すると、成功時だけでは見つからない問題を発見できます。
向いている用途
htmxを検討しやすい例です。
- サーバーレンダリング中心の管理画面
- 検索、絞り込み、ページ送り
- フォームのvalidation結果
- コメントや一覧の追加
- 小規模なモーダル内容の取得
クライアント側で複雑なオフライン状態を持つアプリ、キャンバスやリアルタイム描画が中心の画面、ブラウザ内で大量の状態変換を行う用途では、別の構成も比較します。
まとめ
- htmxはHTML属性からHTTPリクエストを送る
- サーバーはJSONではなくHTML fragmentを返す
hx-targetとhx-swapで更新位置を決める- 認証・認可・CSRF・validationはサーバー側で必要
- サーバーレンダリング中心の画面へ段階的に導入できる