標準のdetailsブロック(詳細ブロック)をスムーズに開閉させる方法(メモ)

公開日:2024(令和6)年3月23日/最終更新日:

WordPress Customize Ideas | Personal WP Customization Notes (PWCN)

【景品表示法に基づく表記】ページ内のコンテンツには、商品プロモーションが含まれています

WordPressの「詳細ブロック」ご存じですか?数々のブロックの中にひっそりとあるので気づいてすらいない方も多いのでは?

このブロックを使うと、タイトルをクリックしたら中身がバーンと展開される、開閉式のコンテンツ(いわゆるアコーディオンコンテンツ)が簡単に作れるんです。しかもいくつものブロックを自由に内包でき、色なども指定できるので、今までショートコードや特別なブロックを持つプラグイン・テーマで実装していたものが簡単に実現できます。

ただ、この「詳細ブロック」にはちょっと難点というかアレな部分があります。それが、開閉がガクッと進むことです。クリックしたらゆっくり開いて、もう一度クリックしたらゆっくり閉じるなんてことができないんです。

まあそれでも開閉コンテンツのためにプラグインを使うよりはいいのかもしれないですけど、できればゆっくりを実現させたい!と思って試行錯誤したら実装できましたので、メモを兼ねて公開しておきます。

多分このページに到達した方は同じことを考えていて、挫折した方かも..と感じますので、詳しい説明は後にして、さっそく以下で動作サンプルをお見せします。

「詳細」ブロックのタイトルというところをクリックすると中に入れた複数のブロックで作ったコンテンツがゆっくり開閉します)

「詳細」ブロックのタイトル

段落を挿入

列1列2列3
表の内容表の内容表の内容
表の内容表の内容表の内容
表の内容表の内容表の内容
標準のdetailsブロック(詳細ブロック)をスムーズに開閉させる方法(メモ)|Personal WP Customization Notes (PWCN)

どうでしょう?ああいい感じ..と感じた方は実装してみてくださいね。

自身この方法でサイトへ実装し続けようと思っているので、時点ではうまく動作しているかと思いますが、ひょっとして未来にもっといい方法があったら変更しているかも知れませんし、動作を停止させているかも知れませんのであしからず..

コードを使用する前に、ここをクリックして注意事項をご確認ください

本ページで掲載しているコードは、以下に了承した上で使用ください

  • コードは商用・非商用問わず自由に使っていただいて構いませんが、コード追加による不具合やトラブルが発生しても当方では一切責任を負いません
  • コードは有効化しているテーマのfunctions.php、style.cssなどへ追加することで機能します。それらのファイルへの変更を行うことに不安のある方は使用しないでください
  • コードは本ページの公開日時点で私の環境において動作したものです。WordPressバージョン他環境の違いによって動作しないことがあります
  • コードは、セキュリティ、コードの正確さなどにおいて完全なものではありません。中には紹介するコードを簡略化するために省略している部分があるものもありますので、ご自身でコードを十分に検証し、必要な部分の編集を行った上で使用するようにしてください
  • 掲載しているのは参考コードです。自身の環境に合わせるための編集はご自身で対応いただく必要があります(コメント欄等から質問いただいても基本回答は致しません)
  • 掲載しているコードの転載を禁じます(SNSで紹介いただいたり、本ページへのリンクを張っていただくことは大歓迎です)

「詳細」ブロックをゆっくり開閉させるためのコード

jsファイルを作って以下のコードを挿入し、WordPress標準のjQueryの後で読み込まれるようにすれば動作します(こんなカスタマイズする人はこの程度の解説で実装可能でしょう..)。

/*** 標準のdetails(詳細)ブロックをゆっくり開閉 ***/
/* /summaryタグの後ろから/detailsタグの手前までをdivでラップ */
document.addEventListener("DOMContentLoaded", function() {
  // summary要素を取得
  var summaries = document.querySelectorAll("summary");

  // 各summary要素に対して処理を行う
  summaries.forEach(function(summary) {
    // details要素を取得
    var details = summary.parentNode;

    // details要素内のsummary要素とそれに続く兄弟要素を取得
    var elementsToWrap = [];
    var currentElement = summary.nextElementSibling;
    while (currentElement && currentElement.tagName !== "DETAILS") {
      elementsToWrap.push(currentElement);
      currentElement = currentElement.nextElementSibling;
    }

    // 要素をdivでラップする
    var wrapper = document.createElement("div");
    elementsToWrap.forEach(function(element) {
      wrapper.appendChild(element);
    });

    // div要素にクラスを付与
    wrapper.classList.add("pwcn-accordion__content"); // ここにクラス名を指定してください

    // div要素をdetails要素内の正しい位置に挿入
    details.insertBefore(wrapper, summary.nextSibling);
  });
});

/* details summaryタグにそれぞれクラスを付与 */
jQuery(function () {
  jQuery('details').addClass('pwcn-accordion');
  jQuery('summary').addClass('pwcn-accordion__title');
});

/* クリックでゆっくり開閉 */
jQuery(function($) {
    let accordionDetails = '.pwcn-accordion';
    let accordionSummary = '.pwcn-accordion__title';
    let accordionContent = '.pwcn-accordion__content';
    let speed = 400;

    $(accordionSummary).each(function (){
        $(this).on("click",function (event){
            event.preventDefault();
            let content = $(this).nextAll(accordionContent);
            if($(this).parent(accordionDetails).attr("open")){
                content.css('max-height', content.height()).animate({ 'max-height': 0 }, speed, function(){
                    $(this).parent(accordionDetails).removeAttr("open");
                    $(this).hide().css('max-height', '');
                });
            }else{
                $(this).parent(accordionDetails).attr("open","true");
                content.css('max-height', 0).show().animate({ 'max-height': content.prop('scrollHeight') }, speed, function(){
                    $(this).css('max-height', '');
                });
            }
        })
    });
});

コードで行っていること

ブロックを使わず、detailsタグでjQueryを使ってスムーズに開閉させる場合、以下のようなhtml構造を作って、開閉に応じてjQueryで処理させるというのが一般的です。

<details class="全体をラップするクラス">
  <summary class="タイトルのクラス">Title</summary>
  <div class="開閉させる内容のクラス">
  .....
  </div>
</details>

jQueryは割愛しますけど、動作的にはこんな感じになりますね。

  • summaryタグの内容を表示させておく
  • 「タイトルのクラス」が付与されたsummaryタグをクリックしたらdetailsタグに「open」属性を付与する
  • open属性が付与されている間だけdivタグの中身を表示

これを実現しようとすると、WordPress標準のdetailsブロックでは以下の措置が必要になります。

  1. detailsタグに「全体をラップするクラス」を追加する
  2. summaryタグに「タイトルのクラス」を追加する
  3. 複数あるかもしれない中身全部を「開閉させる内容のクラス」を持つdivタグで囲む

先ほどの全コードの中で1と2を行っているのが以下の部分、これはaddClassで簡単に追加できます。

/* details summaryタグにそれぞれクラスを付与 */
jQuery(function () {
  jQuery('details').addClass('pwcn-accordion');
  jQuery('summary').addClass('pwcn-accordion__title');
});

苦労したのが、開閉させる中身をdivでラップする部分。まあブロックエディター内で中身すべてを手動でグループ化して「開閉させる内容のクラス」を付与すればいい話ではあるものの、できれば自動化したい、そこで出来上がったのが以下の部分、出力されたHTMLから要素を探して必要なところをdivで囲むという措置です。

/* /summaryタグの後ろから/detailsタグの手前までをdivでラップ */
document.addEventListener("DOMContentLoaded", function() {
  // summary要素を取得
  var summaries = document.querySelectorAll("summary");

  // 各summary要素に対して処理を行う
  summaries.forEach(function(summary) {
    // details要素を取得
    var details = summary.parentNode;

    // details要素内のsummary要素とそれに続く兄弟要素を取得
    var elementsToWrap = [];
    var currentElement = summary.nextElementSibling;
    while (currentElement && currentElement.tagName !== "DETAILS") {
      elementsToWrap.push(currentElement);
      currentElement = currentElement.nextElementSibling;
    }

    // 要素をdivでラップする
    var wrapper = document.createElement("div");
    elementsToWrap.forEach(function(element) {
      wrapper.appendChild(element);
    });

    // div要素にクラスを付与
    wrapper.classList.add("pwcn-accordion__content"); // ここにクラス名を指定してください

    // div要素をdetails要素内の正しい位置に挿入
    details.insertBefore(wrapper, summary.nextSibling);
  });
});

最後に、開閉速度をもう少し速く(遅く)したい場合は以下の部分の400という数字を変更してください。

    let speed = 400;

後述..実はこのコード、自前で全部作成したものではなく、インターネット上で紹介されていた多数のditailsタグに対するアニメーション化の情報をいくつも実装してコードの理解をある程度した上で、AI様と対話して作成したものです。長年やりたくてもできなかったことがこうして実現できると、AIのありがたみを感じますね。

コード使用時の注意点

フロントエンドでditailsタグを使用している場所すべてがこの仕様になる

このコードはフロントエンドに出力されたHTML要素の中でditailsタグを使用した部分を見つけて同じ動作をするようにします。

従って、このコードをそのまま実装すると、ページ内にある詳細ブロック(detailsタグで囲まれた要素)すべてがこの動作仕様になります。

コードでは、クラスの追加と、中身をdivで囲むということしかしていないので、追加するCSSクラスが被らなければ、多分他のプラグインなどが出力するものと競合したりすることはないとは思いますが、不具合があれば以下のような対処は必要かも知れません。

  • jQuery(上記のコード)を有効にするかどうかのスイッチを投稿ごとに判断する等適所に設ける
  • ブロックスタイルを作って、スムース開閉させるかどうかを切り替えにする(全体をラップする方法を変える)

ブロックエディター側には反映されない

前述したように、このコードはフロントエンドに出力したものを..という条件付きのコードですので、投稿編集画面(ブロックエディター側)には反映されません。

100%エディターとフロントの親和性を求めるのであれば、自身で工夫していただく必要があろうかと思いますが、恐らくどんなテーマを使っても100%整合性を保つというのは難しいと思いますので、仕様としてとらえてもいいのではないかと個人的には思います。

ついでに△マークを変更する方法も

「▼」「▲」マークを変更する方法

本ページの主旨とは全く関係ありませんが、本当についでとしてボタン先頭に出る「▼」マークの変更方法をメモとして公開しておきます。

以下のようにすると、after要素(開閉文字列の後ろ)に「【▽ クリックして開く】」「【△ クリックして閉じる】」と表示させるよう変更できます。

「content」要素をサイトのCSSコード上で編集をすると、うまく適用されないことがあるので、デベロッパーツール上で変更して貼り付けるようにすると文字変更もうまくいくことが多いですヨ

details>summary {
  list-style-type: none;
  outline: none;
  cursor: pointer;
}

details>summary::-webkit-details-marker {
  display: none;
}

details>summary::after {
    content: ' 【▽ クリックして開く】';
}

details[open]>summary::after {
    content: ' 【△ クリックして閉じる】';
}

details[open]>summary {
  margin-bottom: 0.5rem;
}

本サイトで行っているdetailsタグ(ブロック)へのカスタマイズ内容

マークの変更までを紹介しましたので、最後に本サイトで現在detailsブロックへ行っているカスタマイズ内容を公開しておきます。

  • 開閉の機構自体は本ページのjQueryでスムーズに開閉するようにしています
  • 以下のように変更するスタイルコードを追加しています
    • マークの変更(独自アイコンで表示)
    • 基本となる余白の設定(タイトル12px、内容4pxの余白)
    • 開いたコンテンツはブロックの設定に関係なく白(サイトの背景色)にする

以下が追加しているスタイルコードです。

summary.pwcn-accordion__title {
	padding: 12px;
}

.pwcn-accordion__content {
	padding: 4px;
	background:#fff;
	margin-top:0;
}

details>summary {
	list-style-type: none;
	outline: none;
	cursor: pointer;
}

details>summary::-webkit-details-marker {
	display: none;
}

details>summary::before {
	content: '\eabe';
	font-family: 'hauicon';
	font-size: 1.5rem;
	vertical-align: sub;
	margin-right: 4px;
}

details[open]>summary::before {
	content: '\eabc';
	font-family: 'hauicon';
	font-size: 1.5rem;
	vertical-align: sub;
	margin-right: 4px;
}
Lolipop ServerMoshimo Ad x-serverMoshimo Ad

WordPress Customize Ideas | Personal WP Customization Notes (PWCN)
メディアライブラリのグリッド表示で、「さらに読み込む」機能を無効にして以前の無限スクロールへ戻す方法