CSSだけでアコーディオンを作る方法(レスポンシブ&矢印付)

アコーディオン

今回はjQueryを使わずに、CSSだけでアコーディオンをサクッと実装する方法を紹介します。どれもレスポンシブ対応です。なお、後半では矢印アイコン付きのものも載せています。コピペして使って頂いてOKです。

アコーディオンメニューのサンプル

このような、クリックしたら中身が表示される縦のアコーディオンになります。表示させる中身はリストでも、文章でも何でもOKです。

CSSだけでアコーディオンを作る仕組み

はじめに仕組みをざっくりと解説しておきます。チェックボックスのinputタグとCSSのセレクタをうまく組み合わせて実装します。

ラベルは非表示にしておく

まず「inputタグ(とラベル)」と「クリックしたら表示させる中身の要素」を並べます。後者ははじめは非表示にしておきます。

チェックが入るとラベルの中身を表示

チェックが入ると、非表示になっていた要素を表示させるようにします。

直後の要素のスタイルを決めるCSSセレクタを活用

CSSだけでアコーディオンを実現させるために、セレクタ+を活用します。

+ △ {スタイル指定} ◯の直後にある△にのみスタイル指定が適用される

「+」で区切ることで、同じ階層のすぐ隣(後ろ)の要素にのみCSSが適用される、というものです。セレクタについては、こちらの記事で詳しく解説しています。

ラベルにチェックが入る

今回の場合「inputタグ」の直後に「中身をのせるdivタグ」を並べます。divタグははじめ非表示にしておきます。

チェックが入った直後のdivタグを表示させる

セレクタ+を使って中身を表示

そして、チェックが入ったinputタグ(input:checked)の、すぐ後ろのdivタグを表示させるようにする、というわけですね。

一旦まとめ

CSSのアコーディオンはinputタグのチェックと連動。チェックの入ったinputの直後の要素の中身を表示させる

アコーディオンのHTML&CSS例

では実装するためのサンプルCSSを紹介します。

See the Pen アコーディオンメニュー by saruwakakun (@saruwakakun) on CodePen.

HTML
<div class="accbox">
  <!--ラベル1-->
    <label for="label1">クリックして表示1</label>
    <input type="checkbox" id="label1" class="cssacc" />
    <div class="accshow">
      <!--ここに隠す中身-->
      <p>
        こんにちは1
      </p>
    </div>
    <!--//ラベル1-->
  <!--ラベル2-->
    <label for="label2">クリックして表示2</label>
    <input type="checkbox" id="label2" class="cssacc" />
    <div class="accshow">
      <!--ここに隠す中身-->
      <p>
        こんにちは2
      </p>
    </div>
    <!--//ラベル2-->
  <!--ラベル3-->
    <label for="label3">クリックして表示3</label>
    <input type="checkbox" id="label3" class="cssacc" />
    <div class="accshow">
      <!--ここに隠す中身-->
      <p>
        こんにちは3
      </p>
    </div>
    <!--//ラベル3-->
  <!--ラベル4-->
    <label for="label4">クリックして表示4</label>
    <input type="checkbox" id="label4" class="cssacc" />
    <div class="accshow">
      <!--ここに隠す中身-->
      <p>
        こんにちは4
      </p>
    </div>
    <!--//ラベル4-->
</div><!--//.accbox-->
CSS
/*ボックス全体*/
.accbox {
    margin: 2em 0;
    padding: 0;
    max-width: 400px;/*最大幅*/
}

/*ラベル*/
.accbox label {
    display: block;
    margin: 1.5px 0;
    padding : 11px 12px;
    color :#2f8fcf;
    font-weight: bold;
    background :#a4cbf3;
    cursor :pointer;
    transition: all 0.5s;
}

/*ラベルホバー時*/
.accbox label:hover {
    background :#85baef;
}

/*チェックは隠す*/
.accbox input {
    display: none;
}

/*中身を非表示にしておく*/
.accbox .accshow {
    height: 0;
    padding: 0;
    overflow: hidden;
    opacity: 0;
    transition: 0.8s;
}

/*クリックで中身表示*/
.cssacc:checked + .accshow {
    height: auto;
    padding: 5px;
    background: #eaeaea;
    opacity: 1;
}

HTMLの解説

まず、この例では4段のアコーディオンメニューを作っています。それぞれのラベルをクリックすると、中身が表示されるという具合です。

隠しておく中身はdivタグの中に

隠しておく中身は<div class="accshow">~</div>の中に入れます。中には何をいれても構いません(pタグで文章を入れても、リストを入れてもOKです)。

メニュー数を増やすには

メニュー数(ラベル数)を5個以上に増やしたいときには、コメントアウトの<--ラベル◯--><--//ラベル◯-->のカタマリを、好きな数だけ複製します。
その際、以下のようにinputタグのidを他と被らない新しいものにします(合わせて、labelタグのfor属性も変えましょう)。

<!--ラベル5--> <label for="label5">クリックして表示</label> <input type="checkbox" id="label5" class="cssacc" /> <div class="accshow"> <!--ここに隠す中身--> </div> <!--//ラベル5-->

上記の赤字の部分を合わせて変えればOKです。

CSSの解説

.accbox {max-width: 400px;}

この部分で、ボックス全体の最大幅を決めています。ここは使用用途に応じて変えて頂ければと思います。なお、小さい端末で見たときには、ボックスははみ出ないようにレスポンシブで縮みます。

.accbox label {~}

この部分でラベル1つ1つのデザインを変えています。 Adfadaとりあえず、青っぽいデザインにしていますが、好みで変えて頂ければと思います。

.accbox input {display: none;}

チェックボックスが見えていると台無しなので非表示にしています。

.accbox .accshow { height: 0;/*高さを0に*/ padding: 0;/*余白を0に*/ overflow: hidden;/*非表示に*/ opacity: 0;/*中身を透明に*/ transition: 0.8s;/*クリック時の動きを滑らかに*/ }

中身を隠しておくためのCSSです。「なぜdisplay:noneで非表示にしないのか」と思われるかもしれませんが、このように指定することで表示させたときの動きが滑らかで、アコーディオンメニューらしくなるのです。

.cssacc:checked + .accshow { height: auto; padding: 5px; background: #eaeaea; opacity: 1; }

クリックでheight0からautoに変えて、中身を表示させています。 background: #eaeaea;はただの背景色なので、好みで変えて頂ければと思います。

応用例:矢印を表示&切替

最後に、上のサンプルコードを使った使用例を紹介しておきます。

ラベルに矢印アイコンを表示させ、クリックするとアイコンが切り替わるようになっています。このアコーディオンメニューのHTMLとCSSは以下のようになります。

HTML
<div class="accbox">
  <!--ラベル1-->
    <input type="checkbox" id="label1" class="cssacc" />
    <label for="label1">HTML&CSS</label>
    <div class="accshow">
      <!--ここに隠す中身-->
    </div>
    <!--//ラベル1-->
  <!--ラベル2-->
    <input type="checkbox" id="label2" class="cssacc" />
    <label for="label2">Photoshop</label>
    <div class="accshow">
      <!--ここに隠す中身-->
    </div>
    <!--//ラベル2-->
  <!--ラベル3-->
    <input type="checkbox" id="label3" class="cssacc" />
    <label for="label3">WordPress</label>
    <div class="accshow">
      <!--ここに隠す中身-->
    </div>
    <!--//ラベル3-->
  <!--ラベル4-->
    <input type="checkbox" id="label4" class="cssacc" />
    <label for="label4">Material Design</label>
    <div class="accshow">
      <!--ここに隠す中身-->
    </div>
    <!--//ラベル4-->  
  <!--ラベル5-->
    <input type="checkbox" id="label5" class="cssacc" />
    <label for="label5">Design Tips</label>
    <div class="accshow">
      <!--ここに隠す中身-->
    </div>
    <!--//ラベル5-->
</div><!--//.accbox-->
CSS
/*ボックス全体*/
.accbox {
    margin: 2em 0;
    padding: 0;
    max-width: 400px;/*最大幅*/
}

/*ラベル*/
.accbox label {
    display: block;
    margin: 1.5px 0;
    padding : 13px 12px;
    color: #ffba47;
    font-weight: bold;
    background: #fff2cc;
    cursor :pointer;
    transition: all 0.5s;
}

/*アイコンを表示*/
.accbox label:before {
    content: '\f054';
    font-family: 'FontAwesome';
    padding-right: 8px;
}

/*ラベルホバー時*/
.accbox label:hover {
    background :#ffe9a9;
}

/*チェックは隠す*/
.accbox input {
    display: none;
}

/*中身を非表示にしておく*/
.accbox .accshow {
    height: 0;
    padding: 0;
    overflow: hidden;
    opacity: 0;
    transition: 0.8s;
}

/*クリックで中身表示*/
.cssacc:checked + label + .accshow {
    height: auto;
    padding: 5px;
    background: #fff5eb;
    opacity: 1;
}

.accbox .accshow p {
    margin: 15px 10px}

/*アイコンを入れ替える*/
.cssacc:checked + label:before {
    content: '\f078';
}

以下の解説をまとめておきます。

解説:矢印アイコンについて

アイコンにはFontAwesomeを使っています。導入方法や、CSSの疑似要素でアイコンを表示させる方法はこちらの記事でまとめています。

はじめはを表示させ、クリックによりへと切り替えています。

疑似要素で表示

矢印アイコンは疑似要素:beforeで表示させています。「疑似要素って何?」という方はこちらの記事をどうぞ。

クリックでアイコンの切替

.cssacc:checked + label:before { content: '\f078';/*切替後のアイコン*/ }

なお、アイコンをクリックしたときに切り替えるために、HTMLでのinputタグとlabelタグの順番を入れ替えています(inputの後にlabelを配置)。それによりinput:checked直後のlabelのアイコンを切り替えています。

解説:中身を表示させるスタイル指定のセレクタも変更

inputlabelが入れ替わったため、inputの直後がdivタグでは無くなってしまいました。input⇒label⇒divという順番になってしまったわけですね。このままだとinput:checkedとなってもdivの中身が表示されません。

.cssacc:checked + label + .accshow {~}

そのため、「チェックの入ったinput」の直後の「label」のさらに直後の「divタグ(.accshow)」というようにセレクタを変えています。inputのチェック有無と、divタグの表示を間接的に結びつけているわけですね。

サルワカくんの顔(通常)
サルワカくん

ちょっと分かりづらいですね…。とりあえずアイコンを使いたいときには、上のコードをコピペして使って頂ければ良いかと思います。

サルワカ