はじめに (対象読者・この記事でわかること)
この記事は、HTML/CSSの基本的な知識があり、JavaScriptの基礎を学習中のWeb開発者や、既存のWebサイトのUI改善に興味がある方を対象としています。
この記事を読むことで、JavaScriptを使ってHTMLテーブルをアコーディオン表示にする具体的な方法がわかります。ユーザーに大量の情報を提示する際に、すべてを表示せず、必要な情報だけを展開・格納できるようにすることで、テーブルの視認性を高め、ユーザー体験を向上させるための基本的なDOM操作やCSSとの連携のコツを習得できます。情報過多になりがちなWebページにおいて、いかにユーザーフレンドリーなUIを構築するかのヒントも得られるでしょう。
前提知識
この記事を読み進める上で、以下の知識があるとスムーズです。 - HTML/CSSの基本的な知識 (要素の構造、セレクタ、基本的なプロパティ) - JavaScriptの基本的な構文 (変数、関数、イベントリスナー、DOM操作の基礎)
アコーディオンテーブルとは?なぜ必要か
アコーディオン表示の概念
アコーディオン表示とは、コンテンツを折りたたみ可能なパネルとして表示するUIパターンの一つです。通常はタイトル部分のみが見えており、クリックすると詳細な内容が展開され、再度クリックすると閉じます。これにより、ページ全体の情報量を一度に表示することなく、ユーザーが必要な情報にのみアクセスできるようにします。
テーブルにアコーディオンが必要な理由
テーブルは、構造化された大量のデータを表示するのに非常に便利なHTML要素です。しかし、列や行が増えすぎると、以下の問題が生じます。
- 視認性の低下: 全てのデータが一度に表示されるため、ユーザーは目的の情報を見つけるのに苦労します。特にモバイルデバイスでは、横スクロールが必要になり、操作性が悪化します。
- 情報過多: 必要でない情報まで常に表示されていると、ユーザーは精神的な負担を感じ、離脱につながる可能性があります。
- モバイルフレンドリー: スマートフォンなどの小さな画面では、広大なテーブルの表示は困難です。アコーディオン化することで、縦方向のスクロールで情報を辿れるようになり、操作性が向上します。
アコーディオンテーブルは、重要なサマリー情報だけを初期表示し、詳細情報を折りたたむことで、これらの問題を解決します。ユーザーは興味のある行をクリックして詳細を確認できるため、UX (ユーザーエクスペリエンス) が大幅に向上します。
JavaScriptで実現!テーブルのアコーディオン表示実装ガイド
ここでは、JavaScriptとCSSを組み合わせて、HTMLテーブルの一部をアコーディオン表示にする具体的な手順を解説します。
ステップ1: 基本のHTML構造を準備する
まず、アコーディオン機能を持たせるための基本的なHTMLテーブル構造を準備します。ここでは、各データ行(<tr>)がヘッダー部分と詳細部分を持つ形式を想定します。詳細部分は初期状態で非表示にします。
Html<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>アコーディオンテーブル</title> <link rel="stylesheet" href="style.css"> </head> <body> <h1>製品情報</h1> <table id="productTable"> <thead> <tr> <th>製品名</th> <th>価格</th> <th>概要</th> <th>詳細</th> <!-- ヘッダーには表示しないが、アコーディオン機能のトリガーとして --> </tr> </thead> <tbody> <!-- 製品1 --> <tr class="accordion-header"> <td>スマートフォンX</td> <td>¥79,800</td> <td>高性能モデル</td> <td><span class="accordion-icon">▼</span></td> <!-- アイコンをここに追加 --> </tr> <tr class="accordion-content"> <td colspan="4"> <div class="content-wrapper"> <p>CPU: 最新Aチップ</p> <p>RAM: 8GB</p> <p>ストレージ: 256GB</p> <p>カメラ: 48MPトリプルレンズ</p> <p>バッテリー: 4000mAh</p> </div> </td> </tr> <!-- 製品2 --> <tr class="accordion-header"> <td>ノートPC Y</td> <td>¥129,800</td> <td>ビジネス向け軽量モデル</td> <td><span class="accordion-icon">▼</span></td> </tr> <tr class="accordion-content"> <td colspan="4"> <div class="content-wrapper"> <p>CPU: Core i7</p> <p>RAM: 16GB</p> <p>ストレージ: 512GB SSD</p> <p>ディスプレイ: 13.3インチ FHD</p> <p>OS: Windows 11 Pro</p> </div> </td> </tr> <!-- 他の製品も同様に続く... --> </tbody> </table> <script src="script.js"></script> </body> </html>
accordion-headerクラスを持つ<tr>がクリック可能なヘッダー行、その直後のaccordion-contentクラスを持つ<tr>がアコーディオンで開閉する詳細行となります。詳細行はcolspanを使って1つのセルにし、その中に詳細コンテンツを入れます。
ステップ2: CSSでスタイルを整える
次に、アコーディオンの開閉を制御するためのCSSと、基本的なテーブルスタイルを適用します。特に、accordion-contentクラスの行は初期状態で非表示にし、開閉時のアニメーションも考慮します。
Css/* style.css */ body { font-family: Arial, sans-serif; margin: 20px; background-color: #f4f4f4; } h1 { text-align: center; color: #333; } table { width: 100%; border-collapse: collapse; margin-top: 20px; background-color: #fff; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); } th, td { border: 1px solid #ddd; padding: 12px 15px; text-align: left; } th { background-color: #f2f2f2; color: #333; font-weight: bold; } /* アコーディオンヘッダーのスタイル */ .accordion-header { cursor: pointer; background-color: #e9e9e9; transition: background-color 0.3s ease; } .accordion-header:hover { background-color: #dcdcdc; } /* アコーディオンアイコンのスタイル */ .accordion-icon { float: right; transition: transform 0.3s ease; font-size: 0.8em; color: #666; } /* アコーディオンヘッダーが開いている時のアイコンの回転 */ .accordion-header.is-open .accordion-icon { transform: rotate(180deg); } /* アコーディオンコンテンツの初期状態(非表示) */ .accordion-content { /* display: none; */ /* JavaScriptでheight制御するため、初期はmax-height: 0; overflow: hidden; */ max-height: 0; overflow: hidden; transition: max-height 0.3s ease-out; /* 開閉アニメーション用 */ background-color: #f9f9f9; } /* アコーディオンコンテンツが展開された状態 */ .accordion-content.is-open { max-height: 500px; /* 十分な高さに設定。コンテンツに合わせて調整 */ transition: max-height 0.3s ease-in; } /* コンテンツラッパーのスタイル */ .content-wrapper { padding: 10px 0; } .content-wrapper p { margin: 5px 0; line-height: 1.5; }
accordion-contentのdisplay: none;をコメントアウトし、max-height: 0; overflow: hidden;とtransitionを設定しています。これにより、max-heightの値を切り替えることでスムーズな開閉アニメーションを実現できます。is-openクラスが追加された時にmax-heightを十分な高さに設定します。
ステップ3: JavaScriptでアコーディオン機能を実装する
最後に、JavaScriptでクリックイベントを処理し、CSSクラスを切り替えることでアコーディオン機能を実現します。
Javascript// script.js document.addEventListener('DOMContentLoaded', () => { // すべてのアコーディオンヘッダーを取得 const accordionHeaders = document.querySelectorAll('.accordion-header'); accordionHeaders.forEach(header => { header.addEventListener('click', () => { // クリックされたヘッダー行の直後の要素(アコーディオンコンテンツ)を取得 const content = header.nextElementSibling; // アコーディオンヘッダーに'is-open'クラスをトグル header.classList.toggle('is-open'); // アコーディオンコンテンツに'is-open'クラスをトグル // これによりCSSのmax-heightが切り替わり、開閉アニメーションが適用される if (content && content.classList.contains('accordion-content')) { content.classList.toggle('is-open'); } }); }); });
このスクリプトは以下の処理を行います。
1. DOMの読み込みが完了したら処理を開始します。
2. accordion-headerクラスを持つすべての要素(アコーディオンの開閉トリガーとなる行)を取得します。
3. それぞれのヘッダー要素に対してクリックイベントリスナーを設定します。
4. クリックイベントが発生すると、クリックされたヘッダー行自体にis-openクラスをトグルします(これによりアイコンの回転などが制御されます)。
5. 次に、そのヘッダー行の直後にある要素(nextElementSibling)がアコーディオンコンテンツ(accordion-contentクラスを持つ)であるかを確認し、is-openクラスをトグルします。これによりCSSで定義したmax-heightが切り替わり、アコーディオンが開閉します。
ハマった点やエラー解決
1. display: none; と transition の問題
問題点: 初期表示にdisplay: none;を設定し、開く時にdisplay: block;やdisplay: table-row;に切り替えると、transitionプロパティによるスムーズなアニメーションが適用されません。displayプロパティはアニメーションの対象外だからです。
解決策:
display: none;の代わりに、max-height: 0; overflow: hidden; を使用します。
コンテンツを隠すにはmax-height: 0;とoverflow: hidden;を設定し、開く時には十分なmax-heightの値を設定します。これにより、max-heightの数値の変化にtransitionが適用され、スムーズなアニメーションが実現します。
HTMLの<td>要素はdisplay: table-cell;ですが、その中のdiv.content-wrapperにdisplay: block;を設定することで、max-heightを使ったアニメーションが適切に機能するようになります。
2. イベントリスナーの対象範囲
問題点: テーブル内に多くの行があり、それぞれに個別にイベントリスナーを設定すると、パフォーマンスが低下したり、動的に追加される行に対応できなかったりする場合があります。
解決策:
イベント委譲(Event Delegation)を利用します。テーブル全体など親要素にイベントリスナーを設定し、event.target(クリックされた要素)やevent.target.closest()メソッドを使って、実際にクリックされたのがaccordion-headerクラスを持つ要素であるかを判断します。
Javascript// イベント委譲を用いた例(より堅牢) document.addEventListener('DOMContentLoaded', () => { const table = document.getElementById('productTable'); // テーブル全体を取得 table.addEventListener('click', (event) => { // クリックされた要素から、最も近い.accordion-headerの祖先要素を探す const header = event.target.closest('.accordion-header'); if (header) { // .accordion-headerがクリックされた場合 const content = header.nextElementSibling; header.classList.toggle('is-open'); if (content && content.classList.contains('accordion-content')) { content.classList.toggle('is-open'); } } }); });
closest('.accordion-header')を使うことで、accordion-iconなどヘッダー内の子要素をクリックしても、正しくaccordion-header要素を特定できます。これにより、イベントリスナーの数を減らし、パフォーマンスを向上させることができます。
まとめ
本記事では、JavaScriptとCSSを組み合わせて、HTMLテーブルをアコーディオン表示にする方法 を解説しました。
- HTML構造:
accordion-headerとaccordion-contentクラスを持つ<tr>を用意し、詳細情報をcolspanを使った<td>内に配置します。 - CSSスタイリング:
accordion-contentにmax-height: 0; overflow: hidden;とtransitionを設定し、is-openクラスでmax-heightを切り替えることでスムーズな開閉アニメーションを実現します。 - JavaScript実装: イベント委譲の手法を用いて親要素にイベントリスナーを設定し、クリックされた
accordion-headerとその直後のaccordion-contentのis-openクラスをトグルすることで、アコーディオン機能を実現しました。
この記事を通して、ユーザーに優しい、整理されたテーブルUIをJavaScriptとCSSで実装するスキル を得られたことと思います。大量のデータを扱う際に、ユーザーが必要な情報に迅速にアクセスできることは、Webサイトの利便性を大きく向上させます。
今後は、アコーディオン開閉時のより洗練されたアニメーションの追加、キーボード操作によるアクセシビリティ対応(ARIA属性の活用)、大量データにおけるパフォーマンス最適化などについても記事にする予定です。
参考資料
- MDN Web Docs: HTML table element
- MDN Web Docs: CSS display property
- MDN Web Docs: CSS max-height property
- MDN Web Docs: Element.classList
- MDN Web Docs: EventTarget.addEventListener()
- MDN Web Docs: Element.closest()