CSSだけ!クリックでスムーズに開閉するアコーディオンメニュー
この前「CSSだけで作る動きのあるドロップダウンメニュー|Webpark」という記事を書きました。jQueryでしそうなことをCSSのみで作ったのですが、これはマウスを乗せたとき動くようにしたいのでhoverを使いました。
今回はクリックで開閉するということで、hoverは使えません。では何を使うのか。
ラジオボタンを使います。ある項目にチェックするとそれまでチェックされていた項目のチェックが外れる。アコーディオンメニューと仕組みが一緒です。
今回もサンプルを用意していますのでご覧ください。
IE8以下の場合「:checked」が非対応なのでうまく表示されません。しかし、CSS3セレクタはSelectivizrを使えば簡単に対応できます。使い方は「CSS3を使うにあたって知っておきたいIE対策のまとめ|Webpark」をご参考に。
それではHTMLから紹介します。
HTML
<div id="accordion"> <form> <label> <input type="radio" name="btn" checked /> <div> <div>カテゴリー1</div> <ul> <li><a href="#">サブカテゴリー1</a></li> <li><a href="#">サブカテゴリー2</a></li> <li><a href="#">サブカテゴリー3</a></li> </ul> </div> </label> <label> <input type="radio" name="btn" /> <div> <div>カテゴリー2</div> <ul> <li><a href="#">サブカテゴリー1</a></li> <li><a href="#">サブカテゴリー2</a></li> <li><a href="#">サブカテゴリー3</a></li> </ul> </div> </label> <label> <input type="radio" name="btn" /> <div> <div>カテゴリー3</div> <ul> <li><a href="#">サブカテゴリー1</a></li> <li><a href="#">サブカテゴリー2</a></li> <li><a href="#">サブカテゴリー3</a></li> </ul> </div> </label> <label> <input type="radio" name="btn" /> <div> <div>カテゴリー4</div> <ul> <li><a href="#">サブカテゴリー1</a></li> <li><a href="#">サブカテゴリー2</a></li> <li><a href="#">サブカテゴリー3</a></li> </ul> </div> </label> <label> <input type="radio" name="btn" /> <div> <div>カテゴリー5</div> <ul> <li><a href="#">サブカテゴリー1</a></li> <li><a href="#">サブカテゴリー2</a></li> <li><a href="#">サブカテゴリー3</a></li> </ul> </div> </label> </form> </div>
CSS
続いてCSSです。かなり長くなっています。先に全体を載せて、後で個別に解説します。
@font-face { font-family: 'Typicons'; src: url('fonts/typicons-regular-webfont.eot'); src: url('fonts/typicons-regular-webfont.eot?#iefix') format('embedded-opentype'), url('fonts/typicons-regular-webfont.woff') format('woff'), url('fonts/typicons-regular-webfont.ttf') format('truetype'), url('fonts/typicons-regular-webfont.svg#TypiconsRegular') format('svg'); font-weight: normal; font-style: normal; } #accordion{ position:relative; width: 500px; margin: 0 auto; padding: 0; border-top: 15px solid #1b4958; border-bottom: 15px solid #1b4958; border-radius: 3px; font-size: 16px; line-height: 1; } #accordion input{ position:absolute; height: 0; padding: 0; } #accordion div div{ position: relative; padding: 15px 10px 12px 40px; border-top: 1px solid #d4ebf2; border-bottom: 1px solid #86c5da; background: #add8e6; } #accordion label:first-child div div{ border-top: 0; } #accordion label:last-child div div{ border-bottom: 0; } #accordion div div:hover{ background: #a0d2e2; cursor: pointer; } #accordion div div:before{ position:absolute; top: 13px; left:10px; color: #2f7f99; font: 24px/100% 'Typicons'; content: "\0023"; } #accordion div div:after{ position:absolute; top: 15px; right:10px; color: #2f7f99; font: 20px 'Typicons'; content: "7"; -moz-transition: .3s; -webkit-transition: .3s; -o-transition: .3s; -ms-transition: .3s; transition: .3s; } #accordion input:checked + div div:after{ top: 12px; right: 15px; -moz-transform: rotate(90deg); -webkit-transform: rotate(90deg); -o-transform: rotate(90deg); -ms-transform: rotate(90deg); transform: rotate(90deg); } #accordion ul{ list-style: none; margin: 0; background: #e1f1f6; } #accordion ul li a{ display: block; overflow: hidden; height: 0; padding: 0px 70px; color: #333; text-decoration: none; -moz-transition: .3s; -webkit-transition: .3s; -o-transition: .3s; -ms-transition: .3s; transition: .3s; } #accordion ul li a:hover{ border-top-color: #c7e4ee; background: #d4ebf2; color: #1b4958; } #accordion input:checked + div ul li a{ position:relative; background: none; line-height: 1; height: 16px; padding: 13px 70px; border-top: 1px solid #fff; border-bottom: 1px solid #a0d2e2; } #accordion input:checked + div ul li a:before{ position: absolute; top: 16px; left: 45px; color: #2f7f99; font:16px/100% 'Typicons'; content: "x"; -moz-transition: .3s; -webkit-transition: .3s; -o-transition: .3s; -ms-transition: .3s; transition: .3s; } #accordion input:checked + div ul li:first-child a{ border-top: 0px; box-shadow: 0 7px 7px -7px rgba(0,0,0,.5) inset; } #accordion input:checked + div ul li:last-child a{ border-bottom: 1px solid #d4ebf2; } #accordion input:checked + div ul li a:hover{ background: #d4ebf2; border-top-color: #eef7fa; }
セレクタはどこか分かりやすいように省略さずに書いています。
Webフォントの読込み
@font-face { font-family: 'Typicons'; src: url('fonts/typicons-regular-webfont.eot'); src: url('fonts/typicons-regular-webfont.eot?#iefix') format('embedded-opentype'), url('fonts/typicons-regular-webfont.woff') format('woff'), url('fonts/typicons-regular-webfont.ttf') format('truetype'), url('fonts/typicons-regular-webfont.svg#TypiconsRegular') format('svg'); font-weight: normal; font-style: normal; }
アイコンにWebフォント使っていますので最初に読み込みます。Webフォントについては「IEでもWebフォントが使えることを知ったので勉強してみました|Webpark」をご参考に。
アコーディオン全体
#accordion{ position:relative; width: 500px; margin: 0 auto; padding: 0; border-top: 15px solid #1b4958; border-bottom: 15px solid #1b4958; border-radius: 3px; font-size: 16px; line-height: 1; }
これは特に問題ないですね。
ラジオボタン
#accordion input{ position:absolute; height: 0; padding: 0; }
ラジオボタンは表示されないようにします。表示はされませんがlabelで囲まれた部分をクリックするとチェックされたことになります。
親カテゴリー
#accordion div div{ position: relative; padding: 15px 10px 12px 40px; border-top: 1px solid #d4ebf2; border-bottom: 1px solid #86c5da; background: #add8e6; }
カテゴリー1~5の部分です。ボーダーを2本重なるようにしています。後で紹介する左右のアイコンの表示位置の基準となるため「position: relative;」を指定します。
親カテゴリーの最初と最後
#accordion label:first-child div div{ border-top: 0; } #accordion label:last-child div div{ border-bottom: 0; }
先ほど2本のボーダーを重ねましたが、必要のないカテゴリー1の上のボーダーとカテゴリー5の下のボーダーをなくします。
カテゴリー1~5(オンマウス)
#accordion div div:hover{ background: #a0d2e2; cursor: pointer; }
マウスを乗せたときに少しだけ色は濃くなります。この辺の色の使い方は0to255を使って決めています。使い方は「カラーツール「0to255」で色を決めてメニューを作ってみる|Webpark」をご参考に。
カテゴリー1~5の左右にあるアイコン
#accordion div div:before{ position:absolute; top: 13px; left:10px; color: #2f7f99; font: 24px/100% 'Typicons'; content: "\0023"; } #accordion div div:after{ position:absolute; top: 15px; right:10px; color: #2f7f99; font: 20px 'Typicons'; content: "7"; -moz-transition: .3s; -webkit-transition: .3s; -o-transition: .3s; -ms-transition: .3s; transition: .3s; }
擬似要素で左右にアイコンを表示します。右側のアイコンはアコーディオンが開く際に下を向きます。その変化に動きをつけるためにtransitionを使います。
開いたときの右側のアイコン
#accordion input:checked + div div:after{ top: 12px; right: 15px; -moz-transform: rotate(90deg); -webkit-transform: rotate(90deg); -o-transform: rotate(90deg); -ms-transform: rotate(90deg); transform: rotate(90deg); }
ラジオボタンにチェックが入っているときのカテゴリー1~5の右側のアイコンの設定です。90度傾いて矢印が下を向くようになります。
サブカテゴリー全体
#accordion ul{ list-style: none; margin: 0; background: #e1f1f6; }
ここからはサブカテゴリー内の設定になります。
サブカテゴリーのリンク
#accordion ul li a{ display: block; overflow: hidden; height: 0; padding: 0px 70px; color: #333; text-decoration: none; -moz-transition: .3s; -webkit-transition: .3s; -o-transition: .3s; -ms-transition: .3s; transition: .3s; }
普段は閉じていますので表示しないようにします。開くときに動きをつけるため「transition」を使います。
サブカテゴリーのリンク(チェック)
#accordion input:checked + div ul li a{ position:relative; background: none; line-height: 1; height: 16px; padding: 13px 70px; border-top: 1px solid #fff; border-bottom: 1px solid #a0d2e2; }
アコーディオンが開いているときに設定です。「input:checked + div」でチェックがされているinput要素の隣のdiv要素ということになります。
サブカテゴリーの最初と最後
#accordion input:checked + div ul li:first-child a{ border-top: 0; box-shadow: 0 7px 7px -7px rgba(0,0,0,.5) inset; } #accordion input:checked + div ul li:last-child a{ border-bottom: 0; }
親カテゴリーと同じように最初サブカテゴリーの上と最後のサブカテゴリーの下のボーダーを消します。また、最初のサブカテゴリーの上側にシャドウを付けています。
サブカテゴリー(オンマウス)
#accordion input:checked + div ul li a:hover{ background: #d4ebf2; border-top-color: #eef7fa; }
サブカテゴリーにマウスを乗せたときに背景を少し濃くします。
サブカテゴリーの左側のアイコン
#accordion input:checked + div ul li a:before{ position: absolute; top: 16px; left: 45px; color: #2f7f99; font:16px/100% 'Typicons'; content: "x"; -moz-transition: .3s; -webkit-transition: .3s; -o-transition: .3s; -ms-transition: .3s; transition: .3s; }
擬似要素を使って右側にアイコンを表示します。
さいごに
ということでCSSだけで作ったアコーディオンメニューを紹介しました。
ただ、今回のような使い方が正しい使い方かどうかは分かりません。しかし、ラジオボタンを使う以外にCSSだけでクリックするタイプのアコーディオンメニューを作る方法が思い付きませんでした。
ラジオボタンがありならタブメニューなんかも簡単に作れそうです。
強引な気もしますが、こんな方法もあるのかと思っていただければうれしいです。

羨ましいですよ。WebParkさんのそのCSSとHtmlそしてJQueryの応用力!!!
毎日、私も勉強していますけど、WebParkさんほどできないんですね。
次の御記事楽しみに待ちます。
あ〜すみませんが、ひょっとして”WordPress”のことご存知ですか。いろいろ
調べていますけど、ここ韓国では互換性問題とかIEのActive-Xのため機能上
も問題があって外国のように活発ではないそうですけど、よいProgramだと
思います。必ず学びたいんです。日本語の”〜させてもらう”とか”〜してもらう”
とかの表現が韓国語にはない故、私の日本語がおかしいかもしれません。
まあ〜よくなると思います。では。。byebye~