details、summaryタグ+jQueryでスムーズに開閉するアコーディオンの実装
以前の記事で、detailsとsummaryタグを使ったアコーディオン(開閉)の作り方を紹介しました。
その際に、htmlとcssだけではアニメーションの処理が不完全だった為、jQueryを追加してスムーズに開閉するアコーディオンをご紹介します。
※jQueryが効かない環境でも、details と summary の元々の開閉機能が動作する仕様となっています。
html
1 2 3 4 5 |
<details> <summary>Question</summary> <p class="content">Answer</p> </details> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> |
css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
summary { display: block; /* デフォルトの三角アイコンを消す */ cursor: pointer; position: relative; background-color: #F7EBDF; padding: 10px 20px; padding-right: 40px; } /* WebKitブラウザのデフォルトの三角形アイコンを消す */ summary::-webkit-details-marker { display: none; } /* 詳細 */ .content { cursor: pointer; padding: 15px 20px; background-color: #F5F5F5; } /* カスタムアイコン */ summary::before { content: ""; position: absolute; top: 50%; right: 15px; width: 10px; height: 10px; border-right: 2px solid #DF4632; border-bottom: 2px solid #DF4632; transform: translateY(-50%) rotate(45deg); transition: transform 0.75s; } /* アイコン切り替え */ details[open] summary::before { transform: translateY(-50%) rotate(225deg); } .content { visibility: hidden; /* 初期状態で非表示、DOM上では存在 */ opacity: 0; /* 初期状態で透明 */ } /* アニメーションのスタイル */ details[open] .content { visibility: visible; opacity: 1; /* 開いたときに透明度を戻す */ transition: opacity 0.3s ease, visibility 0s linear 0.3s; /* アニメーション */ } |
●初期状態
・.content クラスの要素(回答部分)は、visibility: hidden と opacity: 0 で初期状態では隠れています。
表示されていないものの、HTML構造上には存在しています。
●開いたときのアニメーション
・details 要素が open 属性を持つと、その中の .content 要素は visibility: visible と opacity: 1 に変更され、徐々に表示されます。
・transition: opacity 0.3s ease, visibility 0s linear 0.3s; によって、opacity が0から1に変わるアニメーションが 0.3秒 でスムーズに実行されます。
また、visibility の変更は、opacity が完了した後に遅れて行われます。
jQuery
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<script> $(document).ready(function() { $("summary").on("click", function(event) { event.preventDefault(); // デフォルトの開閉を防ぐ let $details = $(this).parent("details"); let $content = $details.children(".content"); if ($details.attr("open")) { // 閉じる処理 $content.slideUp(300, function() { $details.removeAttr("open"); // アニメーション完了後に `open` を削除 }); } else { // 開く処理 $details.attr("open", true); $content.hide().slideDown(300); } }); }); </script> |
・jQuery側では、open 属性の追加と削除によって、CSSアニメーションの開始と終了を管理しています。
DEMO
See the Pen
details、summaryタグ+jQueryでスムーズに開閉するアコーディオンの実装 by mkl may (@mkl-may)
on CodePen.