Kodokon kodokon.com

モダンなインタラクティブHTML: dialog、details、popover、contenteditable

UIライブラリを、モダンなHTMLのネイティブなプリミティブ(モーダルダイアログ、排他的なアコーディオン、ポップオーバー、編集可能な領域)に置き換えます。

10 分 · 3 問

このレッスンを Kodokon で開く

<dialog>は、何年もかけてモーダルライブラリが寄せ集めで作ってきたものをネイティブに解決します。showModal()は要素をトップレイヤーに投影し(あらゆるz-indexの上に)、ドキュメントの残りをinert(フォーカスもクリックもなし)にし、::backdrop疑似要素を公開します。一方show()は、inert性もバックドロップもない非モーダルなダイアログを表示します。最近のclosedby=any属性は、外側をクリックすることによる閉じる機能を追加します。

HTML
<dialog id="confirm-dlg">
  <form method="dialog">
    <p>Delete this item?</p>
    <button value="cancel">Cancel</button>
    <button value="ok">Confirm</button>
  </form>
</dialog>
method=dialogのフォームは、ネットワークリクエストなしでダイアログを閉じます。

<form method=dialog>ネットワーク送信なしでダイアログを閉じます。トリガーとなったボタンのvaluedialog.returnValueになり、closeイベントでそれを読み取れます。Escapeキーは、まずcancelを発火させることでモーダルダイアログを閉じます。入力が進行中の場合はpreventDefault()でそれをキャンセルできます。

JAVASCRIPT
const dlg = document.getElementById("confirm-dlg");
dlg.showModal();
dlg.addEventListener("close", () => {
  console.log(dlg.returnValue); // "ok" or "cancel"
});
閉じる際にユーザーの選択を取得する。

Popover APIは、JavaScriptなしでメニュー、リッチなツールチップ、トーストをカバーします。要素にpopoverを、ボタンにpopovertargetを付ければ、ブラウザがトップレイヤー、ライトディスミス(外側のクリック、Escape)、そしてautoポップオーバー同士の相互の閉じる動作を処理します。showModal()とは異なり、ポップオーバーはページをinertにしません。beforetoggletoggleイベントで、すべての遷移をキャンセルまたは観察できます。

HTML
<button popovertarget="user-menu">Menu</button>
<div id="user-menu" popover>
  <button>Profile</button>
  <button>Log out</button>
</div>
JavaScriptを一行も使わない、完全なメニュー。

<details>はスクリプトなしでアクセシブルな折りたたみコンテンツを提供し、共有されたname属性は排他的なグループを作ります。一つを開くと他が閉じます。toggleイベントは状態が変わるたびにそこで発火します。編集の側では、contenteditableがあらゆる要素をリッチな入力領域に変えます。そのplaintext-onlyバリアントはあらゆるマークアップを禁じ、beforeinputイベントは非推奨のdocument.execCommand APIを有利に置き換えます。

HTML
<details name="faq" open>
  <summary>Delivery time?</summary>
  <p>Within 48 hours.</p>
</details>
<details name="faq">
  <summary>Return policy?</summary>
  <p>Within 30 days.</p>
</details>
共有されたnameがネイティブな排他的アコーディオンを生み出します。

理解度チェック

このレッスンの要点をしっかり覚えているか確認しましょう。

  1. showModal()show()に対して何をもたらしますか?
    • ダイアログが閉じるまでJavaScriptの実行をブロックする
    • ダイアログをトップレイヤーに置き、ドキュメントの残りをinertにし、::backdropを有効にする
    • ページのスクロールを防ぐだけ
  2. 複数の<details>に同一のname属性を付けると何が生じますか?
    • 親フォームの中で一緒に送信される
    • 何も起きない: nameはdetailsで有効な属性ではない
    • 排他的なアコーディオン: 一つを開くと自動的に他が閉じる
  3. autoポップオーバーとmanualポップオーバーの動作上の違いは何ですか?
    • autoはライトディスミス(外側のクリック、Escape)を得て他のautoポップオーバーを閉じる。manualは明示的に閉じられるまで開いたまま
    • manualはトップレイヤーに置けない
    • autoはページが読み込まれると自ら開く