[CSS] 水平・垂直に動くレスポンシブなアコーディオンを簡単に作る

先日の[CSS] レスポンシブなモーダルウィンドウを簡単に作ると同じ類になりますが今回はアコーディオンを実装してみたいと思います。先述のとき同様にクリックイベントでHTMLにClassセレクタを付与するのみをJavaScript の仕事とし表現はCSS に任せ”仕掛けと表現のすみわけ” を前提としたいと思います。

また少しこった点としてPCビューのときはアコーディオンを横方向(水平)に並べ、SPビューのときはアコーディオンを縦方向(垂直)に並べ各デバイスによって表現を変えてみたいと思います。横方向(水平)でアコーディオンを柔軟に実現する考えの1つとしてJavaScript でブラウザの横幅を測り子要素の数とで四則演算し云々みたいな技法がありますが表現部分をCSS に任せることでこの辺の煩わしさを回避できるかと思います。

仕様は以下としてみます。

  • レスポンシブ対応
  • アコーディオンの子要素をクリックしたら該当要素が開く
  • PCビューのときはアコーディオンの子要素が横方向(水平)
  • SPビューのときはアコーディオンの子要素が縦方向(垂直)

HTML はアコーディオンを構成するための親(.panels)と子(.panel)からなる<div>要素になります。

<div class="panels">
    <div class="panel expand">
        <p>ここにコンテンツが入ります。</p>
    </div>
    <div class="panel">
        <p>ここにコンテンツが入ります。</p>
    </div>
    <div class="panel">
        <p>ここにコンテンツが入ります。</p>
    </div>
</div>

JavaScript はアコーディオンの子要素(.panel)をクリックしたら .expand を付与するトリガーの役割のみになります。その際に既に子要素(.panel)に .expand が付与されている場合は除去し初期化しています。

$(document).ready(function() {
    $(".panel").on("click", function(e) {
        e.preventDefault();
        $(".panel").removeClass("expand");
        $(this).addClass("expand");
    });
});

あとはCSS で .expand のある/なしで子要素の開閉を実現しています。肝はPCビューのときはCSSのflexボックスを使って子要素を均等な横幅でかつ横方向(水平)に配置し .expand が付与されると該当の子要素のみflexボックスの定義を打ち消すことでアコーディオンを表現しています。またSPビューのときはCSS のブレイクポイントをきっかけにflexボックス自体を打ち消し縦方向(垂直)にアコーディオンを表現しています。

.panels {
    display: flex;
    width: 100%;
    box-sizing: border-box;
}
.panels > .panel {
    flex-basis: 0;
    flex-grow: 1;
    max-width: 70%;
    box-sizing: border-box;
    overflow: hidden;
    -webkit-transition: .3s ease-out;
    transition: .3s ease-out;
    cursor: pointer;
}
.panels .row {
    display: flex;
    width: 100%;
    min-width: 600px;
    box-sizing: border-box;
}
.panels > .panel.expand {
    flex-basis: auto !important;
    flex-grow: 0 !important;
}
@media only screen and (max-width: 479px) {
    .panels {
        display: block;
    }
    .panels > .panel {
        flex-basis: auto;
        flex-grow: 0;
        max-width: 100%;
    }
    .panels .row {
        display: block;
        min-width: 0;
    }
}

  実際のデモはこちら

ブラウザを横幅に縮めたり広げたりしたときに横方向(水平)のアコーディオンと縦方向(垂直)のアコーディオンを体現できているかと思います。ここにCSS アニメーションも付け加えるとよりリッチな表現ができそうですが自分は面倒なのでやめておきます。

CSS がしっかりしてきたのでどんな表現ができるかを考え試してみるのが面白くなってきたと感じる今日このごろです。

  • 2018.07.13
  • お仕事っぽいこと