作りたいもの
メニューリンクが並んでおり、どれかをクリックすると、その詳細が下に表示されるようなものを作ります。
Bootstrapでいうところの ナビゲーションタブ のようなイメージです。
環境
- HTMX ver2.0.3
ディレクトリ構造
通常は、各種サーバサイドのフレームワークとテンプレートエンジンを使われると思いますが、今回は簡易的な説明のため、静的なhtmlファイル(active.html, link1.html, link2.html)を、index.htmlから呼び出します。
.
└── htmx-test/
├── index.html
├── active.html
├── link1.html
└── link2.html
HTML部分
HTMXのドキュメント を参考に、以下のように書きました。
hx-* は、わたしの使っているエディタでエラーが出たので、data-hx-* になっていますが、やっていることは同じです。
※ なお、HTMXは、headタグで読み込んであります。
<section id="nav-tab">
<nav class="tab-menu">
<input type="radio" name="menu-item" id="active" value="active" checked
data-hx-get="./active.html" data-hx-trigger="change"
data-hx-swap="innerHTML" data-hx-target="#nav-tab>.tab-content"
/>
<label for="active">Active</label>
<input type="radio" name="menu-item" id="link1" value="link1"
data-hx-get="./link1.html" data-hx-trigger="change"
data-hx-swap="innerHTML" data-hx-target="#nav-tab>.tab-content"
/>
<label for="link1">Link1</label>
<input type="radio" name="menu-item" id="link2" value="link2"
data-hx-get="./link2.html" data-hx-trigger="change"
data-hx-swap="innerHTML" data-hx-target="#nav-tab>.tab-content"
/>
<label for="link2">Link2</label>
<input type="radio" name="menu-item"
id="disabled" disabled value="disabled" />
<label for="disabled">Disabled</label>
</nav>
<div class="tab-content">
<div>This is Active page.</div>
</div>
</section>
読み込まれる側のHTMLも作っておきます。
<div>This is Active page.</div>
<div>This is Link 1 page.</div>
<div>This is Link 2 page.</div>
ちなみに、たとえば、PHPのSymfony系統には、isXmlHttpRequest()というメソッドがあるようです。
なのでもしかしたら、上記のactive.htmlのようなエンドポイントは不要で、index.htmlにアクセスするとき、
- 通常のアクセス => HTMLすべてを返却
- HTMX経由(内部的にはAJAX経由)のアクセス => divタグのフラグメントだけを返却
というような実装も可能なのかなと思っています。
Slim frameworkだと、次のような記事を見つけました。
Slim 4 - HTMX Server-side Integration
CSS部分
HTMXを使えば、HTMLにJavaScript操作用のclassセレクタを使用しなくて済むので、CSSも、見やすく書けます。
#nav-tab{
margin:0 auto;
padding:.5rem;
max-width:30rem;
min-height:20rem;
border:solid thin gray;
border-radius: 8px;
display:flex;
flex-direction: column;
> * {
margin:0;padding:.5rem;
}
nav.tab-menu {
display:flex;
gap:.5rem;
border-bottom: solid thin gray;
input[type=radio] {
display:none;
}
label {
margin:0;padding:0 .5rem;
line-height:1.5rem;
}
label:hover {
color:white;
background-color:navy;
border-radius: 8px;
cursor:pointer;
}
input[type=radio]:checked {
+ label {
font-weight: bold;
}
+ label:hover {
color:inherit;
background-color:inherit;
cursor:inherit;
}
}
input[type=radio]:disabled {
+ label {
color:gray;
}
+ label:hover {
background-color:inherit;
cursor:not-allowed;
}
}
}
}
感想
これまでは、.active
セレクターのようなものを、JavaScriptで付けたり消したりしていましたが、HTMXと、ラジオボタンを利用することで、手間が減りました。
HTMXは、クライアントサイドで状態を管理しようとすると、一気に難易度が上がってしまうので、極力、サーバーサイドで管理するか、今回のように、inputタグを使うなど、工夫が必要だと思っています。