アコーディオンは、見出しをクリックすることで隠れている内容を表示・非表示にできるUIです。FAQや商品説明、設定画面など、限られたスペースに多くの情報を整理したい場合に役立ちます。開閉の仕組みにはいくつかの種類がありますが、代表的なのが「複数の項目を同時に開けるタイプ」と「1つの項目だけを開けるタイプ」です。
複数の項目を同時に開けるアコーディオンでは、新しい項目を開いても、すでに開いている項目はそのまま表示されます。例えば、FAQで複数の回答を読み比べたり、商品の仕様を確認したりする場合に便利です。利用者が必要な項目を自由に開閉できるため、複数の情報をまとめて確認したいページに向いています。
一方、複数の項目を開くとページが縦に長くなり、表示する情報が増えすぎてしまう場合もあります。そのような場面では、1つの項目だけを開けるアコーディオンが便利です。新しい項目をクリックすると、それまで開いていた項目が自動的に閉じるため、表示する内容を絞ることができます。また、開いている項目をもう一度クリックすると、その項目も閉じられます。設定項目の説明や、内容を1つずつ確認してほしいページなどに適しています。
この記事では、複数の項目を同時に開く方法と、1つの項目だけを開く方法をそれぞれ紹介します。どちらもHTML・CSS・JavaScriptで実装でき、主な違いはJavaScriptによる開閉処理です。実際のデモで動作を比較しながら、それぞれの作り方を確認していきます。
JavaScriptを使わず、HTMLのdetails要素とsummary要素だけで開閉を制御したい場合は、HTML/CSSだけで作るアコーディオン|複数の項目を同時に開く方法と1つだけ開く方法も参考にしてください。
デモ
複数開くアコーディオン
複数の項目を同時に開いて、内容を確認できるアコーディオンです。
見出しを順番にクリックしてください。複数の項目を同時に開けます。開いている見出しをもう一度クリックすると、その項目だけが閉じます。
1つだけ開くアコーディオン
別の項目を開くと、前の項目が自動的に閉じるアコーディオンです。
見出し1を開いたあと、見出し2をクリックしてください。見出し1が閉じて見出し2だけが開きます。開いている見出しをもう一度クリックすると、すべて閉じた状態になります。
Q 他のアイコンを使いたい場合はどうするの?
無料のSVGアイコン作成ツールを使って、用途に合ったアイコンを作成できます。
コードをコピーして使おう!
複数開くアコーディオン
<!DOCTYPE html>
<html lang="ja">
<head>
<!-- 文字コード -->
<meta charset="UTF-8">
<!-- スマートフォン対応 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- ページタイトル -->
<title>複数開くアコーディオン</title>
<!-- CSSファイル -->
<link rel="stylesheet" href="style.css">
<!-- JavaScriptファイル -->
<script src="script.js" defer></script>
</head>
<body>
<!-- アコーディオン全体 -->
<div class="custom-accordion_wrap">
<!-- 1つ目の項目 -->
<div class="custom-accordion_item">
<!-- 開閉ボタン -->
<button class="custom-accordion_button" type="button" aria-expanded="false">
<!-- 見出し -->
<span class="custom-accordion_label">見出し1</span>
<!-- 開閉アイコン -->
<span class="custom-accordion_icon" aria-hidden="true">
<!-- 閉じているときのプラスアイコン -->
<span class="custom-accordion_icon-closed">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M12 4v16 M4 12h16"/>
</svg>
</span>
<!-- 開いているときのマイナスアイコン -->
<span class="custom-accordion_icon-open">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 12h16"/>
</svg>
</span>
</span>
</button>
<!-- 開閉する内容 -->
<div class="custom-accordion_content">
<div class="custom-accordion_content-inner">1つ目の内容が表示されます。</div>
</div>
</div>
<!-- 2つ目の項目 -->
<div class="custom-accordion_item">
<!-- 開閉ボタン -->
<button class="custom-accordion_button" type="button" aria-expanded="false">
<!-- 見出し -->
<span class="custom-accordion_label">見出し2</span>
<!-- 開閉アイコン -->
<span class="custom-accordion_icon" aria-hidden="true">
<span class="custom-accordion_icon-closed">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M12 4v16 M4 12h16"/>
</svg>
</span>
<span class="custom-accordion_icon-open">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 12h16"/>
</svg>
</span>
</span>
</button>
<!-- 開閉する内容 -->
<div class="custom-accordion_content">
<div class="custom-accordion_content-inner">2つ目の内容が表示されます。</div>
</div>
</div>
<!-- 3つ目の項目 -->
<div class="custom-accordion_item">
<!-- 開閉ボタン -->
<button class="custom-accordion_button" type="button" aria-expanded="false">
<!-- 見出し -->
<span class="custom-accordion_label">見出し3</span>
<!-- 開閉アイコン -->
<span class="custom-accordion_icon" aria-hidden="true">
<span class="custom-accordion_icon-closed">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M12 4v16 M4 12h16"/>
</svg>
</span>
<span class="custom-accordion_icon-open">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 12h16"/>
</svg>
</span>
</span>
</button>
<!-- 開閉する内容 -->
<div class="custom-accordion_content">
<div class="custom-accordion_content-inner">3つ目の内容が表示されます。</div>
</div>
</div>
</div>
</body>
</html>
1つだけ開くアコーディオン
<!DOCTYPE html>
<html lang="ja">
<head>
<!-- 文字コード -->
<meta charset="UTF-8">
<!-- スマートフォン対応 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- ページタイトル -->
<title>1つだけ開くアコーディオン</title>
<!-- CSSファイル -->
<link rel="stylesheet" href="style.css">
<!-- JavaScriptファイル -->
<script src="script.js" defer></script>
</head>
<body>
<!-- アコーディオン全体 -->
<div class="custom-accordion_wrap">
<!-- 1つ目の項目 -->
<div class="custom-accordion_item">
<!-- 開閉ボタン -->
<button class="custom-accordion_button" type="button" aria-expanded="false">
<!-- 見出し -->
<span class="custom-accordion_label">見出し1</span>
<!-- 開閉アイコン -->
<span class="custom-accordion_icon" aria-hidden="true">
<!-- 閉じているときのプラスアイコン -->
<span class="custom-accordion_icon-closed">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M12 4v16 M4 12h16"/>
</svg>
</span>
<!-- 開いているときのマイナスアイコン -->
<span class="custom-accordion_icon-open">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 12h16"/>
</svg>
</span>
</span>
</button>
<!-- 開閉する内容 -->
<div class="custom-accordion_content">
<div class="custom-accordion_content-inner">1つ目の内容が表示されます。</div>
</div>
</div>
<!-- 2つ目の項目 -->
<div class="custom-accordion_item">
<!-- 開閉ボタン -->
<button class="custom-accordion_button" type="button" aria-expanded="false">
<!-- 見出し -->
<span class="custom-accordion_label">見出し2</span>
<!-- 開閉アイコン -->
<span class="custom-accordion_icon" aria-hidden="true">
<span class="custom-accordion_icon-closed">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M12 4v16 M4 12h16"/>
</svg>
</span>
<span class="custom-accordion_icon-open">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 12h16"/>
</svg>
</span>
</span>
</button>
<!-- 開閉する内容 -->
<div class="custom-accordion_content">
<div class="custom-accordion_content-inner">2つ目の内容が表示されます。</div>
</div>
</div>
<!-- 3つ目の項目 -->
<div class="custom-accordion_item">
<!-- 開閉ボタン -->
<button class="custom-accordion_button" type="button" aria-expanded="false">
<!-- 見出し -->
<span class="custom-accordion_label">見出し3</span>
<!-- 開閉アイコン -->
<span class="custom-accordion_icon" aria-hidden="true">
<span class="custom-accordion_icon-closed">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M12 4v16 M4 12h16"/>
</svg>
</span>
<span class="custom-accordion_icon-open">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 12h16"/>
</svg>
</span>
</span>
</button>
<!-- 開閉する内容 -->
<div class="custom-accordion_content">
<div class="custom-accordion_content-inner">3つ目の内容が表示されます。</div>
</div>
</div>
</div>
</body>
</html>
コードをコピーする場合 使用するコードのタブを選び、「このタブをコピー」をクリックすると、現在表示中のコードをコピーできます。 サンプル一式を取得する場合 HTML・CSSなどすべてのファイルが必要な場合は、「サンプル一式をダウンロード」をクリックしてください。
Q ダウンロードしたけど、これをネット上で動かすにはどうするの?
Googleアカウントがあれば、InfinityFreeで無料サーバーを作成して、ダウンロードしたサンプルをネット上で動かせます。
InfinityFreeを初めて利用する場合は①から、すでにサーバーを作成している場合は②へ進んでください。
ファイル構成と設置方法
このサンプルはHTML・CSS・JavaScriptの3ファイルで構成されています。HTMLではアコーディオンの見出しや内容、開閉状態を示すSVGアイコンを配置し、CSSでは横幅や余白、枠線、角丸、文字色などのデザインを設定します。JavaScriptでは見出しをクリックしたときの開閉動作を制御します。
今回は「複数の項目を同時に開くタイプ」と「1つだけ開くタイプ」の2種類を用意しています。どちらもHTMLとCSSの基本構成は共通で、JavaScriptの処理によって開閉動作が異なります。それぞれ独立したサンプルとしてダウンロードできるため、使用したいタイプを選んで設置してください。
sample/
├── index.html
├── style.css
└── script.js
各ファイルの役割
index.htmlはアコーディオン全体を構成するファイルです。各項目の見出し、開いたときに表示する文章、プラス・マイナスのSVGアイコンを設定しています。見出しや文章を書き換えたり、項目を追加・削除したりできます。
style.cssはアコーディオンのデザインを設定するファイルです。全体の横幅、項目間の余白、枠線、角丸、見出しの文字サイズ、SVGアイコンの色や大きさなどを変更できます。また、開閉状態に応じた内容とアイコンの表示切り替えもCSSで設定しています。
script.jsはアコーディオンの開閉動作を制御するファイルです。複数開くタイプではクリックした項目だけを開閉し、1つだけ開くタイプでは新しい項目を開く際にほかの項目を閉じます。
設置方法・使い方
使用したいアコーディオンの「サンプル一式をダウンロード」をクリックし、ZIPファイルを保存してください。ZIPを展開するとsampleフォルダが作成され、その中にindex.html・style.css・script.jsが入っています。
3つのファイルを同じ階層に配置した状態で、sample/index.htmlをブラウザで開いてください。index.htmlからstyle.cssとscript.jsを読み込むことで、デザインと開閉機能が適用されます。
表示された見出しをクリックすると、対応する内容が開きます。複数開くタイプではほかの項目を開いても元の項目は閉じず、1つだけ開くタイプでは新しい項目を開くと、それまで開いていた項目が自動的に閉じます。どちらのタイプも、開いている見出しをもう一度クリックすると閉じることができます。
2種類の開閉動作の違い
2種類のアコーディオンはHTMLとCSSの基本構成が同じですが、script.jsの開閉処理が異なります。どちらもis-openクラスの付け外しによって、内容の表示・非表示を切り替えています。
複数の項目を同時に開くタイプ
複数開くタイプでは、クリックした項目に対して次の処理を実行します。
item.classList.toggle("is-open");
classList.toggle()は、指定したクラスがなければ追加し、すでにあれば削除する処理です。クリックした項目だけを対象にするため、ほかの項目の開閉状態は変わりません。複数の内容を並べて確認したい場合に適しています。
1つだけ開くタイプ
1つだけ開くタイプでは、クリック前の状態を確認してから、すべての項目を閉じる処理を実行します。
/* クリック前の開閉状態を確認 */
const willOpen = !item.classList.contains("is-open");
/* すべての項目を閉じる */
document.querySelectorAll(".custom-accordion_item").forEach(function (currentItem) {
currentItem.classList.remove("is-open");
currentItem.querySelector(".custom-accordion_button").setAttribute(
"aria-expanded",
"false"
);
});
/* クリックした項目が閉じていた場合だけ開く */
if (willOpen) {
item.classList.add("is-open");
button.setAttribute(
"aria-expanded",
"true"
);
}
最初にwillOpenでクリックした項目が閉じているかを確認します。次にclassList.remove("is-open")ですべての項目を閉じ、クリックした項目が閉じていた場合だけis-openクラスを追加します。
この処理によって、新しい項目を開くとほかの項目が自動的に閉じます。また、すでに開いている項目をクリックした場合は、すべて閉じた状態になります。
どちらのタイプもaria-expanded属性を更新し、ボタンの開閉状態を反映しています。
カスタマイズできる内容
index.htmlでは、各項目の「見出し1」「見出し2」「見出し3」や、開いたときに表示する文章を自由に変更できます。項目を増やしたい場合は、custom-accordion_itemを含む要素を複製し、見出しと内容を書き換えてください。項目を減らしたい場合は、不要な項目の要素を削除します。
style.cssでは、アコーディオン全体の横幅、項目の間隔、枠線の色や太さ、角丸、背景色、文字サイズ、SVGアイコンの色や大きさなどを変更できます。
SVGアイコンはindex.html内に直接記述されています。閉じているときはプラスアイコン、開いているときはマイナスアイコンが表示される構成です。別のデザインに変更したい場合は、それぞれのSVGコードを差し替えることで変更できます。アイコンの表示色はstyle.cssの.custom-accordion_iconにあるcolor:#2563eb;で調整できます。
script.jsでは開閉動作を変更できます。複数開くタイプと1つだけ開くタイプでは処理が異なるため、用途に合わせて使用するサンプルを選んでください。
数値調整
style.css
max-width:700px;
アコーディオン全体の最大横幅です。値を大きくすると横に広がり、小さくするとコンパクトになります。
margin:0 0 12px;
各項目の下側余白です。12pxを大きくすると項目同士の間隔が広がり、小さくすると狭くなります。
border:1px solid #000000;
各項目を囲む枠線です。1pxを大きくすると枠線が太くなり、色の値を変更すると枠線の色が変わります。
border-radius:12px;
各項目の角丸です。値を大きくすると丸みが強くなり、0にすると四角いデザインになります。
padding:16px 18px 16px;
見出しボタンの内側余白です。最初と最後の16pxが上下の余白、18pxが左右の余白です。値を大きくすると見出し部分が広くなります。
font-size:16px;
見出しと内容の文字サイズです。それぞれのCSS設定を変更することで、見出しと内容の文字サイズを個別に調整できます。
width:22px;
height:22px;
SVGアイコンの横幅と高さです。値を大きくするとアイコンが大きくなり、小さくするとコンパクトになります。
height:18px;
.custom-accordion_content-inner::afterに設定されている内容の下側余白です。値を大きくすると文章の下の余白が広がり、小さくすると狭くなります。
レスポンシブ対応
このサンプルはレスポンシブ対応です。style.cssのwidth:100%;とmax-width:700px;によって、アコーディオン全体が親要素の横幅に合わせて表示されます。
また、画面幅640px以下ではメディアクエリによって、見出しとSVGアイコンの間隔をgap:12px;に変更しています。見出しの長い文字列は折り返され、SVGアイコンは縮小されないように設定されているため、スマートフォン・タブレット・PCで利用できます。
コメント