インタラクションのために、多数の小さなHTMLページをナビゲーションでつなぎ合わせられる
(blog.jim-nielsen.com)- (L)ots of (L)ittle ht(M)l page(s) アプローチは、JavaScriptベースのページ内インタラクションを、複数の小さなHTMLページ間の移動に置き換える
- インタラクションはHTMLページ間の ナビゲーション として構成し、最新環境ではCSSのビュー遷移(view transitions)で改善し、必要なときだけ少量のJavaScriptを追加する
- ブログの Menu は、JavaScriptで展開されるUIではなく、
<a href="/menu/">リンクをたどってメニュー専用ページへ移動する方式である - メニューを閉じる操作も基本は
/へ行くリンクだが、document.referrer があればJavaScriptでhistory.back()を実行し、履歴にメニューの開閉項目が積み重ならないようにする - ブラウザの基本機能である リンク移動 に依存すれば、旧型デバイス・古いブラウザ・JavaScript無効環境でも動作し、ページサイズを小さく保つほどインタラクションは高速で堅牢になる
メニュー実装方式と設計結果
-
開く・閉じるの両方をリンクで処理
- 通常ページにはメニューページへ移動するリンクがあり、メニューページではそのリンクが「X」に変わってメニューを閉じる役割を担う
- 閉じる動作も基本は
/へ行くリンクだが、document.referrerがあればJavaScriptでhistory.back()を実行し、ブラウザ履歴にメニューの開閉項目が追加されないようにする - 単純化した実装は次のとおり
<!-- Normal page --> <nav> <a href="/menu/"> <svg>...</svg> </a> </nav> <!-- Menu page --> <nav> <a href="/" onclick="document.referrer ? history.back() : window.location.href = '/'; return false;"> <svg>...</svg> </a> </nav>
-
直接訪問と内部移動を区別
document.referrerによって、メニューページにブログ内部からの移動で来たのか、URL入力のような直接訪問で来たのかを区別する- 内部移動なら意味のある
history.back()を実行でき、直接訪問なら/に移動する
-
アプローチがデザインを形作る
- 単純に見える解法だが、ナビゲーションの本質、複数ページをまたぐインタラクション、小さなページサイズを維持する方法をあわせて考える必要がある
- ページサイズを小さく保つことで、インタラクションは高速で堅牢、かつ直感的であり続けられる
- ブラウザを任意コードを実行し、取得し、コンパイルして表示するランタイムではなく、文書を探索するツール と見なせば、ツールが誘導するものよりはるかに単純なWebサイトを作れる
1件のコメント
Lobste.rs の意見
普段は常に HTML で応答するやり方が好きだが、メニューのようなケースについては確信が持てない
トグル可能な要素と、メニューを開くためにページ全体を切り替える方法のどちらがよいのか、アクセシビリティの専門家の意見を聞いてみたい
ここでは Popover API のほうがよい解決策に思える。ページ全体の往復リクエストなしで、JavaScript なしのメニューを提供できるからだ
それ以外については、ページ遷移を恐れる必要はないという点に概ね同意する。今では SPA 的なナビゲーションでも、SSR・静的サイトでアクセシビリティを備えることはほぼ常にそれほど難しくない
ページ遷移は現在位置をリセットするが、メニューを開く意図があって実際にメニューへ到達するなら、両者はかなり似ている
ただし、スクリーンリーダー利用者でなくてもそうであるように、メニューを開くために新しいページへ移動するのはかなり奇妙に感じる
たとえばコンポーネントの開閉状態を 2 つの異なる HTML ページで表現するか、それとも
<details>タグを使うかと聞かれたら、当然後者だ同様に Popover API を使うのもまったく問題ない。要点は、ページ内インタラクションに JavaScript が必須にならないよう避けようということであって、マルチページ HTML ナビゲーションに固執しようという話ではない
提示された方式は JavaScript と
onclickでメニューを動的に読み込むので、遅延が生じ、ユーザージャーニーにデータポイントが 1 つ増える代わりに、各ページにメニューを入れて
<details>要素や:focus-withinCSS セレクタで表示・非表示を切り替えられるhttps://nlnet.nl はこのように動作している
説明されているアプローチは、実際には正しく動いていない。JavaScript を無効にしてブログ記事を開き、メニューを開閉すると、元の記事ではなくホーム(
/)へ移動してしまう閉じるボタンに正しいリンクを入れるには、バックエンド側でメニューを動的にレンダリングしなければこの方式は成立しない
個人的には、可能なら Popover API を好む。そうすればバックエンドなしで、すべてを静的にレンダリングできる
https://blog.jim-nielsen.com/を指しているが、JavaScript を有効にするとonclickハンドラがナビゲーションを横取りしているようだhrefに書かれた場所とは別のページへ送るので、悪いユーザー体験だ。リンクにマウスを乗せて遷移先をよく確認するので、こうしてだまされたように感じるのは好ましくない一方では本当に気に入った。HTML だけでも、JavaScript よりずっと滑らかで単純に多くのことができる
他方では、このやり方は主にモバイル向きに見える。デスクトップのページなら、メニューは常に表示されているかポップアウトするものを期待し、ページ遷移を要求するものとは思わない
となると、今度はブラウザごとに 2 種類のページ が必要になるのだろうかと思ってしまう
摩擦が 2 倍になる
JavaScript はむしろ偶発的な産物に近かった
この方法がどんな JavaScript の解決策よりも難しいとか複雑だと感じるのは不思議だ。ウェブサイトを作る最も単純で簡単な方法であることは確かだ
ナビゲーション方式はいまひとつだが、トランジション効果は気に入ったし、こんなことができるとは知らなかった
自作の C++ 静的ジェネレータとテンプレートライブラリを使っている自分のサイトにも適用した: https://vittorioromeo.com/
特にダーク/ライトテーマの切り替えによく合うと思う
デスクトップで “menu” をクリックして別ページへ飛ばされるのは気分がよくない。ページ全体の再読み込みが発生して、期待に反してかなり煩わしい
個人的には、読む流れと思考の流れが途切れる。別サイトへのリンクをクリックするときは部屋を出る感じなので前の部屋を捨てて移動するが、メニューで同じことが起きると、ドアの前まで行ったらまったく別の部屋に来ていたような感覚で不快だ
アイデア自体は正直よいが、実際に使った感触はよくない
それに、どのトランジション効果を指しているのかもわからない。自分の環境では Menu ボタンを押すと、ただいつも通り Menu ページが読み込まれるだけだ
他のブラウザでも動かないかもしれないが、普段使いのブラウザは Firefox フォークの Librewolf だ
Chromium ではトランジション効果が見える
面白いアイデアだが、デスクトップではどう機能するのか気になる
ページ全体のメニューは少しやりすぎに感じるので、ページ全体を切り替える方式はあまり合っていないように思える
メニューページ読み込みの遅延を減らすための preload に触れていない
これを使うとどれほどうまく動くのか気になる
そうすれば表示前にサーバーへ検証しに行く必要もなくなり、とても高速に感じられるはずだ
数年前に @misty が作ったテキストゲームを見たが、単純なリンクをインタラクションとして使って選択の 幻想 を与えていた
シンプルな HTML と力強い物語が深く響いた