LoginSignup
2
1

More than 5 years have passed since last update.

レスポンシブだけど要素の順序が違うレイアウト

Posted at

やりたいこと

layout.png
画面幅がブレイクポイント以上の場合:
横並びになったボタンをクリックすると、ボタン列の下に対応するコンテンツが表示される、いわゆるタブレイアウト。

画面幅がブレイクポイント未満の場合:
縦に並んだボタンをクリックすると、クリックしたボタンの下に対応するコンテンツが表示される、いわゆるアコーディオン。

単純に考えると、html要素の並びは
タブだと「button1,button2,button3...,content1,content2,content3,...」、
アコーディオンだと「button1,content1,button2,content2,button3,content3,...」と異なるため、
レスポンシブで対応するにはちょっと一工夫が必要です。

実装

html

<div class="alterBox">
  <input class="alterBox_hide" id="tab_01" type="radio" name="tab" checked>
  <label class="alterBox_tab" for="tab_01">
    <span>Button1</span>
  </label>
  <div class="alterBox_body">
    <p>Contents1</p>
  </div>
  <input class="alterBox_hide" id="tab_02" type="radio" name="tab">
  <label class="alterBox_tab" for="tab_02">
    <span>Button2</span>
  </label>
  <div class="alterBox_body">
    <p>Contents2</p>
  </div>
  <input class="alterBox_hide" id="tab_03" type="radio" name="tab">
  <label class="alterBox_tab" for="tab_03">
    <span>Button3</span>
  </label>
  <div class="alterBox_body">
    <p>Contents3</p>
  </div>
</div>

css

アニメーションは割愛

.alterBox {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}
.alterBox_tab {
  display: block;
}
.alterBox_body {
  width: 100%;
  display: none;
}

.alterBox_hide:checked+.alterBox_tab+.alterBox_body {
  display: block;
}
.alterBox_hide {
  display: none;
}
@media all and (min-width: 601px) {
  .alterBox {
    width: 800px;
  }
  .alterBox_tab {
    width: 30%;
  }
  .alterBox_tab:nth-of-type(1) { order: 1; }
  .alterBox_tab:nth-of-type(2) { order: 2; }
  .alterBox_tab:nth-of-type(3) { order: 3; }
  .alterBox_body {
    order: 999;
  }
}
@media all and (max-width: 600px) {
  .alterBox_tab {
    width: 100%;
  }
}
/* 見た目調整 */
.alterBox_tab {
  border: solid 1px;
  padding: 10px;
  text-align: center;
  margin-bottom: 5px;
}
.alterBox_body {
  border:solid 1px;
  min-height: 200px;
  padding: 0 10px;
  margin-bottom: 5px;
}
.alterBox_hide:checked+.alterBox_tab {
  color: white;
  background-color: #000
}
/*-----*/

表示

pc.gif
sp.gif

ポイント

  • html要素の順序はアコーディオンに合わせつつ、
    タブの場合はorderプロパティを用いて、contentsが最後に来るよう表示上の並び順を変更しています。
    .alterBox_tab:nth-of-type(N) { order: N; }を任意のNまで書いておけば、その数まではページが増えてもCSS調整なしで対応することが可能です。

  • タブやアコーディオンの表示制御はCSSで実装しています。
    拡張性にはやや欠けるものの、動作と表示の実装をほぼCSSだけで完結できるので、規模が小さいプロダクトであれば、CSSで実装してしまうのが楽かなと思います。

問題点

表示制御はinput(type="radio")要素を用いているため、
アコーディオンは同時に1つしか開くことができません(1を開いた後2を開くと1が閉じる)。
同時にいくつも開きたい場合は以下のようなjsを用いて、SP表示の時だけラジオボタンをチェックボックスに変更すれば実現可能です。js使っとるやんけとか言わない

document.addEventListener('DOMContentLoaded', function(){
  switchTab();
}, false);
var resizeQue = null;
window.addEventListener('resize', function() {
  clearTimeout( resizeQue );
  resizeQue = setTimeout(function() {
    switchTab();
  }, 300 );
}, false);

function switchTab() {
  var isSp = (window.innerWidth < 601);
  if(!isSp) {
    var radios = document.querySelectorAll('.alterBox_hide');
    for (var i=0; i<radios.length; i++) {
      radios[i].setAttribute("type","radio");
    }
  } else {
    var radios = document.querySelectorAll('.alterBox_hide');
    for (var i=0; i<radios.length; i++) {
      radios[i].setAttribute("type","checkbox");
    }
  }
}
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1