アコーディオンパネルのコードと表示結果 - 枠のコンテンツの冒頭が少し見えるアコーディオンパネル

げんとー
質問: 折りたたみのできる枠で最初の部分だけ見せたい
折りたたみのできる枠(アコーディオンパネル)を実装したいのですが、閉じた状態でも最初の10行ぐらいは見えるようにしたいです。 どのようなコードで実装するのが良いでしょうか?

はじめに

こちらの記事では、detailsタグを利用したアコーディオンパネルを実装しました。 シンプルなアコーディオンパネルは紹介した記事で実装できますが、枠の先頭の一部を表示した状態にしたい場合は、detailsタグを利用せず、 スタイルシートの切り替えで実装したほうが良い場合があります。この記事では、JavaScriptを利用してスタイルを切り替えてアコーディオンパネルを 実装するコードと実行結果を紹介します。

方針

枠の大きさが変化するアコーディオンパネルの場合は、ボタン等をクリックして、枠を開く際にCSSのサブクラスを追加して、スタイルを切り替える方式にします。
今回の例では、AccordionContentFrameクラスを用意して、展開時にexpandedサブクラスを追加します。 .AccordionContentFrame.expandedに枠が開かれた状態のスタイルを記述します。
コンテンツエリアが完全に表示、非表示が切り替わる場合は、たたまれるエリアにdisplay:none;をして非表示にする方法で実装します。

枠のコンテンツの冒頭が少し見えるアコーディオンパネル

コード

以下のHTML、CSSファイルを作成します。
PeekAccordionPanel.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">
      コンテンツです<br />
      コンテンツです<br />
      コンテンツです<br />
      コンテンツです<br />
      コンテンツです<br />
      コンテンツです<br />
      コンテンツです<br />
    </div>
    <button type="button" class="AccordionToggleButton" aria-expanded="false">もっと見る</button>
  </div>
</body>
</html>
PeekAccordionPanel.css
.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プロパティにセットされるロジックがわかりにくいですが、次のロジックで名称が決まります。
  1. data- プレフィックス: HTML のカスタム属性は必ず data- で始まります。例: data-expand-text
  2. ハイフン区切り (-) の変換: data- の後に続く属性名は、JavaScript の dataset オブジェクトで キャメルケース に変換されます。例: data-expand-text → dataset.expandText
  3. 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ブラウザで表示します。下図のページが表示されます。枠の冒頭のコンテンツのみが表示され、[もっと見る]ボタンが表示されています。
アコーディオンパネルのコードと表示結果 - 枠のコンテンツの冒頭が少し見えるアコーディオンパネル:画像1

[もっと見る]ボタンをクリックします。枠が展開され、すべてのコンテンツが表示されます。
アコーディオンパネルのコードと表示結果 - 枠のコンテンツの冒頭が少し見えるアコーディオンパネル:画像2

[閉じる]ボタンをクリックすると枠が折りたたまれ、枠の冒頭のコンテンツのみが表示されます。
アコーディオンパネルのコードと表示結果 - 枠のコンテンツの冒頭が少し見えるアコーディオンパネル:画像3

補足:枠が複数ある場合

アコーディオンパネルを複数設置した、以下の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>

それぞれの枠に対して、展開と折りたたみができます。
アコーディオンパネルのコードと表示結果 - 枠のコンテンツの冒頭が少し見えるアコーディオンパネル:画像4 アコーディオンパネルのコードと表示結果 - 枠のコンテンツの冒頭が少し見えるアコーディオンパネル:画像5
アコーディオンパネルのコードと表示結果 - 枠のコンテンツの冒頭が少し見えるアコーディオンパネル:画像6 アコーディオンパネルのコードと表示結果 - 枠のコンテンツの冒頭が少し見えるアコーディオンパネル:画像7

コンテンツ領域が完全に非表示になる折りたたみパネル

JavaScriptによる、領域が完全に折りたたまれるパネルの実装です。
メモ
CSSの隣接セレクタとチェックボックスを利用すると、JavaScriptを記述せずにアコーディオンパネルが実装できます。 CSSのみでアコーディオンパネルを作成する手順については「折りたたみ可能なパネルの作成 - CSSのみを利用した折りたたみ領域 / アコーディオンパネル」の記事を参照してください。

コード

以下のコードを記述します。
ExpandPanel.html
<!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ファイルを表示します。下図の画面が表示されます。
アコーディオンパネルのコードと表示結果 - 枠のコンテンツの冒頭が少し見えるアコーディオンパネル:画像8

[見出し]のエリアをクリックすると見出しの下のコンテンツ枠が閉じられます。
アコーディオンパネルのコードと表示結果 - 枠のコンテンツの冒頭が少し見えるアコーディオンパネル:画像9
補足1
  <div id="ContentsPanel" style="width:240px;border:1px solid #008d18;display:none;">
    コンテンツ<br />
    ABCDEFG<br />
    あいうえお<br />
  </div>
コンテンツのDiv枠のスタイルに"display:none;"を指定するとページ読み込み時にパネルが閉じた状態になります。
AuthorPortraitAlt
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
作成日: 2025-05-04
Copyright © 1995–2025 iPentec all rights reserverd.