あぱれる男子のつぶやき

プログラミングを奮闘中

【Bootstrapその⑪】グリッドシステムについてもっと深掘ってみた【学習積み上げ】

f:id:mmmouh8845:20200123002523p:plain


着々とBootstrapの学習をしてきました、マサです。


これまでの記事でも何度か書いてきましたが、Bootstrapに頼るのは抵抗があるという方は多いと思います。

Bootstrapに慣れすぎるとcssが疎かになったり、htmlの記述が多くなったり、また他で代用できるとも思います。


ですが、グリッドシステムだけでも採用する価値はあります。

なので、ここだけでもきちんと理解するために、以前記事にしたものをリライトして、個人的に「もっと理論的なことや知っておくべきことがあるな」と感じたところをもっと深堀ってみました。


内容としては、コンテナについての細かいまとめ、その次は以前紹介できなかった余白の使い方についてのまとめです。


では、いきましょう!

Bootstrapのグリッドシステムの詳細

Bootstrapでグリッドシステムを使うときは親要素のclass名にcontainerをつけ、その子要素のclass名にrowをつけるということは以前やりました。

ではこのcontainerとrowの関係性はどうなっているのか?
ここを見ていきます。

containerとrowの仕組み

まず、containerに関してはcontainerとcontainer-fluidの2種類があります。

違いとしては内部コンテナの幅を固定するかしないかです。(実例を後述します)


そしてcontainerとrowに関して、Bootstrapで事前に付いているスタイルがあります。

それは、

.container {
  width: 100%;
  padding-right: 15px;
  padding-left: 15px;
  margin-right: auto;
  margin-left: auto;
}

.row {
  display: flex;
  flex-wrap: wrap;
  margin-right: -15px;
  margin-left: -15px;
}

これです。containerとcontainer-fluidについているスタイルは同じです。
ポイントはcontainerにpaddingが、rowにはネガティブmarginがかかっていることですね。


これを踏まえてcontainerとrowの指定を変えるとどういった挙動になるのか見てみましょう。

両方指定した場合

f:id:mmmouh8845:20200127205535p:plain

   <div class="container mt-5">
    <div class="row">
      <div class="col-3" style="height: 200px; background: #f88;">box1</div>
      <div class="col-9" style="height: 200px; background: #f66;">box2</div>
    </div>
  </div>

  <div class="cotainer-fluid">
    <div class="row">
      <div class="col-5" style="height: 200px; background: #5a5;">box3</div>
      <div class="col-1" style="height: 200px; background: #5f5;">box4</div>
      <div class="col-4" style="height: 200px; background: #5a5;">box5</div>
      <div class="col-2" style="height: 200px; background: #5f5;">box6</div>
    </div>
  </div>
</div>


まずはbox1,2とbox3~6で表示が異なる点から見ていきましょう。

containerをclass名に指定すると、左右に均等なmarginを確保してくれているように見えますが、これはcontainerのclassに「ウィンドウの幅に応じて内部の固定幅が決まる」という特徴があるからです。

以前の記事でも表として登場させましたが、わかりやすく日本語で書いてみました。

ウィンドウの幅 576px未満 576~768px未満 768~992px未満 992~1200px未満 1200px以上
コンテナの幅 100%(ウインドウ幅に準じる) 540px 720px 960px 1140px


このようにウィンドウに応じて、内部の幅が段階的に変わっていくのですが、この画像の場合、bodyは1300px以上あるので、box1,2をあわせたコンテナのwidthは表の一番右のように、1140pxとなります。

f:id:mmmouh8845:20200129073715p:plain
box-1=container、box-2=container-fluid

f:id:mmmouh8845:20200127205849p:plain
mt-5はmargin-topで30pxの余白を取っています。


結果、1349px-1140pxの209pxが余るのですが、Bootstrapのcontainerには前述したようにデフォルトでmarginの左右にautoがかかっているので、209÷2=104.5pxが左右均等にかかることで、コンテナがセンターに位置します。


対して、cotainer-fluid「ウィンドウの幅に関わらずに内部の幅を固定する」という意味になります。

なので、コンテナ=bodyの幅と同じ1349pxを12等分にして、colで分けて表示しているということになります。


f:id:mmmouh8845:20200129074257p:plain
box-3の場合、col=5なので、(1349px÷12)×5=562.08...となります。



そしてここからが本題です。
containerにはデフォルトでmarginの左右にautoがかかっていると前述しましたが、先ほどコードで書いたように他にもpaddingが左右に15pxかかって、同じようにrowにはデフォルトでmarginが-15pxがかかっています。

そうすると余白が相殺されるので、0になります。
特にcotainer-fulidを指定したときにウィンドウの幅ピッタリに要素が表示されるのが分かります。

ですので、ウィンドウの幅を変えたとしても、横スクロールバーは表示されずにピッタリになっています。

こういった事情があるため、container(container-fulid)とrowは両方とも指定することがデザインが崩れないためには望ましいとされています。

containerのみを指定した場合

では先ほどのbox1,2を含むrowをコメントアウトして、containerのみにしてみました。

<div class="container">
    <!-- <div class="row"> -->
      <div class="col-3" style="height: 200px; background: #f88;">box1</div>
      <div class="col-9" style="height: 200px; background: #f66;">box2</div>
    <!-- </div> --></div>

この場合はcolが無効になり、要素が縦並びになります。

f:id:mmmouh8845:20200127215356p:plain


しかしこれでは、余白の挙動がよくわかりません。

なので、rowを外しても影響がないようにcol-12のbox7を追加してみました。

  <div class="container-fulid">
    <div class="row">
      <div class="col-12" style="height: 200px; background: #57b;"> box7</div>
    </div>
  </div>

containerとrowの両方指定のときは、ウィンドウの幅ぴったりに要素が表示されます。

f:id:mmmouh8845:20200129075400p:plain
box-7はウィンドウの幅ピッタリで横スクロールバーも無い


そして、これのrowの部分をなくしてみると、

f:id:mmmouh8845:20200129075535p:plain


先ほどと似ていますが1349pxから1319pxに変わったことで、左右に余白ができました。

このことから、rowをなくしてcontainer(container-fulid)のみの指定にすると、余白の相殺がなくなり、container(container-fulid)にデフォルトで付いている左右のpaddingが15pxのみになります。


f:id:mmmouh8845:20200129082213p:plain

つまり、要素に計30pxの余白がつくことになります。


rowのみを指定した場合

では、containerをなくしてrowのみの指定にするとどうでしょう。

  <!-- <div class="container mt-5"> -->
    <div class="row">
      <div class="col-3" style="height: 200px; background: #f88;">box1</div>
      <div class="col-9" style="height: 200px; background: #f66;">box2</div>
    </div>
  <!-- </div> -->

わかりやすくするため、box-1,2のcontainer部分をコメントアウトしてみました。

この場合はcontainerのmarginもpaddingもないため、画面幅の領域いっぱいに要素が広がります。

そして、rowにデフォルトで付いているmargin-15px分が押し広げられることになるので、

f:id:mmmouh8845:20200129082559p:plain


このように、1349pxから1379pxと逆に30px分大きくなっています。
bodyのwidthは変わらず1349pxなので、今度は横スクロールバーもついていますね。

no-guttersを用いた場合

割とマニアックなケースですが、no-guttersというコードをrowと一緒にclass名に指定する方法があります。
box2のrowにのみno-guttersを指定しました。

   <div class="container-fluid">
    <div class="row no-gutters">
      <div class="col-5" style="height: 200px; background: #5a5;">box3</div>
      <div class="col-1" style="height: 200px; background: #5f5;">box4</div>
      <div class="col-4" style="height: 200px; background: #5a5;">box5</div>
      <div class="col-2" style="height: 200px; background: #5f5;">box6</div>
    </div>
  </div>

このコードの意味はrowについた余白(ネガティブマージン)を無効にするという意味になるので、このように見え方は先ほどcontainerのみを指定したときのpadding15px分が左右の外側についた状態になります。

f:id:mmmouh8845:20200129083500p:plain

メリットとしては、先ほどのように普通にrowを無効にしてcontainerのみにしたときはcolまで解除されて要素が縦並びになっていました。

このcolを有効にしつつ、ネガティブマージンを無効にしたいときにこのclass名が使えるわけです。


画像を用いた場合


boxに画像を使用することもあるかと思いますが、特定のclass名が使えます。


例えば、画像をいくつか並べたいときは、これまでと同様にcolを使い、中にimgタグを入れます。

  <div class="container my-5">
    <div class="row">
      <div class="col-3"><img src="~" alt=""></div>
      <div class="col-3"><img src="~" alt=""></div>
      <div class="col-3"><img src="~" alt=""></div>
      <div class="col-3"><img src="~" alt=""></div>
    </div>
  </div>

しかし、このままでは画像が大きくて見切れてしまいます。

f:id:mmmouh8845:20200129104617p:plain


ここで、imgタグにimg-fluidというclass名をつけると、

f:id:mmmouh8845:20200129104732p:plain


こんな感じで崩れた写真がちゃんと表示されてます。


また、以前の記事でやったサイズとの組み合わせを応用して使ってみました。

  <div class="container my-5">
    <div class="row align-items-end">
 <!-- 後述します -->
      <div class="col-lg-3 col-md-6 mt-3"><img class="img-fluid" src="~" alt=""></div>
      <div class="col-lg-3 col-md-6 mt-3"><img class="img-fluid" src="~" alt=""></div>
      <div class="col-lg-3 col-md-6 mt-3"><img class="img-fluid" src="~" alt=""></div>
      <div class="col-lg-3 col-md-6 mt-3" ><img class="img-fluid" src="~" alt=""></div>
    </div>
  </div>

このようなサイズの複数指定をすると、lg=992px以上のときはcol=3なので写真4枚が一列に並び、991pxからmd=768pxのブレイクポイントまではmd-6になることで、写真が2枚に並びます。そして、smの指定が無いため、768px未満からは、写真1枚が縦に並ぶというスタイルが作れます。

f:id:mmmouh8845:20200129111226p:plain
ウィンドウが1200px以上なので、col-3が適用されている

f:id:mmmouh8845:20200129111348p:plain
ウィンドウが992px以下なので、col-6が適用されている

f:id:mmmouh8845:20200129111513p:plain
ウィンドウが768px以下なので、col-12が適用されている


超簡単レスポンシブですね。写真を使ってここまで便利にできるとかなり楽です。


また、コードを見るとalign-itemsが使われていると思いますが、これは写真4枚が一列に並ぶときに見栄えを悪くしないため、下揃えに指定しているからです。

flexのときにcssで使うスタイルに似てますよね。これに関してはその⑫で詳しく記事にします。


おわりに

今回はcontainerについての詳細な説明と、boxの代わりに写真を用いてより分かりやすくした説明をしました。

正直ここまで詳しくBootstrapをマスターしなくてもいいんじゃないかな、、とは思いますが、グリッドレイアウトを実装するときに思わぬイレギュラーとならないように頭の片隅に入れておきます。


次回はこのグリッドレイアウトで余白や順序を自由に使えるように深掘った記事にします。




それでは。