details と summary で開閉できる内容を作る
内容を <details> で囲み、最初に <summary> を置きます。summary は表示されたままで、ほかの内容は読者がクリックするまで隠れています。
質問をクリックすると開き、もう一度クリックすると閉じます。ブラウザが三角の印を付け、summary をフォーカスできるようにし、Enter キーやスペースキーで開閉させ、展開されているか折りたたまれているかをスクリーンリーダーに伝えます。JavaScript はまったく使っていません。
<summary> を省くと、代わりにブラウザが初期のラベル (英語では「Details」) を表示します。
最初から開いておく
真偽値の open 属性を付けると、最初から内容が表示されます。読者が開閉するとブラウザが open を追加したり外したりするので、スタイルを付ける手がかりにもなります。
開いている箱には details[open] で青い枠線が付いています。「Returns」を開くとそれも青くなります。両方を同時に開いておけます。
アコーディオン: 一度に 1 つだけ開く
複数の <details> 要素に同じ name を付けると、排他的なグループになります。1 つを開くとほかのものが閉じます。以前は JavaScript が必要でしたが、現在の Chrome、Edge、Firefox、Safari では属性だけで動きます。
2 つ目の質問を開くと 1 つ目が閉じます。name 属性を消すと、それぞれが独立して開くようになります。排他的なアコーディオンは読者が比べたいかもしれない内容を隠してしまうので、セクションが選択肢同士であるときに使い、複数を開きたい場合がありそうなら普通の <details> を使いましょう。
印のデザイン
三角は summary に付いたリストの印 (マーカー) です。list-style: none で消し (::-webkit-details-marker のルールは Safari 向けです)、疑似要素で独自の印を描けます。
セクションが開くと、プラス記号が 45 度回転してバツ印になります。ここにある :focus-visible の outline のように、フォーカスのスタイルは見えるように残しましょう。初期の印を消したら、キーボードのユーザーが頼りにするのはフォーカスリングです。
toggle イベントと open プロパティ
JavaScript では details.open を読み書きでき、クリック、キー操作、スクリプトのどれで変わった場合でも、変化のたびに toggle イベントが発生します。
「Expand all」は両方に open を設定し、ログには最後の toggle イベントが表示されます。このイベントはバブリングしないので、親ではなく各 <details> 要素で受け取りましょう。
summary に入れるもの
summary にはテキスト、インライン要素、またはセクションのタイトルをページのアウトラインに含めたいときは見出しを入れます。
<details>
<summary><h3>Refund policy</h3></summary>
<p>...</p>
</details>
<summary> の中にリンク、ボタン、フォームの入力欄を置くのは避けましょう。summary 自体がすでに操作できる部品なので、その中の部品は見落としやすく、間違って押しやすく、スクリーンリーダーも入れ子の部品をうまく読み上げられません。操作できる内容は <details> の本体に置きましょう。
よくある間違い
<div>と JavaScript で開閉を作る。<details>はクリック、キー操作、スクリーンリーダーへの状態の通知をすでに処理しています。独自の開閉がどうしても必要なら、aria-expandedを付けた ボタン を使いましょう。<summary>を最初以外の場所に置く。<details>の最初の子要素でなければなりません。- 代わりを用意せずに印を消す。 上のプラス記号のように、summary を開けることが読者にわかる印を付けましょう。
displayで内容を隠す。 代わりにopenを切り替えましょう。内容を強制的に表示したり隠したりする CSS は、ブラウザの状態とぶつかります。- 比べたい内容に排他的なグループを使う。
nameは、一度に 1 つだけ開くことに意味があるときだけ使いましょう。
よくある質問
HTML の details と summary は何をしますか?
<details> は開閉できるセクション (ディスクロージャーウィジェット) を作ります。最初の子要素の <summary> は常に表示されるラベルで、それをクリックすると (またはフォーカスがあるときに Enter キーかスペースキーを押すと)、<details> の中のほかの内容が表示されたり隠れたりします。
details 要素を最初から開いた状態にするには?
真偽値の open 属性を付けます: <details open>。ユーザーが開閉するとブラウザがこの属性を追加したり外したりするので、CSS では details[open] でスタイルを付けられます。
1 つだけ開くアコーディオンを作るには?
グループ内のすべての <details> に、name="faq" のような同じ name 属性を付けます。1 つを開くと、同じグループのほかのものが JavaScript なしで閉じます。
details の summary の矢印を消したり変えたりするには?
summary に list-style: none を指定し、Safari 向けに summary::-webkit-details-marker { display: none; } を追加します。そのうえで summary::after などで独自の印を描き、details[open] summary::after で切り替えます。
details 要素が開いたことを検知できますか?
できます。<details> 要素の toggle イベントを受け取り、open プロパティを読みます。JavaScript で details.open = true を設定すると開きます。