LoginSignup
19
15

More than 3 years have passed since last update.

flexboxで1行7カラムのカレンダー表示

Last updated at Posted at 2016-06-29

背景

多数のdiv要素をカレンダー様表示(1行当たり7カラム表示)にしたい。

しかし、グリッドレイアウトの基本数字である12カラムと7カラムは相性が悪いため、bootstrap以外の方法が必要。

目的

  • cssにある基本機能を使い、div要素をカレンダーのように横7カラム表示する
    スクリーンショット 2016-06-29 10.40.25.png

  • レスポンシブも対応する

方法

  • カラム表示にflexboxを使い、レスポンシブのためにメディアクエリを追加する。

注意

1行3カラムレイアウトを作る

いつもの方法(bootstrap)

  • bootstrapで3カラムならばdivのclassにcol-xx-4と書く。(今回はcol-sm-4)
  • 本質的にCSSは不要。だたし、枠が合った方がカラム数が明確になるためCSSによりborderを指定した。

コード

bootstrap_test.html
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!-- 文字コード指定 -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<!-- bootstrap読み込み -->
<link rel="stylesheet" type="text/css" href="custom_bs.css">
<!-- css読み込み -->

<div class="row">
  <div class="col-sm-4">
    <p>
      1日目のメニュー
    </p>
  </div>
  <div class="col-sm-4">
    <p>
      2日目のメニュー
    </p>
  </div>
  <div class="col-sm-4">
    <p>
      3日目のメニュー
    </p>
  </div>
  <div class="col-sm-4">
    <p>
      4日目のメニュー
    </p>
  </div>
  <div class="col-sm-4">
    <p>
      5日目のメニュー
    </p>
  </div>
  <div class="col-sm-4">
    <p>
      6日目のメニュー
    </p>
  </div>
  <div class="col-sm-4">
    <p>
      7日目のメニュー
    </p>
  </div>
  <div class="col-sm-4">
    <p>
      8日目のメニュー
    </p>
  </div>
  <div class="col-sm-4">
    <p>
      9日目のメニュー
    </p>
  </div>
</div>
custom_bs.css
div.row > div {
  border: 1px solid black;
  /* 飾り */
}

結果

  • デスクトップ表示
    スクリーンショット 2016-06-29 10.33.47.png

  • スマホ表示(イメージ)
    スクリーンショット 2016-06-29 11.56.50.png

cssの機能を用いた方法(flexbox)

  • 解説は後で。

コード

flexbox_test.html
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!-- 文字コード指定 -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<!-- bootstrap読み込み。bootstrapと見た目を一緒にするために加えている。flexboxはこれが無くても動作する -->
<link rel="stylesheet" type="text/css" href="custom_fb.css">
<!-- css読み込み -->

<div class="cont">
  <!-- flexboxのコンテナ -->
  <div class="item">
    <!-- flexboxのアイテム-->
    <p>
      1日目のメニュー
    </p>
  </div>
  <div class="item">
    <!-- flexboxのアイテム-->
    <p>
      2日目のメニュー
    </p>
  </div>
  <div class="item">
    <!-- flexboxのアイテム-->
    <p>
      3日目のメニュー
    </p>
  </div>
  <div class="item">
    <!-- flexboxのアイテム-->
    <p>
      4日目のメニュー
    </p>
  </div>
  <div class="item">
    <!-- flexboxのアイテム-->
    <p>
      5日目のメニュー
    </p>
  </div>
  <div class="item">
    <!-- flexboxのアイテム-->
    <p>
      6日目のメニュー
    </p>
  </div>
  <div class="item">
    <!-- flexboxのアイテム-->
    <p>
      7日目のメニュー
    </p>
  </div>
  <div class="item">
    <!-- flexboxのアイテム-->
    <p>
      8日目のメニュー
    </p>
  </div>
  <div class="item">
    <!-- flexboxのアイテム-->
    <p>
      9日目のメニュー
    </p>
  </div>
</div>
custom_fb.css
* {
  box-sizing: border-box;
  /* widthにpaddingとborderを含めて計算を簡単にするため */
}
div.cont {
  display: flex;
  /* flexboxレイアウトを使うための命令 */
  flex-wrap: wrap;
  /* 上記で囲われたflexアイテムを折り返すように設定する */
}
div.item {
  width: 33.3%;
  /* 100%を1行当たりのカラム数(今回は3)で割った数値 */
  border: 1px solid black;
  /* 飾り */
  margin: 0;
  /* widthの計算簡単にするため(marginも使うための拡張は後で) */
}
@media (max-width: 767px) {
  /*レスポンシブ用*/
  div.cont {
    display: block;
  }
  div.item {
    width: 100%;
  }
}

結果

  • デスクトップ表示
    スクリーンショット 2016-06-29 10.34.58.png

  • スマホ表示(イメージ)
    スクリーンショット 2016-06-29 11.57.38.png

本題:1行7カラムレイアウトを作る

bootstrapでやる方法はわからなかったので、flexboxの例のみ。

flexbox

コード

  • flexbox_test.htmlは上記と同じ。
  • custom_fb.cssの変更は 1行だけ 。div.itemのwidthを33.3%から14.28%に書き換える。それだけ。
    • 100 / 7 = 14.28
custom_fb.css
* {
  box-sizing: border-box;
  /* widthにpaddingとborderを含めて計算を簡単にするため */
}
div.cont {
  display: flex;
  /* flexboxレイアウトを使うための命令 */
  flex-wrap: wrap;
  /* 上記で囲われたflexアイテムを折り返すように設定する */
}
div.item {
  width: 14.28%;
  /* 100%を1行当たりのカラム数(今回は7)で割った数値 */
  border: 1px solid black;
  /* 飾り */
  margin: 0;
  /* widthの計算簡単にするため(marginも使うための拡張は後で) */
}
@media (max-width: 767px) {
  /*レスポンシブ用*/
  div.cont {
    display: block;
  }
  div.item {
    width: 100%;
  }
}

結果

  • デスクトップ表示
    スクリーンショット 2016-06-29 10.40.25.png

  • スマホ表示(イメージ)
    省略

解説

xxx.html
<div class="cont">
  <div class="item">
  </div>
  <div class="item">
  </div>
</div>
yyy.css
div.cont {
  display: flex;
}
  • このままだとdiv.itemが横に並ぶだけなので折り返すためにflex-wrap: wrap;を追加する
yyy.css
div.cont {
  display: flex;
  flex-wrap: wrap;
}
  • 任意のカラム数で折り返してもらうためdiv.itemのwidthを指定する。このときwidthは%で指定し、100%を目的とするカラム数で割った値に設定する。7カラムであれば14.28%。
yyy.css
div.cont {
  display: flex;
  flex-wrap: wrap;
}
div.item {
  width: 14.28%
}
  • レスポンシブになるように、幅が狭い場合(本例では767px以下)ではflexboxを使わない様にする
yyy.css
div.cont {
  display: flex;
  flex-wrap: wrap;
}
div.item {
  width: 14.28%
}
@media (max-width: 767px) {
  div.cont {
    display: block;
  }
}

応用(marginも設定したい場合)

  • 単純にdiv.itemにmarginを指定すると1行当たりに表示したいカラム数が減ってしまいます。
  • div.itemのwidthはmarginの合計を差し引いた値をカラム数で割った値にします。
  • widthの計算の単位を揃えるため、div.itemにmarginも設定したい場合は、%単位で指定してください。
    • (100% - margin (%) * (カラム数 - 1) * 2 + margin (%) * 2}) / カラム数}
  • 例えば、margin: 1%;でカラム数7の場合は以下のかんじです。
yyy.css
div.item {
  width: 12.28% /* = 100 - 1 * (7 - 1) * 2 + 1 * 2  */
  margin: 1%
}
  • scssだったら変数を使うと一般化できます
zzz.scss
$n: 7; //1行当たりのカラム数
$m: 1%; //カラム左右のマージン
// 省略
div.item {
  width: calc((100% - #{$m * ($n - 1) * 2 + $m * 2}) / #{$n});
  margin: $m;
}
// 省略

結果

スクリーンショット 2016-06-29 11.14.22.png

その他

  • paddingを使う時は、widthの計算を簡単にするため、* {box-sizing: border-box;}を使うと楽

    http://phiary.me/css3-box-sizing/

  • 今回の例では効果がわからないけど、flexboxでレイアウトしたitemの高さはデフォルトで 揃います 。floatでこれをやるとすごい面倒。

    http://shanabrian.com/web/html-css-js-technics/css-equal-height.php

  • コードは省略するけど、こんな感じに高さが揃った表示もflexboxだとすごい簡単だった。

    スクリーンショット 2016-06-29 11.27.11.png

最後に

  • bootstrapだとhtmlに見た目も書くことになって気持ち悪かったのが、flexboxだと楽々すっきり。
19
15
1

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
19
15