【レスポンシブ】CSSだけで作る!ウィンドウサイズで切り替わる タブ・アコーディオン

CSSだけで作るEasy-Responsive-Tabs-to-Accordion

jQueryのプラグイン、「Easy-Responsive-Tabs-to-Accordion」をご存知ですか?
ウィンドウサイズでタブとアコーディオンを切り替えてくれる便利なプラグインなのですが、今回はこれをJSを使わずにCSSだけで作ってみました。

まずはデモをお試しください。
大きい画面でのご確認はこちらから。
http://codepen.io/leo-trym/full/jVqqdX/

See the Pen Responsive-Tabs-to-Accordion-Pyua-CSS by leo (@leo-trym) on CodePen.

ソース

HTML

HTMLはラジオボタンを使用します。
初めは :target で作ってみたのですが、
その位置までスクロールしてしまうため不採用になりました。

初期表示のため最初のラジオボタンは checked を付けています。

<div class="ly_rta">
 
  <article class="bl_box">
    <label for="rta01" class="el_heading01">title1</label>
    <input id="rta01" class="el_radio" type="radio" name="rta" value="1" checked>
    <div class="bl_content01" title="title1">
      <div class="bl_inner">
        <p>Li Europan lingues es membres del sam familie. Lor separat existentie es un myth. Por scientie, musica, sport etc, litot Europa usa li sam vocabular. Li lingues differe solmen in li grammatica, li pronunciation e li plu commun vocabules. Omnicos directe al desirabilite de un nov lingua franca: On refusa continuar payar custosi traductores. At solmen va esser necessi far uniform grammatica, pronunciation e plu sommun paroles. Ma quande lingues coalesce, li grammatica del resultant lingue es plu simplic e regulari quam ti del coalescent lingues. Li nov lingua franca va esser plu simplic e regulari quam li existent Europan lingues. It va esser tam simplic quam Occidental in fact, it va esser Occidental. A un Angleso it va semblar un simplificat Angles, quam un skeptic Cambridge amico dit me que Occidental es. Li Europan lingues es membres del sam familie. Lor separat existentie es un myth. Por scientie, musica, sport etc, litot Europa usa li sam vocabular. Li lingues differe solmen in li grammatica, li pronunciation e li plu commun vocabules. Omnicos directe al desirabilite de un nov lingua franca: On refusa continuar payar custosi traductores. At solmen va esser necessi far uniform grammatica, pronunciation e plu sommun paroles. Ma quande lingues coalesce, li grammatica del resultant lingue es plu simplic e regulari quam ti del coalescent lingues. Li nov lingua franca va esser plu simplic e regulari quam li existent Europan lingues. It va esser tam simplic quam Occidental in fact, it va esser Occidental. A un Angleso it va semblar un simplificat Angles, quam un skeptic Cambridge amico dit me que Occidental es.Li Europan lingues es membres del sam familie. Lor separat existentie es un myth. Por scientie, musica, sport etc, litot Europa usa li sam vocabular. Li lingues differe solmen in li grammatica, li pronunciation</p>
      </div>
    </div>
  </article>
 
  <article class="bl_box">
    <label for="rta02" class="el_heading02">title2</label>
    <input id="rta02" class="el_radio" type="radio" name="rta" value="2">
    <div class="bl_content02" title="title2">
      <div class="bl_inner">
        <p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex</p>
      </div>
    </div>
  </article>
 
  <article class="bl_box">
    <label for="rta03" class="el_heading03">title3</label>
    <input id="rta03" class="el_radio" type="radio" name="rta" value="3">
    <div class="bl_content03" title="title3">
      <div class="bl_inner">
        <p>Li Europan lingues es membres del sam familie. Lor separat existentie es un myth. Por scientie, musica, sport etc, litot Europa usa li sam vocabular. Li lingues differe solmen in li grammatica, li pronunciation e li plu commun vocabules. Omnicos directe al desirabilite de un nov lingua franca: On refusa continuar payar custosi traductores. At solmen va esser necessi far uniform grammatica, pronunciation e plu sommun paroles. Ma quande lingues coalesce, li grammatica del resultant lingue es plu simplic e regulari quam ti del coalescent lingues. Li nov lingua franca va esser plu simplic e regulari quam li existent Europan lingues. It va esser tam simplic quam Occidental in fact, it va esser Occidental. A un Angleso it va semblar un simplificat Angles, quam un skeptic Cambridge amico dit me que Occidental es. Li Europan lingues es membres del sam familie. Lor separat existentie es un myth. Por scientie, musica, sport etc, litot Europa usa li sam vocabular. Li lingues differe solmen in li grammatica, li pronunciation e li plu commun vocabules. Omnicos directe al desirabilite de un nov lingua franca: On refusa continuar payar custosi traductores. At solmen va esser necessi far uniform grammatica, pronunciation e plu sommun paroles. Ma quande lingues coalesce, li grammatica del resultant lingue es plu simplic e regulari quam ti del coalescent lingues. Li nov lingua franca va esser plu simplic e regulari quam li existent Europan lingues. It va esser tam simplic quam Occidental in fact, it va esser Occidental. A un Angleso it va semblar un simplificat Angles, quam un skeptic Cambridge amico dit me que Occidental es. Li Europan lingues es membres del sam familie. Lor separat existentie es un myth. Por scientie, musica, sport etc, litot Europa usa li sam vocabular. Li lingues differe solmen in li grammatica, li pronunciation e li plu commun vocabules. Omnicos directe al desirabilite de un nov lingua franca: On refusa continuar payar custosi traductores. At solmen va esser necessi far uniform grammatica, pronunciation e plu sommun paroles. Ma quande lingues coalesce, li grammatica del resultant lingue es plu simplic e regulari quam ti del coalescent lingues. Li nov lingua franca va esser plu simplic e regulari quam li existent Europan lingues. It va esser tam simplic quam Occidental in fact, it va esser Occidental. A un Angleso it va semblar un simplificat Angles, quam un skeptic Cambridge amico dit me que Occidental es.Li Europan lingues es membres del sam familie. Lor separat existentie es un myth. Por scientie, musica, sport etc, litot Europa usa li sam vocabular. Li lingues differe solmen in li grammatica, li pronunciation e li plu commun vocabules. Omnicos directe al desirabilite de un nov lingua franca: On refusa continuar payar custosi traductores. At solmen va esser necessi far uniform grammatica, pronunciation e plu sommun paroles. Ma quande lingues coalesce, li grammatica del resultant lingue es plu simplic e regulari quam ti del coalescent lingues. Li nov lingua franca va esser plu simplic e regulari quam li existent Europan lingues.</p>
      </div>
    </div>
  </article>
 
  <article class="bl_box">
    <label for="rta04" class="el_heading04">title4</label>
    <input id="rta04" class="el_radio" type="radio" name="rta" value="4">
    <div class="bl_content04" title="title4">
      <div class="bl_inner">
        <p>Li Europan lingues es membres del sam familie. Lor separat existentie es un myth. Por scientie, musica, sport etc, litot Europa usa li sam vocabular. Li lingues differe solmen in li grammatica, li pronunciation e li plu commun vocabules. Omnicos directe al desirabilite de un nov lingua franca: On refusa continuar payar custosi traductores. At solmen va esser necessi far uniform grammatica, pronunciation e plu sommun paroles. Ma quande lingues coalesce, li grammatica del resultant lingue es plu simplic e regulari quam ti del coalescent lingues. Li nov lingua franca va esser plu simplic e regulari quam li existent Europan</p>
      </div>
    </div>
  </article>
 
  <article class="bl_box">
    <label for="rta05" class="el_heading05">title5</label>
    <input id="rta05" class="el_radio" type="radio" name="rta" value="5">
    <div class="bl_content05" title="title5">
      <div class="bl_inner">
        <p>Li Europan lingues es membres del sam familie. Lor separat existentie es un myth. Por scientie, musica, sport etc, litot Europa usa li sam vocabular. Li lingues differe solmen in li grammatica, li pronunciation e li plu commun vocabules. Omnicos directe al desirabilite de un nov lingua franca: On refusa continuar payar custosi traductores. At solmen va esser necessi far uniform grammatica, pronunciation e plu sommun paroles. Ma quande lingues coalesce, li grammatica del resultant lingue es plu simplic e regulari quam ti del coalescent lingues. Li nov lingua franca va esser plu simplic e regulari quam li existent Europan lingues. It va esser tam simplic quam Occidental in fact, it va esser Occidental. A un Angleso it va semblar un simplificat Angles, quam un skeptic Cambridge amico dit me que Occidental es. Li Europan lingues es membres del sam familie. Lor separat existentie es un myth. Por scientie, musica, sport etc, litot Europa usa li sam vocabular. Li lingues differe solmen in li grammatica, li pronunciation e li plu commun vocabules. Omnicos directe al desirabilite de un nov lingua franca: On refusa continuar payar custosi traductores. At solmen va esser necessi far uniform grammatica, pronunciation e plu sommun paroles. Ma quande lingues coalesce, li grammatica del resultant lingue es plu simplic e regulari quam ti del coalescent lingues. Li nov lingua franca va esser plu simplic e regulari quam li existent Europan lingues. It va esser tam simplic quam Occidental in fact, it va esser Occidental. A un Angleso it va semblar un simplificat Angles, quam un skeptic Cambridge amico dit me que Occidental es.Li Europan lingues es membres del sam familie. Lor separat existentie es un myth. Por scientie, musica, sport etc, litot Europa usa li sam vocabular. Li lingues differe solmen in li grammatica, li pronunciation</p>
      </div>
    </div>
  </article>
 
</div>

SCSS

長くなりますがSCSSは下記です。

/* =========================================================
Reset
========================================================= */
 
* {
  margin: 0;
}
 
/* =========================================================
 init
========================================================= */
$pc: 769px; //PCサイズ
$sp: 768px; //SPサイズ
$tab_class: '.ly_rta'; //親要素
$tab_heading: 'label[class^="el_heading"]'; //タブ
$tab_content: 'div[class^="bl_content"]'; //コンテンツ
$tab_length: 5; //タブの数
$tab_width: 150px; //タブの幅
$tab_height: 50px; //タブの高さ
$tab_padding: 10px; //タブのpadding
 
//タブのサイズを計算
@mixin tab-size {
  box-sizing: border-box;
  width: $tab-width;
  height: $tab-height;
  padding: $tab-padding;
}
 
#{$tab-class} {
  .el_radio {
    display: none;
  }
 
  //* ----- 高さを可変にするため指定 ----- */
  #{$tab_content} {
    overflow: hidden;
    max-height: 0;
  }
 
  .el_radio:checked + #{$tab_content} {
    max-height: 9999px;
  }
  //* ----- /高さを可変にするため指定 ----- */
 
  .bl_inner {
    padding: 1em;
  }
}
 
/* =========================================================
 Tab(PC)
========================================================= */
@media screen and (min-width: $pc) {
  
  #{$tab-class} {
    position: relative;
 
    #{$tab_heading} {
      position: absolute;
      z-index: 1;
      top: 0;
      cursor: pointer;
      background-color: #fff;
 
      @include tab-size;
    }
 
    //タブのコンテンツ
    #{$tab_content} {
      position: absolute;
      left: 0;
      padding-top: $tab-height;
      transition: opacity .5s ease-in;
      opacity: 0;
 
      //:before でアクティブなタブを表示します
      &:before {
        position: absolute;
        z-index: 1;
        top: 0;
        display: block;
        content: attr(title);
        transition: opacity .5s ease-in;
        background-color: #d5d5d5;
 
        @include tab-size;
      }
    }
 
    .bl_inner {
      background-color: #d5d5d5;
    }
 
    //タブの幅×個数でleftの位置を出力
    $tmp: '';
    @for $i from 0 through $tab-length - 1 {//0〜5が出力されるためマイナス1に
      //ゼロパディング処理
      @if $i < 10 {
        $tmp: 0#{$i+1}; //1からのカウントにする
      } @else {
        $tmp: $i+1; //1からのカウントにする
      }
 
      .el_heading#{$tmp},
      .bl_content#{$tmp}:before {
        left: $tab-width * $i;
      }
    }
 
 
    //ラジオボタンがチェックされたら直後の要素を表示する
    .el_radio:checked + #{$tab_content} {
      transition: opacity .5s ease-in;
      opacity: 1;
 
      //アクティブなタブの色
      &:before {
        background-color: #d5d5d5;
      }
    }
  }
}
 
/* =========================================================
 Accordion(SP)
========================================================= */
@media screen and (max-width: $sp) {
 
  #{$tab-class} {
 
    border: 1px solid #000;
    border-bottom: 0;
 
    .bl_inner {
      border-bottom: 0;
 
      &:before {
        display: none;
      }
    }
 
    #{$tab_heading} {
      display: block;
      margin: 0;
      padding: .5em;
      color: #000;
      border-bottom: 1px solid #000;
      background: #d5d5d5;
    }
 
    //タブのコンテンツ
    #{$tab_content} {
      transition: max-height .15s ease-out;
    }
 
    //ラジオボタンがチェックされたら直後の要素を表示する
    .el_radio:checked + #{$tab_content} {
      transition: max-height 1s ease-in;
      border-bottom: 1px solid #000;
    }
  }
}

タブのカレント表示のために :before を使っています。
:before の中身は bl_content01 等に付けたtitle属性を content: attr(title); で表示させています。
これがちょっと無理やり感ありますが、やむを得ず。。

タブをひとつずつ左にずらしていく処理をfor文で書いています。
タブの幅×個数でleftの数値が計算されています。

アコーディオンやタブの高さを可変にするために

アコーディオンやタブの高さを可変にするためにどう書けばよいか悩みました。

height: 0 → height: auto

↑では動きません。

heightの代わりにmax-heightを使えば良いことがわかり、
勉強になりました。

まとめ

タブの初期表示のため最初のラジオボタンに checked を付けたのですが、
そのせいでアコーディオンになっても一番上が開いたままになってしまいました。
この辺はJS使わないと難しいですね。。

またラジオボタンを利用しているため、アコーディオンでひとつ開くと他が閉じてしまいます。
そのため画面が狭いスマートフォンでは、ちょっと見づらくなってしまいます。

これらの問題はアコーディオンだけならチェックボックスで作れば解決できるのですが、
今回はタブとの両立があり、クリアできませんでした。

SCSSは変数やfor文を使っているので、ぱっと見プログラムっぽくなってしまいました。
しかしこのお陰で編集がとても楽になります。

実務で実用的かはともかく、JSを使わずにここまで出来る、
ということがわかり有意義でした。

Writer

KO

誕生日に会社のみんなから『世界文学全集』をプレゼントしてもらった読書好きフロントエンド・エンジニアです。WordPressとMovableTypeが得意ですが、本当の特技は薪割りです。

Contact

ご提案依頼、ご相談、お見積もりなど
お気軽にお問合わせください。

03-6403-3259

平日 10:00~19:00

「Web制作について」とお伝え頂ければ
担当者に取次させていただきます。

Mailform

contact@trym.jp
でも受け付けております。