アコーディオンパネルのコードと表示結果 - 枠のコンテンツの冒頭が少し見えるアコーディオンパネル
質問: 折りたたみのできる枠で最初の部分だけ見せたい
折りたたみのできる枠(アコーディオンパネル)を実装したいのですが、閉じた状態でも最初の10行ぐらいは見えるようにしたいです。
どのようなコードで実装するのが良いでしょうか?
はじめに
こちらの記事では、detailsタグを利用したアコーディオンパネルを実装しました。
シンプルなアコーディオンパネルは紹介した記事で実装できますが、枠の先頭の一部を表示した状態にしたい場合は、detailsタグを利用せず、
スタイルシートの切り替えで実装したほうが良い場合があります。この記事では、JavaScriptを利用してスタイルを切り替えてアコーディオンパネルを
実装するコードと実行結果を紹介します。
方針
枠の大きさが変化するアコーディオンパネルの場合は、ボタン等をクリックして、枠を開く際にCSSのサブクラスを追加して、スタイルを切り替える方式にします。
今回の例では、
AccordionContentFrame
クラスを用意して、展開時に
expanded
サブクラスを追加します。
.AccordionContentFrame.expanded
に枠が開かれた状態のスタイルを記述します。
コンテンツエリアが完全に表示、非表示が切り替わる場合は、たたまれるエリアに
display:none;
をして非表示にする方法で実装します。
枠のコンテンツの冒頭が少し見えるアコーディオンパネル
コード
以下のHTML、CSSファイルを作成します。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<link rel="stylesheet" href="PeekAccordionPanel.css" />
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function () {
document.querySelectorAll('.AccordionFrame').forEach(accordion => {
const btn_ac = accordion.querySelector('.AccordionToggleButton');
const content_ac = accordion.querySelector('.AccordionContentFrame');
const expandText = accordion.dataset.expandText;
const collapseText = accordion.dataset.collapseText;
if (btn_ac != null){
btn_ac.addEventListener('click', () => {
const expanded = content_ac.classList.toggle('expanded');
btn_ac.textContent = expanded ? collapseText : expandText;
btn_ac.setAttribute('aria-expanded', expanded.toString());
});
}
});
});
</script>
</head>
<body>
<h1>アコーディオンパネルのデモ</h1>
<div class="AccordionFrame" data-expand-text="もっと見る" data-collapse-text="閉じる">
<div class="AccordionContentFrame">
コンテンツです<br />
コンテンツです<br />
コンテンツです<br />
コンテンツです<br />
コンテンツです<br />
コンテンツです<br />
コンテンツです<br />
</div>
<button type="button" class="AccordionToggleButton" aria-expanded="false">もっと見る</button>
</div>
</body>
</html>
.AccordionFrame {
border:1px solid #808080;
}
.AccordionContentFrame {
max-height: 96px;
overflow: hidden;
transition: max-height .3s;
mask-image: linear-gradient(to bottom, black 70%, transparent 100%);
}
.AccordionContentFrame.expanded {
max-height: none;
mask-image: none;
}
.AccordionExpandButtonFrame {
max-height: none;
mask-image: none;
}
.AccordionToggleButton {
display: block;
margin: 12px auto;
padding: 6px 16px;
font-size: 0.8rem;
background-color: #FFFFFF;
border: 1px solid #808080;
border-radius: 20px;
cursor: pointer;
}
解説
ドキュメントが読み込まれたタイミングでJavaScriptを実行します。
document.addEventListener("DOMContentLoaded", function () {
/* 略 */
});
AccordionFrame
クラスを持つ要素を取得します。取得するごとに、forEachメソッドに与えた関数
accordion => {}
を実行します。
document.querySelectorAll('.AccordionFrame').forEach(accordion => {
}
});
最初の4行は
AccordionFrame
要素内の
AccordionToggleButton
AccordionContentFrame
を取得するコードと
AccordionFrame
要素の
expandText
collapseText
属性を取得するコードです。
後半は、ボタンの要素のクリックイベントを設定するコードです。クリックされた際に、
expanded
サブクラスを追加しボタンの文字列を変更し、aria-expandedの値を更新しています。
const btn_ac = accordion.querySelector('.AccordionToggleButton');
const content_ac = accordion.querySelector('.AccordionContentFrame');
const expandText = accordion.dataset.expandText;
const collapseText = accordion.dataset.collapseText;
if (btn_ac != null){
btn_ac.addEventListener('click', () => {
const expanded = content_ac.classList.toggle('expanded');
btn_ac.textContent = expanded ? collapseText : expandText;
btn_ac.setAttribute('aria-expanded', expanded.toString());
});
data-expand-textがdataset.expandTextプロパティにセットされるロジック
data-expand-textがdataset.expandTextプロパティにセットされるロジックがわかりにくいですが、次のロジックで名称が決まります。
- data- プレフィックス: HTML のカスタム属性は必ず data- で始まります。例: data-expand-text
- ハイフン区切り (-) の変換: data- の後に続く属性名は、JavaScript の dataset オブジェクトで キャメルケース に変換されます。例: data-expand-text → dataset.expandText
- dataset オブジェクト: JavaScript では、dataset オブジェクトを通じて、data-* 属性にアクセスできます。accordion.dataset.expandText で data-expand-text の値を取得可能
CSSは閉じられた状態では、
max-height:96px
としており、96ピクセルまでコンテンツが表示されています。
mask-image
は枠の下部をフェードアウトする効果です。詳細は
こちらの記事を参照してください。
.AccordionContentFrame {
max-height: 96px;
overflow: hidden;
transition: max-height .3s;
mask-image: linear-gradient(to bottom, black 70%, transparent 100%);
}
枠が展開された状態では、
max-height
mask-image
の設定をなしにします。
.AccordionContentFrame.expanded {
max-height: none;
mask-image: none;
}
実行結果
上記のHTMLファイルをWebブラウザで表示します。下図のページが表示されます。枠の冒頭のコンテンツのみが表示され、[もっと見る]ボタンが表示されています。
[もっと見る]ボタンをクリックします。枠が展開され、すべてのコンテンツが表示されます。
[閉じる]ボタンをクリックすると枠が折りたたまれ、枠の冒頭のコンテンツのみが表示されます。
補足:枠が複数ある場合
アコーディオンパネルを複数設置した、以下のHTMLの場合でも問題なく動作します。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<link rel="stylesheet" href="PeekAccordionPanel.css" />
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function () {
document.querySelectorAll('.AccordionFrame').forEach(accordion => {
const btn_ac = accordion.querySelector('.AccordionToggleButton');
const content_ac = accordion.querySelector('.AccordionContentFrame');
const expandText = accordion.dataset.expandText;
const collapseText = accordion.dataset.collapseText;
if (btn_ac != null){
btn_ac.addEventListener('click', () => {
const expanded = content_ac.classList.toggle('expanded');
btn_ac.textContent = expanded ? collapseText : expandText;
btn_ac.setAttribute('aria-expanded', expanded.toString());
});
}
});
});
</script>
</head>
<body>
<h1>アコーディオンパネルのデモ</h1>
<div class="AccordionFrame" data-expand-text="もっと見る" data-collapse-text="閉じる">
<div class="AccordionContentFrame">
コンテンツ1です<br />
コンテンツ2です<br />
コンテンツ3です<br />
コンテンツ4です<br />
コンテンツ5です<br />
コンテンツ6です<br />
コンテンツ7です<br />
コンテンツ8です<br />
コンテンツ9です<br />
コンテンツ10です<br />
</div>
<button type="button" class="AccordionToggleButton" aria-expanded="false">もっと見る</button>
</div>
<hr/>
<div class="AccordionFrame" data-expand-text="もっと見る" data-collapse-text="閉じる">
<div class="AccordionContentFrame">
コンテンツAです<br />
コンテンツBです<br />
コンテンツCです<br />
コンテンツDです<br />
コンテンツEです<br />
コンテンツFです<br />
コンテンツGです<br />
コンテンツHです<br />
コンテンツIです<br />
コンテンツJです<br />
</div>
<button type="button" class="AccordionToggleButton" aria-expanded="false">もっと見る</button>
</div>
</body>
</html>
それぞれの枠に対して、展開と折りたたみができます。
コンテンツ領域が完全に非表示になる折りたたみパネル
JavaScriptによる、領域が完全に折りたたまれるパネルの実装です。
コード
以下のコードを記述します。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<script type="text/ecmascript">
function HeaderClick() {
target = document.getElementById("ContentsPanel");
if (target.style.display == "none") {
target.style.display = "block";
} else {
target.style.display = "none";
}
}
</script>
</head>
<body>
<div>パネルの上</div>
<div id="ContentsHeader" style="width:240px;border:1px solid #008d18; background-color:#b6ff00;"
onclick="HeaderClick();">見出し</div>
<div id="ContentsPanel" style="width:240px;border:1px solid #008d18;">
コンテンツ<br />
ABCDEFG<br />
あいうえお<br />
</div>
<div>パネルの下</div>
</body>
</html>
解説
パネルの切り替えは、JavvaScriptでスタイルを変更することで実現します。パネルを表示させる場合はstyle.displayを"block"に非表示にする場合は"none"に設定します。
JavaScript部
function HeaderClick() {
target = document.getElementById("ContentsPanel");
if (target.style.display == "none") {
target.style.display = "block";
} else {
target.style.display = "none";
}
}
ヘッダのdiv枠のクリックにより実行されるJavaScriptです。"ContentsPanel"IDを持つ要素を取得し、styleのdisplayプロパティが"none"であれば要素(div枠)を表示し、それ以外の場合は要素(div枠)を非表示します。style.displayの値を変更して、m表示、非表示の切り替えをします。
HTML
<div id="ContentsHeader" style="width:240px;border:1px solid #008d18; background-color:#b6ff00;"
onclick="HeaderClick();">見出し</div>
<div id="ContentsPanel" style="width:240px;border:1px solid #008d18;">
コンテンツ<br />
ABCDEFG<br />
あいうえお<br />
</div>
HTMLの折りたたみ枠はdiv枠で記述します。見出しの枠にはonclick属性を記述し、クリックされた際にJavaScriptを実行する動作にします。
実行結果
HTMLファイルを表示します。下図の画面が表示されます。
[見出し]のエリアをクリックすると見出しの下のコンテンツ枠が閉じられます。
補足1
<div id="ContentsPanel" style="width:240px;border:1px solid #008d18;display:none;">
コンテンツ<br />
ABCDEFG<br />
あいうえお<br />
</div>
コンテンツのDiv枠のスタイルに"display:none;"を指定するとページ読み込み時にパネルが閉じた状態になります。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用