アコーディオンが上手く動作しない…
何が原因なんだろうか?
よくあるのはこれから紹介する3パターンだね
私は今まで100人を超えるコーダーの質問に応じてきましたが
「アコーディオンの動作不良」に関する質問を多く受けることがありました。
多くのアコーディオン動作不良に立ち会う中で
「またこれか」と感じたよくある事例をご紹介します。
transiton:all 1s;が邪魔している
アコーディオンを作成する際の思考回路として
アコーディオンの仕組み自体は完成した→次は動きをつけよう→よしtransition:all 1s;だな
という考えを持ってしまう人が多い印象です。
しかし、アコーディオンの動作はJavaScript側で制御することがほとんどのため
CSS側で制御してしまうと競合して動作不良となります。
以下に例を示します。
See the Pen Untitled by りょーすけ (@s_ryosuke_1242) on CodePen.
緑のクエスチョン部分をクリックした際に
アンサー部分の動きが滑らかでないのが分かると思います。
transition:all 1s;を削除すればOK
クラス名.faqAccordion__contentに付与された
transition:all 1s;を削除するだけで解決できるはずです
じゃあ、なぜ削除しても滑らかに動くの?
これはjQueryの.slideToggle()メソッドに秘密が隠れてます。
上の例にて、.slideToggle()の括弧の部分が空白になってますが、
通常はここに秒数を指定します。
空白の場合はデフォルトで0.4秒が適用されるため最初から滑らかに動くようになっています。
// デフォルトの0.4秒でアンサー部分を開閉してね
$(this).next('.faqAccordion__content').slideToggle();
よく質問でいただくアコーディオンの動作不良については
transition:all;の削除でほとんどが解決されます。
このあと紹介するパターンは少しニッチなものとなります。
開閉部分にmarginを適用している
次にご紹介するのも開閉時に動きが不自然になってしまっています。
See the Pen accordion malfunction 2 by りょーすけ (@s_ryosuke_1242) on CodePen.
特にアンサー部分が開き終わるタイミングでカクついているのが分かると思います。
アコーディオンの機能を作成しているのは先程と違い
jQueryではなく素のJS(Vanilla JS)を使用しています。
さて、どのように解決しましょうか。解決方法は2つあります。
marginではなくpaddingを使用する
意外と解決方法は簡単です。
コンテンツ部分に使用している余白を作るためのプロパティmarginをpaddingに変更するだけで解消されます。
なぜmarginはダメなの?
marginは外側の余白を制御するものであり、アニメーションが発火した際に周囲の要素のレイアウトも再計算される必要があります。
この再計算(リフロー)は比較的負荷がかかる処理のため動きがカクついてしまうと考えられます。
overflow:hidden;を追加
コンテンツが開閉される部分にoverflow:hidden;を追加することで解消されます。
oveflow:hidden;で改善できる理由
・要素の外側にはみ出たコンテンツが非表示になるため再計算(リフロー)が必要な範囲が制限される
→描画効率が上がる期待も
上記の方法を試しても改善できない場合は次の対策法をご覧ください。
他のセクションでfilterプロパティを多用している
これに関してはCodePenで再現するのが出来なかったので実例を見せるのは難しいですが、(すみません…)
カードがいくつも並ぶようなセクションで
カードに対してfilter:drop-shadow();を使用すると
アコーディオンにも影響を及ぼし、
動きが不自然になってしまう事例が確認されました。
box-shadow();でデザインを再現できるはずの箇所に対して
安易にfilterプロパティを使用してしまっていないか確認してみてください。
まとめ
よくあるアコーディオンの不具合の事例と解決策について3パターンご紹介しました。
アニメーション関連での不具合は再計算(リフロー)や描画効率に着目して探していると原因が見つかったりします。
今回ご紹介した事例の中に不具合を紐解くきっかけとなるものがあれば幸いです。