縦長アコーディオンは、縦方向に配置した見出しをクリックすると、内容が左右に展開するUIです。一般的なアコーディオンは見出しの下方向へ内容を開きますが、縦長アコーディオンでは横方向に開くため、画面の高さを大きく変えずに情報を切り替えられます。横並びのメニューや情報パネル、複数の項目を比較するレイアウトなどに利用でき、見出しを縦書きにすることで限られた横幅にも複数の項目を配置できます。
縦長アコーディオンには、見出しの左側へ内容を展開する「左方向」と、右側へ展開する「右方向」があります。また、それぞれの方向で「複数の項目を同時に開くタイプ」と「1つの項目だけを開くタイプ」を作成できます。見出しの並び順は左から1・2・3のまま固定し、内容を表示する位置とJavaScriptの開閉処理を変更することで、合計4種類の動作を実現します。
左方向に開くアコーディオン
左方向に開くタイプでは、縦長の見出しをクリックすると、その見出しの左側に内容が表示されます。複数開くタイプでは、別の見出しをクリックしても開いている項目は閉じず、複数の内容を同時に確認できます。一方、1つだけ開くタイプでは、新しい見出しをクリックすると、それまで開いていた項目が自動的に閉じます。
左方向に開くアコーディオン(複数開く・1つだけ開く)
右方向に開くアコーディオン
右方向に開くタイプでは、見出しの右側へ内容を展開します。複数開くタイプは、開いた項目をそのまま残しながら別の項目を追加で開けるため、複数の情報を並べて確認する場合に便利です。1つだけ開くタイプは、常に開いている項目を1つ以下に制限するため、表示する情報を絞りながら操作できます。どちらも開いている見出しをもう一度クリックすると、その項目を閉じられます。
右方向に開くアコーディオン(複数開く・1つだけ開く)
左右どちらのタイプも、内容が表示領域の横幅を超えた場合は、アコーディオン部分を横方向へスクロールして確認できます。スマートフォンなど画面幅が狭い環境でも、ページ全体を横に広げずに使用できる構成です。また、見出しの開閉状態に合わせてプラス・マイナスのアイコンを切り替えるため、現在どの項目が開いているかを視覚的に確認できます。
この記事では、HTML・CSS・JavaScriptを使って、左方向に複数開くタイプ、左方向に1つだけ開くタイプ、右方向に複数開くタイプ、右方向に1つだけ開くタイプの4種類を紹介します。デモではタブを切り替えてそれぞれの動作を比較でき、各パターンのコードも個別に確認できます。見出しの配置や開く方向、複数開閉と単一開閉の仕組みを確認しながら、縦長アコーディオンの作り方を解説します。
デモ
見出しをクリックすると左方向へ内容が開きます。複数の項目を同時に開けます。
見出しをクリックすると左方向へ内容が開きます。別の項目を開くと、前の項目が閉じます。
見出しをクリックすると右方向へ内容が開きます。複数の項目を同時に開けます。
見出しをクリックすると右方向へ内容が開きます。別の項目を開くと、前の項目が閉じます。
見出しは左から1・2・3の順番で固定されています。内容が表示領域を超えた場合は、横方向へスクロールして確認できます。
Q
他のアイコンを使いたい場合はどうするの?
コードをコピーして使おう!
<!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="vertical-accordion-open_wrap">
<div class="vertical-accordion-open_area">
<div class="vertical-accordion-open_items">
<!-- 見出し1と対応する内容 -->
<div class="vertical-accordion-open_item">
<button class="vertical-accordion-open_button" type="button" aria-expanded="false" aria-controls="accordion-content-1">
見出し1
</button>
<div class="vertical-accordion-open_content" id="accordion-content-1">
<p>1つ目の内容が表示されます。</p>
</div>
</div>
<!-- 見出し2と対応する内容 -->
<div class="vertical-accordion-open_item">
<button class="vertical-accordion-open_button" type="button" aria-expanded="false" aria-controls="accordion-content-2">
見出し2
</button>
<div class="vertical-accordion-open_content" id="accordion-content-2">
<p>2つ目の内容が表示されます。</p>
</div>
</div>
<!-- 見出し3と対応する内容 -->
<div class="vertical-accordion-open_item">
<button class="vertical-accordion-open_button" type="button" aria-expanded="false" aria-controls="accordion-content-3">
見出し3
</button>
<div class="vertical-accordion-open_content" id="accordion-content-3">
<p>3つ目の内容が表示されます。</p>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
/* アコーディオン全体 */
.vertical-accordion-open_wrap {
box-sizing: border-box; /* 横幅に余白と枠線を含める */
width: 100%; /* 親要素の横幅に合わせる */
max-width: 700px; /* 最大横幅。大きくすると全体が広がる */
margin: 0 auto; /* 左右中央に配置する */
font-family: sans-serif; /* 表示フォントを指定する */
}
/* 横スクロール領域 */
.vertical-accordion-open_area {
box-sizing: border-box; /* 余白を横幅に含める */
width: 100%; /* 親要素いっぱいに表示する */
min-height: 260px; /* 最低の高さ。大きくすると縦長になる */
overflow-x: auto; /* 横幅を超えた場合に横スクロールする */
overflow-y: hidden; /* 縦方向のはみ出しを隠す */
}
/* 見出しを左から1・2・3の順に並べる */
.vertical-accordion-open_items {
display: flex; /* 項目を横並びにする */
gap: 12px; /* 項目の間隔。大きくすると広がる */
width: max-content; /* 開いた項目に合わせて横幅を広げる */
min-width: 100%; /* 閉じたときも表示領域の横幅を確保する */
}
/* アコーディオンの各項目 */
.vertical-accordion-open_item {
display: flex; /* 見出しと内容を横並びにする */
flex-direction: row-reverse; /* 内容を見出しの左側へ配置する */
flex: 0 0 auto; /* 項目の幅を縮めない */
overflow: hidden; /* 角丸からのはみ出しを隠す */
border: 1px solid #e5e7eb; /* 項目を囲む枠線 */
border-radius: 12px; /* 角丸。大きくすると丸みが強くなる */
background: #ffffff; /* 項目の背景色 */
}
/* 縦書きの見出しボタン */
.vertical-accordion-open_button {
box-sizing: border-box; /* 余白を幅に含める */
display: flex; /* 文字と記号を配置する */
align-items: center; /* 横方向の中央に揃える */
justify-content: center; /* 縦方向の中央に揃える */
gap: 10px; /* 文字と記号の間隔 */
flex: 0 0 64px; /* 見出しの幅を64pxに固定する */
width: 64px; /* 見出しの横幅。大きくすると太くなる */
min-height: 260px; /* 見出しの最低高さ。大きくすると長くなる */
padding: 16px 10px; /* 上下左右の内側余白 */
border: none; /* 標準のボタン枠線を消す */
border-radius: 0; /* ボタン固有の角丸をなくす */
background: #ffffff; /* 見出しの背景色 */
color: #111827; /* 見出しの文字色 */
font-family: inherit; /* 親要素のフォントを使う */
font-size: 16px; /* 文字サイズ。大きくすると文字が大きくなる */
font-weight: 700; /* 見出しを太字にする */
line-height: 1.5; /* 文字の行間 */
writing-mode: vertical-rl; /* 文字を縦書きにする */
text-orientation: mixed; /* 文字の向きを適切に表示する */
cursor: pointer; /* クリックできることを示す */
}
/* 閉じているときのプラス記号 */
.vertical-accordion-open_button::after {
content: "+"; /* 閉じた状態の記号 */
color: #0b6bff; /* 記号の色 */
font-size: 18px; /* 記号の大きさ */
font-weight: 700; /* 記号を太くする */
}
/* 開いているときのマイナス記号 */
.vertical-accordion-open_item.is-open .vertical-accordion-open_button::after {
content: "-"; /* 開いた状態の記号 */
}
/* 開閉する内容 */
.vertical-accordion-open_content {
box-sizing: border-box; /* 余白と枠線を幅に含める */
display: none; /* 初期状態は非表示にする */
flex: 0 0 260px; /* 内容の幅を260pxに固定する */
width: 260px; /* 内容の横幅。大きくすると広がる */
padding: 18px; /* 内容の内側余白 */
border-right: 1px solid #e5e7eb; /* 見出しとの境界線 */
background: #ffffff; /* 内容の背景色 */
color: #4b5563; /* 内容の文字色 */
font-size: 16px; /* 内容の文字サイズ */
line-height: 1.8; /* 内容の行間 */
overflow-wrap: anywhere; /* 長い文字を折り返す */
}
/* 内容の段落 */
.vertical-accordion-open_content p {
margin: 0; /* 段落の標準余白をなくす */
}
/* 開いた項目の内容 */
.vertical-accordion-open_item.is-open .vertical-accordion-open_content {
display: block; /* 開いた内容を表示する */
}
/* スマートフォン用の調整 */
@media (max-width: 640px) {
.vertical-accordion-open_items {
gap: 8px; /* 狭い画面では項目間隔を小さくする */
}
.vertical-accordion-open_button {
flex-basis: 56px; /* ボタンの固定幅を小さくする */
width: 56px; /* ボタンの横幅を小さくする */
}
.vertical-accordion-open_content {
flex-basis: 220px; /* 内容の固定幅を小さくする */
width: 220px; /* 内容の横幅を小さくする */
}
}
/* アコーディオンの見出しボタンを取得 */
const accordionButtons = document.querySelectorAll(".vertical-accordion-open_button");
/* 各見出しにクリック処理を設定 */
accordionButtons.forEach(function (button) {
button.addEventListener("click", function () {
const item = button.closest(".vertical-accordion-open_item");
const willOpen = !item.classList.contains("is-open");
/* クリックした項目だけを開閉する */
item.classList.toggle("is-open", willOpen);
button.setAttribute("aria-expanded", String(willOpen));
});
});
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8"> <!-- 文字コード -->
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- スマートフォン対応 -->
<title>縦長アコーディオン|左に1つ</title>
<link rel="stylesheet" href="style.css"> <!-- デザインを読み込む -->
<script src="script.js" defer></script> <!-- 開閉処理を読み込む -->
</head>
<body>
<!-- 縦長アコーディオン本体 -->
<div class="vertical-accordion-open_wrap">
<div class="vertical-accordion-open_area">
<div class="vertical-accordion-open_items">
<!-- 見出し1と対応する内容 -->
<div class="vertical-accordion-open_item">
<button class="vertical-accordion-open_button" type="button" aria-expanded="false" aria-controls="accordion-content-1">
見出し1
</button>
<div class="vertical-accordion-open_content" id="accordion-content-1">
<p>1つ目の内容が表示されます。</p>
</div>
</div>
<!-- 見出し2と対応する内容 -->
<div class="vertical-accordion-open_item">
<button class="vertical-accordion-open_button" type="button" aria-expanded="false" aria-controls="accordion-content-2">
見出し2
</button>
<div class="vertical-accordion-open_content" id="accordion-content-2">
<p>2つ目の内容が表示されます。</p>
</div>
</div>
<!-- 見出し3と対応する内容 -->
<div class="vertical-accordion-open_item">
<button class="vertical-accordion-open_button" type="button" aria-expanded="false" aria-controls="accordion-content-3">
見出し3
</button>
<div class="vertical-accordion-open_content" id="accordion-content-3">
<p>3つ目の内容が表示されます。</p>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
/* アコーディオン全体 */
.vertical-accordion-open_wrap {
box-sizing: border-box; /* 横幅に余白と枠線を含める */
width: 100%; /* 親要素の横幅に合わせる */
max-width: 700px; /* 最大横幅。大きくすると全体が広がる */
margin: 0 auto; /* 左右中央に配置する */
font-family: sans-serif; /* 表示フォントを指定する */
}
/* 横スクロール領域 */
.vertical-accordion-open_area {
box-sizing: border-box; /* 余白を横幅に含める */
width: 100%; /* 親要素いっぱいに表示する */
min-height: 260px; /* 最低の高さ。大きくすると縦長になる */
overflow-x: auto; /* 横幅を超えた場合に横スクロールする */
overflow-y: hidden; /* 縦方向のはみ出しを隠す */
}
/* 見出しを左から1・2・3の順に並べる */
.vertical-accordion-open_items {
display: flex; /* 項目を横並びにする */
gap: 12px; /* 項目の間隔。大きくすると広がる */
width: max-content; /* 開いた項目に合わせて横幅を広げる */
min-width: 100%; /* 閉じたときも表示領域の横幅を確保する */
}
/* アコーディオンの各項目 */
.vertical-accordion-open_item {
display: flex; /* 見出しと内容を横並びにする */
flex-direction: row-reverse; /* 内容を見出しの左側へ配置する */
flex: 0 0 auto; /* 項目の幅を縮めない */
overflow: hidden; /* 角丸からのはみ出しを隠す */
border: 1px solid #e5e7eb; /* 項目を囲む枠線 */
border-radius: 12px; /* 角丸。大きくすると丸みが強くなる */
background: #ffffff; /* 項目の背景色 */
}
/* 縦書きの見出しボタン */
.vertical-accordion-open_button {
box-sizing: border-box; /* 余白を幅に含める */
display: flex; /* 文字と記号を配置する */
align-items: center; /* 横方向の中央に揃える */
justify-content: center; /* 縦方向の中央に揃える */
gap: 10px; /* 文字と記号の間隔 */
flex: 0 0 64px; /* 見出しの幅を64pxに固定する */
width: 64px; /* 見出しの横幅。大きくすると太くなる */
min-height: 260px; /* 見出しの最低高さ。大きくすると長くなる */
padding: 16px 10px; /* 上下左右の内側余白 */
border: none; /* 標準のボタン枠線を消す */
border-radius: 0; /* ボタン固有の角丸をなくす */
background: #ffffff; /* 見出しの背景色 */
color: #111827; /* 見出しの文字色 */
font-family: inherit; /* 親要素のフォントを使う */
font-size: 16px; /* 文字サイズ。大きくすると文字が大きくなる */
font-weight: 700; /* 見出しを太字にする */
line-height: 1.5; /* 文字の行間 */
writing-mode: vertical-rl; /* 文字を縦書きにする */
text-orientation: mixed; /* 文字の向きを適切に表示する */
cursor: pointer; /* クリックできることを示す */
}
/* 閉じているときのプラス記号 */
.vertical-accordion-open_button::after {
content: "+"; /* 閉じた状態の記号 */
color: #0b6bff; /* 記号の色 */
font-size: 18px; /* 記号の大きさ */
font-weight: 700; /* 記号を太くする */
}
/* 開いているときのマイナス記号 */
.vertical-accordion-open_item.is-open .vertical-accordion-open_button::after {
content: "-"; /* 開いた状態の記号 */
}
/* 開閉する内容 */
.vertical-accordion-open_content {
box-sizing: border-box; /* 余白と枠線を幅に含める */
display: none; /* 初期状態は非表示にする */
flex: 0 0 260px; /* 内容の幅を260pxに固定する */
width: 260px; /* 内容の横幅。大きくすると広がる */
padding: 18px; /* 内容の内側余白 */
border-right: 1px solid #e5e7eb; /* 見出しとの境界線 */
background: #ffffff; /* 内容の背景色 */
color: #4b5563; /* 内容の文字色 */
font-size: 16px; /* 内容の文字サイズ */
line-height: 1.8; /* 内容の行間 */
overflow-wrap: anywhere; /* 長い文字を折り返す */
}
/* 内容の段落 */
.vertical-accordion-open_content p {
margin: 0; /* 段落の標準余白をなくす */
}
/* 開いた項目の内容 */
.vertical-accordion-open_item.is-open .vertical-accordion-open_content {
display: block; /* 開いた内容を表示する */
}
/* スマートフォン用の調整 */
@media (max-width: 640px) {
.vertical-accordion-open_items {
gap: 8px; /* 狭い画面では項目間隔を小さくする */
}
.vertical-accordion-open_button {
flex-basis: 56px; /* ボタンの固定幅を小さくする */
width: 56px; /* ボタンの横幅を小さくする */
}
.vertical-accordion-open_content {
flex-basis: 220px; /* 内容の固定幅を小さくする */
width: 220px; /* 内容の横幅を小さくする */
}
}
/* アコーディオンの見出しボタンを取得 */
const accordionButtons = document.querySelectorAll(".vertical-accordion-open_button");
/* 各見出しにクリック処理を設定 */
accordionButtons.forEach(function (button) {
button.addEventListener("click", function () {
const item = button.closest(".vertical-accordion-open_item");
const willOpen = !item.classList.contains("is-open");
/* ほかの項目を閉じ、開閉状態を更新する */
document.querySelectorAll(".vertical-accordion-open_item").forEach(function (currentItem) {
currentItem.classList.remove("is-open");
currentItem.querySelector(".vertical-accordion-open_button").setAttribute("aria-expanded", "false");
});
/* 元が閉じていた場合だけクリックした項目を開く */
if (willOpen) {
item.classList.add("is-open");
button.setAttribute("aria-expanded", "true");
}
});
});
<!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="vertical-accordion-open_wrap">
<div class="vertical-accordion-open_area">
<div class="vertical-accordion-open_items">
<!-- 見出し1と対応する内容 -->
<div class="vertical-accordion-open_item">
<button class="vertical-accordion-open_button" type="button" aria-expanded="false" aria-controls="accordion-content-1">
見出し1
</button>
<div class="vertical-accordion-open_content" id="accordion-content-1">
<p>1つ目の内容が表示されます。</p>
</div>
</div>
<!-- 見出し2と対応する内容 -->
<div class="vertical-accordion-open_item">
<button class="vertical-accordion-open_button" type="button" aria-expanded="false" aria-controls="accordion-content-2">
見出し2
</button>
<div class="vertical-accordion-open_content" id="accordion-content-2">
<p>2つ目の内容が表示されます。</p>
</div>
</div>
<!-- 見出し3と対応する内容 -->
<div class="vertical-accordion-open_item">
<button class="vertical-accordion-open_button" type="button" aria-expanded="false" aria-controls="accordion-content-3">
見出し3
</button>
<div class="vertical-accordion-open_content" id="accordion-content-3">
<p>3つ目の内容が表示されます。</p>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
/* アコーディオン全体 */
.vertical-accordion-open_wrap {
box-sizing: border-box; /* 横幅に余白と枠線を含める */
width: 100%; /* 親要素の横幅に合わせる */
max-width: 700px; /* 最大横幅。大きくすると全体が広がる */
margin: 0 auto; /* 左右中央に配置する */
font-family: sans-serif; /* 表示フォントを指定する */
}
/* 横スクロール領域 */
.vertical-accordion-open_area {
box-sizing: border-box; /* 余白を横幅に含める */
width: 100%; /* 親要素いっぱいに表示する */
min-height: 260px; /* 最低の高さ。大きくすると縦長になる */
overflow-x: auto; /* 横幅を超えた場合に横スクロールする */
overflow-y: hidden; /* 縦方向のはみ出しを隠す */
}
/* 見出しを左から1・2・3の順に並べる */
.vertical-accordion-open_items {
display: flex; /* 項目を横並びにする */
gap: 12px; /* 項目の間隔。大きくすると広がる */
width: max-content; /* 開いた項目に合わせて横幅を広げる */
min-width: 100%; /* 閉じたときも表示領域の横幅を確保する */
}
/* アコーディオンの各項目 */
.vertical-accordion-open_item {
display: flex; /* 見出しと内容を横並びにする */
flex-direction: row; /* 内容を見出しの右側へ配置する */
flex: 0 0 auto; /* 項目の幅を縮めない */
overflow: hidden; /* 角丸からのはみ出しを隠す */
border: 1px solid #e5e7eb; /* 項目を囲む枠線 */
border-radius: 12px; /* 角丸。大きくすると丸みが強くなる */
background: #ffffff; /* 項目の背景色 */
}
/* 縦書きの見出しボタン */
.vertical-accordion-open_button {
box-sizing: border-box; /* 余白を幅に含める */
display: flex; /* 文字と記号を配置する */
align-items: center; /* 横方向の中央に揃える */
justify-content: center; /* 縦方向の中央に揃える */
gap: 10px; /* 文字と記号の間隔 */
flex: 0 0 64px; /* 見出しの幅を64pxに固定する */
width: 64px; /* 見出しの横幅。大きくすると太くなる */
min-height: 260px; /* 見出しの最低高さ。大きくすると長くなる */
padding: 16px 10px; /* 上下左右の内側余白 */
border: none; /* 標準のボタン枠線を消す */
border-radius: 0; /* ボタン固有の角丸をなくす */
background: #ffffff; /* 見出しの背景色 */
color: #111827; /* 見出しの文字色 */
font-family: inherit; /* 親要素のフォントを使う */
font-size: 16px; /* 文字サイズ。大きくすると文字が大きくなる */
font-weight: 700; /* 見出しを太字にする */
line-height: 1.5; /* 文字の行間 */
writing-mode: vertical-rl; /* 文字を縦書きにする */
text-orientation: mixed; /* 文字の向きを適切に表示する */
cursor: pointer; /* クリックできることを示す */
}
/* 閉じているときのプラス記号 */
.vertical-accordion-open_button::after {
content: "+"; /* 閉じた状態の記号 */
color: #0b6bff; /* 記号の色 */
font-size: 18px; /* 記号の大きさ */
font-weight: 700; /* 記号を太くする */
}
/* 開いているときのマイナス記号 */
.vertical-accordion-open_item.is-open .vertical-accordion-open_button::after {
content: "-"; /* 開いた状態の記号 */
}
/* 開閉する内容 */
.vertical-accordion-open_content {
box-sizing: border-box; /* 余白と枠線を幅に含める */
display: none; /* 初期状態は非表示にする */
flex: 0 0 260px; /* 内容の幅を260pxに固定する */
width: 260px; /* 内容の横幅。大きくすると広がる */
padding: 18px; /* 内容の内側余白 */
border-left: 1px solid #e5e7eb; /* 見出しとの境界線 */
background: #ffffff; /* 内容の背景色 */
color: #4b5563; /* 内容の文字色 */
font-size: 16px; /* 内容の文字サイズ */
line-height: 1.8; /* 内容の行間 */
overflow-wrap: anywhere; /* 長い文字を折り返す */
}
/* 内容の段落 */
.vertical-accordion-open_content p {
margin: 0; /* 段落の標準余白をなくす */
}
/* 開いた項目の内容 */
.vertical-accordion-open_item.is-open .vertical-accordion-open_content {
display: block; /* 開いた内容を表示する */
}
/* スマートフォン用の調整 */
@media (max-width: 640px) {
.vertical-accordion-open_items {
gap: 8px; /* 狭い画面では項目間隔を小さくする */
}
.vertical-accordion-open_button {
flex-basis: 56px; /* ボタンの固定幅を小さくする */
width: 56px; /* ボタンの横幅を小さくする */
}
.vertical-accordion-open_content {
flex-basis: 220px; /* 内容の固定幅を小さくする */
width: 220px; /* 内容の横幅を小さくする */
}
}
/* アコーディオンの見出しボタンを取得 */
const accordionButtons = document.querySelectorAll(".vertical-accordion-open_button");
/* 各見出しにクリック処理を設定 */
accordionButtons.forEach(function (button) {
button.addEventListener("click", function () {
const item = button.closest(".vertical-accordion-open_item");
const willOpen = !item.classList.contains("is-open");
/* クリックした項目だけを開閉する */
item.classList.toggle("is-open", willOpen);
button.setAttribute("aria-expanded", String(willOpen));
});
});
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8"> <!-- 文字コード -->
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- スマートフォン対応 -->
<title>縦長アコーディオン|右に1つ</title>
<link rel="stylesheet" href="style.css"> <!-- デザインを読み込む -->
<script src="script.js" defer></script> <!-- 開閉処理を読み込む -->
</head>
<body>
<!-- 縦長アコーディオン本体 -->
<div class="vertical-accordion-open_wrap">
<div class="vertical-accordion-open_area">
<div class="vertical-accordion-open_items">
<!-- 見出し1と対応する内容 -->
<div class="vertical-accordion-open_item">
<button class="vertical-accordion-open_button" type="button" aria-expanded="false" aria-controls="accordion-content-1">
見出し1
</button>
<div class="vertical-accordion-open_content" id="accordion-content-1">
<p>1つ目の内容が表示されます。</p>
</div>
</div>
<!-- 見出し2と対応する内容 -->
<div class="vertical-accordion-open_item">
<button class="vertical-accordion-open_button" type="button" aria-expanded="false" aria-controls="accordion-content-2">
見出し2
</button>
<div class="vertical-accordion-open_content" id="accordion-content-2">
<p>2つ目の内容が表示されます。</p>
</div>
</div>
<!-- 見出し3と対応する内容 -->
<div class="vertical-accordion-open_item">
<button class="vertical-accordion-open_button" type="button" aria-expanded="false" aria-controls="accordion-content-3">
見出し3
</button>
<div class="vertical-accordion-open_content" id="accordion-content-3">
<p>3つ目の内容が表示されます。</p>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
/* アコーディオン全体 */
.vertical-accordion-open_wrap {
box-sizing: border-box; /* 横幅に余白と枠線を含める */
width: 100%; /* 親要素の横幅に合わせる */
max-width: 700px; /* 最大横幅。大きくすると全体が広がる */
margin: 0 auto; /* 左右中央に配置する */
font-family: sans-serif; /* 表示フォントを指定する */
}
/* 横スクロール領域 */
.vertical-accordion-open_area {
box-sizing: border-box; /* 余白を横幅に含める */
width: 100%; /* 親要素いっぱいに表示する */
min-height: 260px; /* 最低の高さ。大きくすると縦長になる */
overflow-x: auto; /* 横幅を超えた場合に横スクロールする */
overflow-y: hidden; /* 縦方向のはみ出しを隠す */
}
/* 見出しを左から1・2・3の順に並べる */
.vertical-accordion-open_items {
display: flex; /* 項目を横並びにする */
gap: 12px; /* 項目の間隔。大きくすると広がる */
width: max-content; /* 開いた項目に合わせて横幅を広げる */
min-width: 100%; /* 閉じたときも表示領域の横幅を確保する */
}
/* アコーディオンの各項目 */
.vertical-accordion-open_item {
display: flex; /* 見出しと内容を横並びにする */
flex-direction: row; /* 内容を見出しの右側へ配置する */
flex: 0 0 auto; /* 項目の幅を縮めない */
overflow: hidden; /* 角丸からのはみ出しを隠す */
border: 1px solid #e5e7eb; /* 項目を囲む枠線 */
border-radius: 12px; /* 角丸。大きくすると丸みが強くなる */
background: #ffffff; /* 項目の背景色 */
}
/* 縦書きの見出しボタン */
.vertical-accordion-open_button {
box-sizing: border-box; /* 余白を幅に含める */
display: flex; /* 文字と記号を配置する */
align-items: center; /* 横方向の中央に揃える */
justify-content: center; /* 縦方向の中央に揃える */
gap: 10px; /* 文字と記号の間隔 */
flex: 0 0 64px; /* 見出しの幅を64pxに固定する */
width: 64px; /* 見出しの横幅。大きくすると太くなる */
min-height: 260px; /* 見出しの最低高さ。大きくすると長くなる */
padding: 16px 10px; /* 上下左右の内側余白 */
border: none; /* 標準のボタン枠線を消す */
border-radius: 0; /* ボタン固有の角丸をなくす */
background: #ffffff; /* 見出しの背景色 */
color: #111827; /* 見出しの文字色 */
font-family: inherit; /* 親要素のフォントを使う */
font-size: 16px; /* 文字サイズ。大きくすると文字が大きくなる */
font-weight: 700; /* 見出しを太字にする */
line-height: 1.5; /* 文字の行間 */
writing-mode: vertical-rl; /* 文字を縦書きにする */
text-orientation: mixed; /* 文字の向きを適切に表示する */
cursor: pointer; /* クリックできることを示す */
}
/* 閉じているときのプラス記号 */
.vertical-accordion-open_button::after {
content: "+"; /* 閉じた状態の記号 */
color: #0b6bff; /* 記号の色 */
font-size: 18px; /* 記号の大きさ */
font-weight: 700; /* 記号を太くする */
}
/* 開いているときのマイナス記号 */
.vertical-accordion-open_item.is-open .vertical-accordion-open_button::after {
content: "-"; /* 開いた状態の記号 */
}
/* 開閉する内容 */
.vertical-accordion-open_content {
box-sizing: border-box; /* 余白と枠線を幅に含める */
display: none; /* 初期状態は非表示にする */
flex: 0 0 260px; /* 内容の幅を260pxに固定する */
width: 260px; /* 内容の横幅。大きくすると広がる */
padding: 18px; /* 内容の内側余白 */
border-left: 1px solid #e5e7eb; /* 見出しとの境界線 */
background: #ffffff; /* 内容の背景色 */
color: #4b5563; /* 内容の文字色 */
font-size: 16px; /* 内容の文字サイズ */
line-height: 1.8; /* 内容の行間 */
overflow-wrap: anywhere; /* 長い文字を折り返す */
}
/* 内容の段落 */
.vertical-accordion-open_content p {
margin: 0; /* 段落の標準余白をなくす */
}
/* 開いた項目の内容 */
.vertical-accordion-open_item.is-open .vertical-accordion-open_content {
display: block; /* 開いた内容を表示する */
}
/* スマートフォン用の調整 */
@media (max-width: 640px) {
.vertical-accordion-open_items {
gap: 8px; /* 狭い画面では項目間隔を小さくする */
}
.vertical-accordion-open_button {
flex-basis: 56px; /* ボタンの固定幅を小さくする */
width: 56px; /* ボタンの横幅を小さくする */
}
.vertical-accordion-open_content {
flex-basis: 220px; /* 内容の固定幅を小さくする */
width: 220px; /* 内容の横幅を小さくする */
}
}
/* アコーディオンの見出しボタンを取得 */
const accordionButtons = document.querySelectorAll(".vertical-accordion-open_button");
/* 各見出しにクリック処理を設定 */
accordionButtons.forEach(function (button) {
button.addEventListener("click", function () {
const item = button.closest(".vertical-accordion-open_item");
const willOpen = !item.classList.contains("is-open");
/* ほかの項目を閉じ、開閉状態を更新する */
document.querySelectorAll(".vertical-accordion-open_item").forEach(function (currentItem) {
currentItem.classList.remove("is-open");
currentItem.querySelector(".vertical-accordion-open_button").setAttribute("aria-expanded", "false");
});
/* 元が閉じていた場合だけクリックした項目を開く */
if (willOpen) {
item.classList.add("is-open");
button.setAttribute("aria-expanded", "true");
}
});
});
コードについて
本記事のコードはサンプルコードです。ご利用前に必ず動作確認を行ってください。
免責事項
本コードの利用により発生した損害について、当サイトは一切の責任を負いません。
コードをコピーする場合
使用するコードのタブを選び、「このタブをコピー」をクリックすると、現在表示中のコードをコピーできます。
サンプル一式を取得する場合
HTML・CSSなどすべてのファイルが必要な場合は、「サンプル一式をダウンロード」をクリックしてください。
Q
ダウンロードしたけど、これをネット上で動かすにはどうするの?
ファイル構成と設置方法
このサンプルはHTML・CSS・JavaScriptの3ファイルで構成されています。HTMLでは縦書きの見出しと開閉する内容を配置し、CSSでは見出しのサイズや左右の展開方向、背景色、枠線などを設定します。JavaScriptでは見出しをクリックしたときの開閉動作を制御します。
今回は「左に複数」「左に1つ」「右に複数」「右に1つ」の4種類を用意しています。左右の展開方向はCSSで設定し、複数開くか1つだけ開くかはJavaScriptで制御しています。それぞれ独立したサンプルとしてダウンロードできるため、使用したいタイプを選んで設置してください。
sample/
├── index.html
├── style.css
└── script.js
各ファイルの役割
index.htmlは縦長アコーディオンの構造を設定するファイルです。見出し1〜3の開閉ボタンと、それぞれに対応する内容を配置しています。見出しや文章を書き換えたり、項目を追加・削除したりできます。
style.cssは縦長アコーディオンのデザインを設定するファイルです。見出しの縦書き表示、内容の展開方向、各項目の横幅や高さ、背景色、枠線、角丸などを変更できます。また、開閉状態に応じた内容の表示切り替えや、スマートフォン向けのサイズ調整も設定しています。
script.jsはアコーディオンの開閉動作を制御するファイルです。複数開くタイプではクリックした項目だけを開閉し、1つだけ開くタイプでは新しい項目を開く際に、ほかの項目を自動的に閉じます。
設置方法・使い方
使用したいアコーディオンの「サンプル一式をダウンロード」をクリックし、ZIPファイルを保存してください。ZIPを展開するとsampleフォルダが作成され、その中にindex.html・style.css・script.jsが入っています。
3つのファイルを同じ階層に配置した状態で、sample/index.htmlをブラウザで開いてください。index.htmlからstyle.cssとscript.jsを読み込むことで、デザインと開閉機能が適用されます。
縦書きの見出しをクリックすると、対応する内容が左方向または右方向に表示されます。複数開くタイプではほかの項目を開いても元の項目は閉じず、1つだけ開くタイプでは新しい項目を開くと、それまで開いていた項目が自動的に閉じます。どちらも開いている見出しをもう一度クリックすると閉じられます。
複数の項目を開いて表示領域の横幅を超えた場合は、アコーディオン部分を横方向にスクロールして内容を確認できます。
左右の展開方向を切り替える仕組み
左右の展開方向は、style.cssのflex-directionで設定しています。各項目の見出しと内容を横並びにし、その並び方を変更することで展開方向を切り替えています。
左方向に開くタイプでは、次のCSSを使用します。
flex-direction: row-reverse;
row-reverseは要素の並び順を反転させる指定です。HTMLでは見出しのあとに内容を配置していますが、この指定によって内容が見出しの左側に表示されます。
右方向に開くタイプでは、次のCSSを使用します。
flex-direction: row;
rowは要素を通常の順番で横並びにする指定です。見出しの右側に内容が配置されるため、クリックすると右方向に展開します。
どちらも見出し1〜3の並び順は変更せず、各項目の内容が開く方向だけを切り替えています。
複数開くタイプと1つだけ開くタイプの違い
どちらのタイプも、JavaScriptでis-openクラスを付け外しすることで、内容の表示・非表示を切り替えています。
複数開くタイプでは、クリックした項目に対して次の処理を実行します。
item.classList.toggle("is-open", willOpen);
button.setAttribute("aria-expanded", String(willOpen));
classList.toggle()によって、クリックした項目だけにis-openクラスを追加・削除します。ほかの項目の状態は変更しないため、複数の内容を同時に表示できます。
一方、1つだけ開くタイプでは、新しい項目を開く前に、同じアコーディオン内のほかの項目を閉じる処理を実行します。これにより、開いている項目を1つ以下に制限しています。
どちらのタイプもaria-expanded属性を更新し、ボタンの開閉状態を反映しています。
カスタマイズできる内容
見出しと内容の変更
index.htmlでは、「見出し1」「見出し2」「見出し3」の文字を変更できます。また、それぞれの見出しに対応する文章を書き換えることで、展開時に表示する内容を変更できます。
項目の追加・削除
index.htmlのvertical-accordion-open_itemを複製すると項目を追加できます。不要な項目は、対応する見出しと内容を含む要素ごと削除してください。
見出しの縦書き
style.cssのwriting-mode: vertical-rl;によって、見出しを縦書きで表示しています。横書きに変更したい場合は、この指定を変更し、必要に応じて見出しの横幅や高さも調整してください。
色とデザイン
style.cssのbackgroundで背景色、colorで文字色、borderで枠線、border-radiusで角丸を変更できます。開閉を示すプラス・マイナス記号の色も、見出しボタンの::afterで変更できます。
数値調整
アコーディオン全体の最大横幅:700px
style.cssの.vertical-accordion-open_wrapにあるmax-width: 700px;で調整できます。数値を大きくするとアコーディオン全体の表示領域が広がり、小さくすると狭くなります。
見出しの横幅:64px
style.cssの.vertical-accordion-open_buttonにあるflex: 0 0 64px;とwidth: 64px;で調整できます。数値を大きくすると縦長の見出しが太くなり、小さくすると細くなります。変更する場合は両方の数値を揃えてください。
見出しの最低高さ:260px
style.cssの.vertical-accordion-open_buttonにあるmin-height: 260px;で調整できます。数値を大きくすると見出しが縦に長くなり、小さくすると短くなります。必要に応じて.vertical-accordion-open_areaのmin-height: 260px;も同じ値に変更してください。
展開する内容の横幅:260px
style.cssの.vertical-accordion-open_contentにあるflex: 0 0 260px;とwidth: 260px;で調整できます。数値を大きくすると開いた内容の表示領域が広がり、小さくすると狭くなります。変更する場合は両方の数値を揃えてください。
項目間の余白:12px
style.cssの.vertical-accordion-open_itemsにあるgap: 12px;で調整できます。数値を大きくすると見出し同士の間隔が広がり、小さくすると狭くなります。
レスポンシブ対応
画面幅が640px以下になると、メディアクエリによって見出しの横幅を64pxから56px、展開する内容の横幅を260pxから220pxに変更しています。また、項目間の余白も12pxから8pxに縮小しています。
スマートフォン向けの数値を変更する場合は、style.cssの@media (max-width: 640px)内にあるflex-basisとwidthをそれぞれ同じ値に調整してください。
アコーディオン部分にはoverflow-x: auto;を設定しているため、画面幅を超える場合でも横方向にスクロールできます。これにより、スマートフォンでも複数の項目を開いて内容を確認できます。
コメント