details、summaryタグ+jQueryでスムーズに開閉するアコーディオンの実装
以前の記事で、detailsとsummaryタグを使ったアコーディオン(開閉)の作り方を紹介しました。
その際に、htmlとcssだけではアニメーションの処理が不完全だった為、jQueryを追加してスムーズに開閉するアコーディオンをご紹介します。
※jQueryが効かない環境でも、details と summary の元々の開閉機能が動作する仕様となっています。
html
1 2 3 4 5 6 7 8 |
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <details class="toggle-box"> <summary class="toggle-header">Question</summary> <div class="toggle-content"> <p>Answer テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。</p> <p>テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。</p> </div> </details> |
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 52 53 54 55 56 57 58 59 60 61 62 63 64 |
.toggle-header { display: flex; /* display: list-item; 以外を指定してデフォルトの三角形アイコンを消す */ align-items: center; position: relative; padding: 1em 2em 1em 3em; background-color: #F7EBDF; cursor: pointer; } /* WebKitブラウザのデフォルトの三角形アイコンを消す */ .toggle-header::-webkit-details-marker { display: none; } /* 開閉アイコン */ .toggle-header::after { position: absolute; top: 50%; right: 15px; width: 10px; height: 10px; margin-left: 10px; border-right: 2px solid #DF4632; border-bottom: 2px solid #DF4632; transform: translateY(-50%) rotate(45deg); transition: transform .5s; content: ''; } .toggle-box[open] summary::after { transform: translateY(-50%) rotate(225deg); } /* 詳細 */ .toggle-content { position: relative; transform: translateY(-10px); margin: 0; padding: .3em 3em 1.5em; background-color: #F5F5F5; opacity: 0; transition: transform .5s, opacity .5s; } .toggle-box[open] .toggle-content { transform: none; opacity: 1; } /* Q、Aの文字を表示する場合に指定 */ .toggle-header::before , .toggle-content::before { position: absolute; left: 1em; font-weight: 600; font-size: 1.3em; line-height: 1.2; } .toggle-header::before { color: #75bbff; content: "Q"; } .toggle-content::before { top: 1.3rem; color: #ff8d8d; content: "A"; } |
CSSの補足説明
●初期状態
- ・summary(.toggle-header(質問部分))に、 display: list-item; 以外を指定してデフォルトの三角形アイコンを消します。
- ・.toggle-content(回答部分)は opacity: 0 を指定し、初期状態では非表示にします。
- ・transform: translateY(-10px) により、少し上にずれた状態で待機します。
●開いたときのアニメーション
- ・details 要素(.toggle-box)に open属性が付与されると、その中の .toggle-content が opacity: 1 になり、表示されます。
- ・transform も none に戻るため、上からスライドしてくるような視覚効果になります。
- ・transition: transform .5s, opacity .5s; により、opacity と transform の変化が 0.5秒かけてアニメーションします。
jQuery
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
$(document).ready(function() { $(".toggle-header").on("click", function(event) { event.preventDefault(); // デフォルトの開閉を防ぐ let $details = $(this).parent(".toggle-box"); let $content = $details.children(".toggle-content"); if ($details.attr("open")) { // 閉じる処理 $content.slideUp(300, function() { $details.removeAttr("open"); // アニメーション完了後に open を削除 }); } else { // 開く処理 $details.attr("open", true); $content.hide().slideDown(300); } }); }); |
jQuery 側の役割
- ・summary(.toggle-header(質問部分))をクリックすると、デフォルトの <details>/<summary> の開閉動作を event.preventDefault() で無効化し、独自の開閉処理を行います。
- ・open 属性の有無によって現在の状態を判定しています。
- ・閉じる場合は .toggle-content を slideUp(300) し、アニメーション完了後に open 属性を削除します。
- ・開く場合は open 属性を追加したうえで、.toggle-content を slideDown(300) で表示します。
- ・この open 属性の追加・削除によって、CSS のアニメーションが開始・終了する仕組みになっています。
DEMO
See the Pen
details、summaryタグ+jQueryでスムーズに開閉するアコーディオンの実装 by mkl may (@mkl-may)
on CodePen.