アコーディオンは、ページを開いたときにすべての項目を閉じておくだけでなく、最初から内容を表示した状態にすることもできます。例えば、よく読まれる説明を最初から見せたい場合や、複数の項目をまとめて確認してもらいたい場合に便利です。開いておく項目をあらかじめ指定すれば、利用者が最初にクリックする手間を減らせます。
今回は、最初からすべての項目が開いているアコーディオンと、最初の項目だけが開いているアコーディオンの2種類を作成します。どちらも見出しをクリックすると個別に開閉でき、ほかの項目の状態には影響しません。ページを読み込んだ時点で開いている項目が異なるだけで、基本的な操作方法は共通です。
初期状態の指定には、HTMLのis-openクラスを使用します。すべて開く場合は各項目にクラスを付け、特定の項目だけ開く場合は、その項目にだけ付けます。JavaScriptで項目番号を指定する必要がないため、HTMLを編集するだけで最初に表示する内容を変更できます。この記事では、実際に操作できるデモとサンプルコードを使って、初期状態の設定方法や開閉の仕組みを紹介します。
※ デモでは、各見出しをクリックして開閉できます。「初期状態に戻す」ボタンを押すと、ページを再読み込みせずに最初の表示状態へ戻せます。
デモ
ページを表示した時点で、3つの項目がすべて開いています。見出しをクリックすると個別に開閉できます。
ページを表示した時点では、1番目の項目だけが開いています。ほかの項目もクリックで開閉できます。
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>
<link rel="stylesheet" href="style.css">
<script src="script.js" defer></script>
</head>
<body>
<!-- アコーディオン本体 -->
<div class="initial-open-accordion_all">
<!-- 1番目:最初から開く -->
<div class="initial-open-accordion_all-item is-open">
<button class="initial-open-accordion_all-button" type="button" aria-expanded="true" aria-controls="initial-open-accordion-all-panel-1">
<span class="initial-open-accordion_all-label">アコーディオンとは?</span>
<span class="initial-open-accordion_all-icon" aria-hidden="true">
<span class="initial-open-accordion_all-icon-closed">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 4v16 M4 12h16"/>
</svg>
</span>
<span class="initial-open-accordion_all-icon-open">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 12h16"/>
</svg>
</span>
</span>
</button>
<div class="initial-open-accordion_all-content" id="initial-open-accordion-all-panel-1">
<div class="initial-open-accordion_all-content-inner">
必要な項目だけを開閉しながら情報を表示できるUIです。
</div>
</div>
</div>
<!-- 2番目:最初から開く -->
<div class="initial-open-accordion_all-item is-open">
<button class="initial-open-accordion_all-button" type="button" aria-expanded="true" aria-controls="initial-open-accordion-all-panel-2">
<span class="initial-open-accordion_all-label">利用シーン</span>
<span class="initial-open-accordion_all-icon" aria-hidden="true">
<span class="initial-open-accordion_all-icon-closed">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 4v16 M4 12h16"/>
</svg>
</span>
<span class="initial-open-accordion_all-icon-open">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 12h16"/>
</svg>
</span>
</span>
</button>
<div class="initial-open-accordion_all-content" id="initial-open-accordion-all-panel-2">
<div class="initial-open-accordion_all-content-inner">
FAQ、設定画面、サービス紹介などで利用できます。
</div>
</div>
</div>
<!-- 3番目:最初から開く -->
<div class="initial-open-accordion_all-item is-open">
<button class="initial-open-accordion_all-button" type="button" aria-expanded="true" aria-controls="initial-open-accordion-all-panel-3">
<span class="initial-open-accordion_all-label">使用ファイル</span>
<span class="initial-open-accordion_all-icon" aria-hidden="true">
<span class="initial-open-accordion_all-icon-closed">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 4v16 M4 12h16"/>
</svg>
</span>
<span class="initial-open-accordion_all-icon-open">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 12h16"/>
</svg>
</span>
</span>
</button>
<div class="initial-open-accordion_all-content" id="initial-open-accordion-all-panel-3">
<div class="initial-open-accordion_all-content-inner">
HTML・CSS・JavaScriptの3ファイルで実装できます。
</div>
</div>
</div>
</div>
</body>
</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">
<script src="script.js" defer></script>
</head>
<body>
<!-- アコーディオン本体 -->
<div class="initial-open-accordion_single">
<!-- 1番目:最初から開く -->
<div class="initial-open-accordion_single-item is-open">
<button class="initial-open-accordion_single-button" type="button" aria-expanded="true" aria-controls="initial-open-accordion-single-panel-1">
<span class="initial-open-accordion_single-label">アコーディオンとは?</span>
<span class="initial-open-accordion_single-icon" aria-hidden="true">
<span class="initial-open-accordion_single-icon-closed">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 4v16 M4 12h16"/>
</svg>
</span>
<span class="initial-open-accordion_single-icon-open">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 12h16"/>
</svg>
</span>
</span>
</button>
<div class="initial-open-accordion_single-content" id="initial-open-accordion-single-panel-1">
<div class="initial-open-accordion_single-content-inner">
クリックした項目の内容を開閉できるUIです。
</div>
</div>
</div>
<!-- 2番目:最初は閉じる -->
<div class="initial-open-accordion_single-item">
<button class="initial-open-accordion_single-button" type="button" aria-expanded="false" aria-controls="initial-open-accordion-single-panel-2">
<span class="initial-open-accordion_single-label">どんな場面で使う?</span>
<span class="initial-open-accordion_single-icon" aria-hidden="true">
<span class="initial-open-accordion_single-icon-closed">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 4v16 M4 12h16"/>
</svg>
</span>
<span class="initial-open-accordion_single-icon-open">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 12h16"/>
</svg>
</span>
</span>
</button>
<div class="initial-open-accordion_single-content" id="initial-open-accordion-single-panel-2">
<div class="initial-open-accordion_single-content-inner">
FAQや設定画面などで重要な内容を最初に見せたい場合に利用できます。
</div>
</div>
</div>
<!-- 3番目:最初は閉じる -->
<div class="initial-open-accordion_single-item">
<button class="initial-open-accordion_single-button" type="button" aria-expanded="false" aria-controls="initial-open-accordion-single-panel-3">
<span class="initial-open-accordion_single-label">使用ファイル</span>
<span class="initial-open-accordion_single-icon" aria-hidden="true">
<span class="initial-open-accordion_single-icon-closed">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 4v16 M4 12h16"/>
</svg>
</span>
<span class="initial-open-accordion_single-icon-open">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 12h16"/>
</svg>
</span>
</span>
</button>
<div class="initial-open-accordion_single-content" id="initial-open-accordion-single-panel-3">
<div class="initial-open-accordion_single-content-inner">
HTML・CSS・JavaScriptの3ファイルで動作します。
</div>
</div>
</div>
</div>
</body>
</html>
コードをコピーする場合 使用するコードのタブを選び、「このタブをコピー」をクリックすると、現在表示中のコードをコピーできます。 サンプル一式を取得する場合 HTML・CSSなどすべてのファイルが必要な場合は、「サンプル一式をダウンロード」をクリックしてください。
Q ダウンロードしたけど、これをネット上で動かすにはどうするの?
Googleアカウントがあれば、InfinityFreeで無料サーバーを作成して、ダウンロードしたサンプルをネット上で動かせます。
InfinityFreeを初めて利用する場合は①から、すでにサーバーを作成している場合は②へ進んでください。
ファイル構成と設置方法
今回のサンプルは、HTMLでアコーディオンの初期状態を指定し、CSSで開閉時の表示を切り替え、JavaScriptで見出しをクリックしたときの動作を制御しています。 「最初からすべて開く」と「最初の項目だけ開く」の2種類を用意しており、それぞれのコードカードから個別にダウンロードできます。 どちらもファイル構成は同じですが、HTMLで最初に開いておく項目の指定が異なります。
sample/
├── index.html
├── style.css
└── script.js
各ファイルの役割
index.htmlには、3つのアコーディオン項目と開閉ボタン、表示する文章を記述しています。各項目のis-openクラスとボタンのaria-expanded属性によって、ページを開いたときの状態を指定します。
style.cssでは、項目の枠線や角丸、文字、プラス・マイナスアイコンの表示、開閉する内容の表示・非表示を設定しています。
script.jsでは、見出しをクリックしたときにis-openクラスを切り替え、開閉状態に合わせてaria-expanded属性を更新しています。
設置方法・使い方
セクション3から、使用したいサンプルの「サンプル一式をダウンロード」をクリックします。「最初からすべて開く」と「最初の項目だけ開く」は別々のZIPファイルなので、目的に合う方を選んでください。
ダウンロードしたZIPを展開し、sampleフォルダ内のindex.html、style.css、script.jsを同じ階層に配置します。index.htmlをブラウザで開くと、指定した初期状態でアコーディオンが表示されます。
各見出しをクリックすると、その項目だけを開閉できます。ページを再読み込みすると、HTMLで指定した初期状態に戻ります。
最初から開く項目を指定する方法
最初から開いておく項目は、index.htmlの各項目に付けるis-openクラスで指定します。
「最初からすべて開く」のサンプルでは、3つの項目すべてにis-openを付けています。
<!-- 1番目:最初から開く -->
<div class="initial-open-accordion_all-item is-open">
上記は1番目の項目の開始タグです。2番目と3番目にも同じようにis-openが付いているため、ページを開いた時点ですべての内容が表示されます。
is-openを外した項目は、最初は閉じた状態になります。
最初の項目だけ開く方法
「最初の項目だけ開く」のサンプルでは、1番目の項目にだけis-openを付けています。
<!-- 1番目:最初から開く -->
<div class="initial-open-accordion_single-item is-open">
一方、2番目と3番目にはis-openを付けていません。
<!-- 2番目:最初は閉じる -->
<div class="initial-open-accordion_single-item">
この違いによって、1番目だけが開き、残りの2項目は閉じた状態で表示されます。
2番目だけを最初から開きたい場合は、1番目のis-openを外して2番目に付けます。3番目だけ開きたい場合も同様です。
複数の項目を開きたい場合は、開いておきたい項目それぞれにis-openを付けてください。
aria-expanded属性も初期状態に合わせる
is-openを変更するときは、同じ項目のbuttonに設定されているaria-expanded属性も変更します。
開いた状態ではtrue、閉じた状態ではfalseを指定します。
これは、スクリーンリーダーなどの支援技術へ開閉状態を伝えるための属性です。
<button class="initial-open-accordion_single-button" type="button" aria-expanded="true" aria-controls="initial-open-accordion-single-panel-1">
上記は1番目の項目のボタンです。最初から開いているため、aria-expanded="true"になっています。
項目を最初から閉じる場合は、is-openを外すとともにaria-expanded="false"へ変更してください。
aria-controlsは対応する内容のIDを示しているため、開閉状態を変更するだけなら書き換える必要はありません。
項目番号の「1・2・3」と「0・1・2」の違い
今回の初期状態はHTMLのis-openで指定するため、JavaScriptで項目番号を入力する必要はありません。
ただし、JavaScriptで複数の項目を取得して番号で指定する場合、番号は通常0から始まります。
画面上の1番目は[0]、2番目は[1]、3番目は[2]に対応します。
つまり、画面上の「1・2・3」は、JavaScriptの配列では「0・1・2」になります。
セクション3のscript.jsでは、取得したボタンをforEachで順番に処理しているため、現在のコードに項目番号を追加する必要はありません。
クリックした項目だけを開閉する仕組み
開閉操作はscript.jsで行います。以下は「最初の項目だけ開く」のサンプルから抜粋した処理です。
button.addEventListener("click", function() {
// クリックしたボタンの項目を取得
const item = button.closest(".initial-open-accordion_single-item");
// is-openクラスを切り替えて内容を開閉
item.classList.toggle("is-open");
// 開閉状態をアクセシビリティ属性へ反映
button.setAttribute(
"aria-expanded",
String(item.classList.contains("is-open"))
);
});
addEventListener("click", ...)で見出しのクリックを検知し、closest()でクリックしたボタンが属する項目を取得します。
続いてclassList.toggle("is-open")によって、クラスが付いていれば外し、付いていなければ追加します。
最後にaria-expandedを更新することで、見た目と属性の開閉状態を一致させています。
この処理はクリックした項目だけを対象とするため、ほかの項目は開いたまま、または閉じたままになります。
開閉状態によって内容とアイコンが変わる仕組み
style.cssでは、通常の内容をdisplay: none;で隠し、is-openが付いた項目の内容だけを表示しています。
以下は「最初の項目だけ開く」のサンプルから抜粋したCSSです。
/* 開いた状態の内容 */
.initial-open-accordion_single-item.is-open .initial-open-accordion_single-content {
display: block; /* 内容を表示する */
}
同じis-openクラスを使って、開閉アイコンも切り替えています。
閉じているときはプラス、開いているときはマイナスを表示する仕組みです。
そのため、HTMLで初期状態を変更しても、内容とアイコンは同じ状態で表示されます。
カスタマイズできる内容
項目の見出しや説明文はindex.htmlで変更できます。見出しはinitial-open-accordion_all-labelまたはinitial-open-accordion_single-label、説明文は各content-inner要素の中を書き換えてください。
最初に開いておく項目を変更する場合は、各項目のis-openとaria-expandedをセットで調整します。
枠線の色や背景色、文字色、アイコンの色はstyle.cssから変更できます。プラス・マイナスの形状を変更したい場合は、index.html内のSVGのpathを編集します。
数値調整
style.cssのmax-width: 700px;は、アコーディオン全体の最大横幅です。値を大きくすると横に広がり、小さくすると狭くなります。
各項目のmargin: 0 0 12px;は項目同士の間隔で、border-radius: 12px;は角丸の大きさです。
開閉ボタンのpadding: 16px 18px;は上下と左右の内側余白を指定しています。値を大きくすると、ボタンの高さや文字の周囲の余白が広がります。
レスポンシブ対応
style.cssでは、アコーディオン本体にwidth: 100%;とmax-width: 700px;を設定しています。広い画面では最大700pxで表示し、狭い画面では親要素の横幅に合わせて縮小します。
また、画面幅640px以下ではメディアクエリによって、見出しとアイコンの間隔を16pxから12pxへ調整しています。長い見出しも折り返されるため、スマートフォンでも内容を確認しやすい構成です。
コメント