お疲れ様です。ウェブドアのカワヰです。
今回は、「アコーディオンメニュー」の実装についてをガチで考察してみようと思います。

初心者の方にとっては少し難しく感じるであろうアコーディオン。
HTMLやCSSの勉強を始めた方にとっては、覚えることが多くて「何のこっちゃ?」って思いながら記述してることでしょう。

かくいうカワヰも、勉強を始めた頃は何が何やら意味不明でした。

  • 隣接要素って何?
  • いや、クリックしても解答欄普通に消えへんやん
  • クリックの反応しやんのだがw

といった感じで悩みながら記述していたことを覚えています。(今もちょこちょこ悩んでます笑)

学習初期のカワヰと同じように、悩んでる方も多いはず…。
ということで、アコーディオンメニューを3パターン作成し、それぞれのメリットやデメリットを思いつくだけ書いていきます。

実際にフロントエンドエンジニア歴を4年積ませてもらっているので、案件ベースでお話しができるかと思います。
それでは、いってみよ~。

アコーディオンメニューの実装とメリット・デメリット

今回のアコーディオンメニューですが、

  • 「HTML + CSS」のパターン2つ
  • 「HTML + CSS + JavaScript(Vanilla)」の1つ

をご紹介していきます。

inputタグとlabelタグで作るアコーディオンメニュー

一番ポピュラーで汎用性が高いであろう実装がこの、inputタグとlabelタグを使う方法。
まずはソースコードを見ていきましょう。

See the Pen Untitled by Takao Kawai (@codeQuina) on CodePen.

チェックボックスにチェックした状態だった時は兄弟要素の「content」を開けて、チェックしてない状態は兄弟要素の「content」を閉じる

という感じです。
これだけで説明が終わる…とでも思っていたのか?

実はこのコード、かなりレアなケースです。
JavaScriptが使えない&PCはアコーディオンなし、タブレット以下でアコーディオンメニューを作成&フワッとしたトランジションをつける時に記述したものです。

これを基に、inputタグとlabelタグ版のメリット・デメリットを考察しましょう。

inputタグとlabelタグ版のメリット

まず初めに、inputタグとlabelタグの実装がおそらく一番汎用性が高いように思います。
先ほどのケースみたいな場合でも唯一、このパターンでの実装だと上手くハマってくれました。

detailsとsummaryでも頑張ってみようと思ったのですが、どうしてもPCでアコーディオンを表示させないということが難しかったです。

次に、CSSやScssを記述した際に理解が深まりやすいというのはあるかと思います。
まぁどのパターンも勉強にはなりますが、inputやlabel等の挙動がどうなるとか、兄弟要素に当てる方法とか、チェックがついた時にどうするとか…。

結構この辺り、お問い合わせフォームとかでゴリゴリ記述する場面があります。
その時に「そういやアコーディオンでも似たようなことしたな…」ってなるのとならないのでは、小さいですが積もると結構な差になります。

inputタグとlabelタグ版のデメリット

まず、CSS(Scss)が割と複雑になりやすいです。
兄弟要素やcheckedセレクタ、inputやlabelをどうするか等々…。
慣れていればなんてことはないですが、初学者からすると意味不明なままとりあえずコピペしとこ…ってなりがち。

さらに複雑なコードは冗長さや不要なコードを産んでしまう要因にもなります。
CSS(Scss)の勉強になる分、その辺りは気にしておきたいところです。

また、汎用性は高いですが細かいデザイン性には制限がでます
例えば、チェック後、コンテンツが下にスライドしているときに、謎の余白が出たり、チェックを外してコンテンツが上に行ってる時、スライドに合わせて文字がいきなり消えたり…等々。

コーディング担当でない方が気になるレベルではないものかも知れませんが、こうした細かいデザイン性にはどうしても制限がでてしまいます。

detailsタグとsummaryタグで作るアコーディオンメニュー

最近登場し、一躍ルーキーになった実装。タグもCSSも少ない記述であっという間にアコーディオンメニューが作成できます。
ひとまずソースコードを見てみましょう。

See the Pen accordion ( details + summary ) by Takao Kawai (@codeQuina) on CodePen.

実案件のソースコードを基に、即席で改変してみました。
detailsとsummaryで実装してみたメリット、デメリットを確認してみましょう。

detailsタグとsummaryタグ版のメリット

やってみて思ったのは、圧倒的に記述が少なくて済むことです。
兄弟要素やcheckedの指定は不要、HTMLタグをそのままCSSで調整するだけで、それなりのアコーディオンメニューを作成できました。

記述が少ない分、冗長さや意図しない不要なコードを記述することも少なくなります
時短にもつながりますので、使いどころはありそうです。

また、detailsタグとsummaryタグはHTML5のネイティブ機能として設計されています。
スクリーンリーダーはsummaryタグを見出しとして認識し、detailsが展開可能なコンテンツであることをユーザーに通知します。

開閉状態(開いているか閉じているか)は自動的にaria-expandedに相当する形で解釈されるため、明示的なaria-*属性を追加する必要がありません。
構造的に考えると、detailsタグとsummaryタグはセマンティックなコードだと言えます。

detailsタグとsummaryタグ版のデメリット

まず、CSSだけでトランジションを付けたアニメーションを実装することは現段階でかなり難しいといえます。
クリックをすると、detailsタグにopen属性が付与されるのですが、これを基にtransition等を設定しても、開閉は上手く動作しません。

summaryでは上手くアニメーションが動作しましたが、もう一歩感があります。
JSを使えばこれらの調整はできると思いますが、CSSのみでフワッとした開閉アコーディオンを実装することは、難しいでしょう。

そして、IEなどの古いブラウザの対応もしていません
もはやIEを使っているサイトなど皆無かもしれませんが、古いブラウザを使用している案件等は気を付けるべきです。

最後に、inputタグとlabelタグ版のようにスマホ、PCでレイアウトが変わる場合の実装にも向きません
detailsタグとsummaryタグを使用した時点で、開閉のアクションも自動的についてきます。そしてこの実装は、CSSだけで変更することは現状不可能。

少ないケースかも知れませんが、レイアウトがガラッと変わる系の案件では注意する必要がありそうです。

JavaScriptを使って作るアコーディオンメニュー

CSSにできない超細かいところまでをイイ感じに再現してくれるのがJavaScriptを使っての実装。
早速ソースコードをみてみましょう。

See the Pen accordion ( JavaScript ) by Takao Kawai (@codeQuina) on CodePen.

JavaScriptを使った実装のメリット

何といっても、自分のやりたいことができることです。
フワッとしたり、クリック後に変な余白なく出てきてくれたり、消すときにもフワッと消したり…

CSSだけの実装でも随分と解消されていることが多いです。
しかし、「ここもうちょいこうしたい…」という職人技はJavaScriptを使う方がうまく行くことも往々にしてあります。

痒い所に手が届くJavaScript、マスターしておけば必ず役に立ちます。

状態管理も自由にできるので、「すべて閉じるを禁止する」や「最初の3つだけを表示させ、ボタンクリックで全てのアコーディオンメニューを表示させる」といった実装も行えます。

さらに、古いブラウザでも同じように開閉できるので、ユーザーの環境を選ばずに安定した動画を実装することができます。

JavaScriptを使った実装のデメリット

まずJavaScriptをある程度分かっていないと、何がどうなってるのかがわかりません
アコーディオンメニューに使用するJavaScriptはそれほど難しいものは使っていませんが、初心者の方はとっつきにくいコードになってるでしょう。

もちろんjQueryでもできますが、ライブラリに依存しますし、Vanillaよりも重くなります。

そしてjQueryに慣れすぎると、ReactやVueの習得に苦労すると思います(Vanillaに慣れてないからという個人的な主観…笑)。

また、HTML, CSS, JavaScriptの3言語を使ってますので、コード量は確実に増えます。複雑にすればするほどコード量が増えるので、意図しないエラーやバグを産みだす原因にもつながります。

さらに、JavaScriptが使えない案件の場合、全く思うような実装ができなくなります。この場合は、泣く泣くHTMLとCSSのみで実装する他ありません。

アコーディオンメニューって何?

終盤になりましたが、そもそもアコーディオンメニューって何?ということをお話しします。

アコーディオンメニューは、リスト形式のコンテンツをコンパクトにまとめ、必要に応じて一部のコンテンツを展開または折りたたむことができるUIコンポーネントの一種です。
展開時に表示される内容がアコーディオン(蛇腹式)のように開閉する動作からその名前がついています。

アコーディオンメニューの特徴

スペースを省ける

折りたたみが可能なため、ページ上のスペースを効率的に利用できます。特に情報量が多い場合でも、ユーザーに見やすいレイアウトを提供します。

ユーザー操作による動的な表示

ユーザーがクリックやタップなどの操作でコンテンツを開閉できるため、必要な情報だけを表示する仕組みが可能です。

整理された視覚構造

似た種類の情報をグループ化し、視覚的にわかりやすい構造を作るのに適しています。

主な利用シーン

FAQセクション

項目ごとに質問を並べ、回答を折りたたんでおくことで、ユーザーは知りたい質問だけを展開して確認できます。

ナビゲーションメニュー

サイドバーやモバイルメニューで、階層化された情報を整理して表示できます。サブメニューを展開/折りたたみ可能にすることで、使いやすさが向上します。

プロダクト情報や詳細説明

商品詳細やスペック、レビューなど、特定の情報をカテゴリごとに折りたたむことで、コンテンツの見通しを良くします。

様々なアコーディオンメニューを実装できるようになろう!

ということで、フロントエンドエンジニア歴4年のカワヰが、偉そうにアコーディオンメニューについてをガチで考察してみました。
カワヰ個人的には、JavaScriptを使って実装する方が色々な対応ができるので好みです。

次いでinputタグ + labelタグの実装。こちらもJavaScriptほどではないですが、CSSだけでもかなりできる幅が広いです。

detailタグとsummaryタグは、今のところ見送りという感じです…。超スピードで進める案件等があれば、使うかも知れません。
今後の動向に期待を膨らませておきます。

いずれにしても、HTMLやCSS, JavaScriptなどを駆使して、様々な実装に慣れておくべきだと改めて感じました。

ということで、最後までご覧いただきありがとうございました!
この記事が誰かの参考になれば幸いです。