はじめに
私たちを取り巻くWeb技術は、もはや社会的なインフラとしてめまぐるしく進化しています。HTMLやCSSはもちろんのこと、JavaScriptやライブラリ、フレームワークなど、それぞれがニーズにキャッチアップする形で、機能強化を繰り返しています。その中でも、Web技術の中核に位置するにもかかわらず、意外と見過ごされがちなのがHTMLの進化です。本連載は、このHTMLと関連するJavaScript APIにフォーカスして、その新機能を手軽に試していただこうというものです。理解も利用もたやすいHTMLなので、ライトな気持ちで「こんなことができるようになったのか」を感じていただきます。
[NOTE]サンプルについて
本記事のサンプルは、HTMLファイルとCSSファイルを各節で少しずつ機能強化/改良するスタイルとなっており、各節のスナップショットを配布サンプルに全て含めています。スナップショットのファイル名は各節でリストともに記載しているので、各節のサンプルを参照したい場合にはそのファイル名を参照してください。配布サンプルは、以下のURLから入手できます。
https://github.com/wateryinhare62/mynavi_html
連載第1回の目的
この回では、HTMLから簡単に利用できるインタラクションであるアコーディオンを試します。summary/details要素のみによるシンプルな実現方法の他、スタイルの指定による見た目を調整する例も多数紹介します。初回なので、VS Codeのセットアップについても簡単に解説します。
環境構築
本連載は、HTMLの新機能をサンプルとともに紹介していくというものです。サンプルはHTMLファイル、CSSファイル、あとJavaScriptファイルが中心ですが、編集や実行のしやすさを考慮して開発環境を整えておきましょう。開発環境は、コードエディタの定番であるVS Code(Visual Studio Code)に、拡張機能であるLive Serverをインストールして使います。
▼Download Visual Studio Code - Mac, Linux, Windows
https://code.visualstudio.com/download
▼Live Server - Visual Studio Marketplace
https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer
Live Serverがインストールされていると、HTMLファイルの右クリックで表示されるメニューから[Open with Live Server]を選択してブラウザに即座に表示できる他、ファイル内容の修正と保存でブラウザ表示を自動で更新するなど、使い勝手良くサンプルを試すことができます(図1)。
また、新機能を試していくので、ブラウザは最新である方がよいでしょう。本記事のサンプルは、最新のGoogle Chromeで動作することを確認しています。
アコーディオンとは
今回のテーマであるアコーディオンとは、開示ウィジェットの並びをいいます(図2)。開示ウィジェットとは、コンテンツのヘッダ部分のクリックで、コンテンツの表示と非表示を切り替えることのできるUI部品です。
インタラクティブに表示と非表示を切り替える必要のあることから、JavaScriptのライブラリやフレームワークで実装することが多かったのですが、現在はHTMLのdetails要素とsummary要素を組み合わせることで、開示ウィジェットおよびアコーディオンを簡単に実装することができます。
アコーディオンの中でも、開いている項目を最大1個に制限するものをエクスクルーシブアコーディオン(排他的アコーディオン)といいます。エクスクルーシブであるものとないものにはそれぞれ用途があるので、使い分けることになっています。なお、エクスクルーシブアコーディオンの仕様は、Open UI(https://open-ui.org/)という組み込みコンポーネントの拡張を目的とするコミュニティグループによって提案されたものです。
ベーシックなアコーディオン
アコーディオンは、details要素とsummary要素を組み合わせて作ります。summary要素には、項目が開いていないときの概要(サマリー)を入れて、details要素で詳細(ディテール)とともに囲みます(リスト1)。これでエクスクルーシブでないベーシックなアコーディオンができあがります。
リスト1:basic.html
<details>
<summary>ラーメン</summary>
<p>
ラーメンと一口に言っても千差万別である。…略…
</p>
</details>
<details>
<summary>そば</summary>
<p>
蕎麦はこだわりが多い食べ物と言われる。…略…
</p>
</details>
<details>
<summary>うどん</summary>
<p>
うどん県なるものがあるのは、うどんの特権である。…略…
</p>
</details>
[NOTE]
詳細であるp要素の中身は適当に省略しています。長さは動作に直接影響しませんが、全容は配布サンプルを参照してください。
さっそくブラウザで表示させてみると、図3のようになります。
右向き三角をクリックすると、それぞれの項目を開いたり、閉じたりできます。HTMLタグを2種類使うだけでこのようなアクションが実現できるのは便利ですね。
アコーディオンの見た目を整える
アコーディオンの目的は達成できましたが、非常に素っ気ないですね。何もスタイルを設定していないので当然です。このままでは、インタラクティブな要素であることが外見的に伝わりにくいので、外観を整えてマウスカーソルも変化するようにしましょう。以下のスタイルを用意して、CSSファイルを取り込んだHTMLファイルを新たに用意します(リスト2、リスト3)。
リスト2:styled.css
details {
border: 1px solid gray;
border-radius: 8px;
background-color: antiquewhite;
margin: 0.5rem;
padding: 0.5rem;
width: 50rem;
height: auto;
}
details summary {
font-weight: bold; /* 概要は太字にする */
cursor: pointer; /* マウスカーソルはポインタにする */
}
リスト3:styled.html
<title>スタイルを付けたアコーディオン</title>
<link rel="stylesheet" href="styled.css" /> <!-- 以降も対応するCSSファイルを取り込み -->
表示させてみると、図4のように外見が変わり、概要にマウスカーソルを乗せるとポインタに変化します。アコーディオンっぽくなってきました。
エクスクルーシブなアコーディオン
エクスクルーシブアコーディオンとして、開いている項目は常に最大1個までとしてみます。閉じている項目を開いたら、開いていた別の項目は閉じます。これには、項目のまとまりとなるdetails要素に、Open UIの提案によって新しく導入されたname属性を指定します。ラジオボタンを作るときのoption要素のイメージで、まとめたい項目に全て同じname属性を指定します。
リスト4:exclusive.html
<details name="noodle"> <!-- name属性を指定 -->
<summary>ラーメン</summary>
<p>
ラーメンと一口に言っても千差万別である。…略…
</p>
</details>
…他の項目も同様…
実際に操作してみると、開いている項目があるときは、別の項目のクリックでそれが閉じるようになります(図5)。
最初に開いておく項目のあるアコーディオン
details要素にはopen属性があり、その有無で開閉をコントロールすることができます。JavaScriptから項目を操作したり、項目の状態を知るために使えますが、HTML上でもopen属性を指定しておけば、最初から開いている項目とすることができます。
リスト5:opened.html
<details name="noodle" open> <!-- open属性を指定 -->
<summary>ラーメン</summary>
<p>
ラーメンと一口に言っても千差万別である。…略…
</p>
</details>
開閉アイコンを変更する
項目を開いたり閉じたりするアイコンは、既定では三角形です。アイコンの変更例として、それぞれプラス記号とマイナス記号にしてみます。アイコンを変更するには、まずは既定のアイコンを無効化(非表示)して、代わりにアイコンに相当する文字をsummary要素の直前のコンテンツとして配置します。
リスト6:custom_icon.css
details summary {
font-weight: bold;
cursor: pointer;
list-style: none; /* 既定のアイコンを無効化 */
}
details summary::before { /* 閉じているときに挿入 */
font-size: xx-large;
font-weight: 900;
content: '+';
margin-right: 0.5rem;
}
details[open] summary::before { /* 属性セレクタで開いているときに挿入 */
content: '-';
}
開いているときのアイコンは、属性セレクタでopenを指定して適用します。属性セレクタが省略されていると、開いているときと閉じているときの両方に適用されるスタイルとなります。
アイコンの変更は、list-styleプロパティをnone以外にすることでも行えます。この場合、ul要素などと同じくアイコンの形状、画像、文字列、位置を指定できますが、配置に融通が利くという点では::before疑似要素でコンテンツを直接埋め込む方法が有利でしょう。
なお、属性セレクタを利用して、開いている項目の外観だけ変えることもできます。リスト7は、開いている項目のボーダーと背景を変更し、シャドウを付けています。シャドウの分、下マージンも調整しています。
リスト7:opened_item.css
details[open] {
border: 2px solid black;
background-color:lightcoral;
box-shadow: 0.5rem 0.5rem #cccccc;
margin-bottom: 1rem;
}
アイコンを右に置く
アイコンを右に置いて、プルダウンっぽく見せたいこともあるかも知れません。前述の開閉アイコンの代わりに、::after疑似要素を指定して、アイコンをsummary要素の直後に配置します。
リスト8:rightside_icon.css
details summary {
font-weight: bold;
cursor: pointer;
list-style: none;
position: relative; /* 以下でposision: absoluteのために必要 */
}
details summary::after { /* summary要素の直後 */
font-size: large;
font-weight: 900;
content: '▼';
margin-right: 0.5rem;
position: absolute; /* 親要素(summary)に対して位置を指定 */
right: 0.5rem; /* 右から0.5rem */
transition: transform 0.5s ease-in-out; /* ちょっとしたアニメーション */
}
details[open] summary::after { /* summary要素の直後(開いているとき) */
transform: rotate(180deg); /* 上下反転 */
}
まとめ
アコーディオンはいかがでしたでしょうか。details要素、summary要素を中心に、属性やスタイルの設定次第で幅広い用途に使える機能であるということを、お伝えできたのではないかと思います。次回は、その場で音声や画像をキャプチャできるHTML Media Captureを紹介します。
WINGSプロジェクト 山内直(著) 山田 祥寛(監修)
有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。現在も執筆メンバーを募集中。興味のある方は、どしどし応募頂きたい。著書、記事多数。
RSS
X:@WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト)<著者について>
WINGSプロジェクト所属のテクニカルライター。出版社を経てフリーランスとして独立。ライター、エディター、デベロッパー、講師業に従事。屋号は「たまデジ。」。