🔬

【令和版】CSSで要素を横並びにする方法+α

2022/07/30に公開

はじめに

普段、個人でWebアプリを書くときにはこだわりが無いのでBootstrapを使っていました。ただ他にもっとシンプルなの無いかなぁ、と探してたらWater.cssというclasslessなCSSフレームワークを見つけました。
https://watercss.kognise.dev/
HTMLタグに直接装飾がマッピングされているので、それっぽいデザインが簡単に出来ます。ダークモードが中々良いですね。
ただBootstrapのようにグリッド機能が無さそうなので、レイアウトがちょっとめんどそうだな。。。と思いつつも今回は簡単なUIだから久しぶりにfloatとか手書きすることに。そして記憶の彼方にいったやり方を調べてたらCSS Grid Layoutという機能が標準搭載されてる事を今更知りました。中々便利そう&私のようにBootstrap + JQuery時代で止まってる人も居るかもしれないので、簡単に紹介しておこうと思います。

TL;DR

  • CSS Grid Layoutを使えばブラウザの標準機能
  • Bootstrapのようなカラムでレイアウトが出来る
  • 手癖でやってる事もたまに調べるのは大事

横並びのレイアウトをしたい! CSS - float/flex編

一般的なWebサイトだとこういう感じでアイテムを縦横に並べた感じに作りますよね?

いにしえの時代であれば古代語魔法のframeタグとか禁呪法のテーブルレイアウトを使ってこうしたデザインを作ってきたわけですが、近代からはCSSを使ってこうしたデザインを作るのが当たり前になっています。そんなわけで css横に並べる でググって良く出てくるのがfloatやflexを利用する方法です。

<div class="container">
    <div class="box">One</div>
    <div class="box">Two</div>
    <div class="box">Three</div>
    <div class="box">Four</div>
    <div class="box">Five</div>
    <div class="box">Six</div>
</div>

上記のようなHTMLに対して以下のようなCSSを適用します。

.box {
    float: left;
}

これで各ボックスが左に回り込んで横並びになります。ただ、複雑に並んでるHTMLだと結構レイアウトの制御が難しく、display: flexが出てようやく横並びのデザインが簡単に出来るようになったという印象。

.container {
    display: flex;
}

ただ、これでも各ボックスの大きさの調整だとか、最初に貼ったような普通のレイアウトのデザインを作るのもそれなりに手間でした。

Bootstrapによるグリッドシステム

およそ10年くらい前からBootstrapが登場し、私のようなデザインセンスとスキルの無いプログラマでもそれっぽいUIが簡単に作れるという事もあって瞬く間に人気になりました。もちろんカスタマイズして高度な利用も出来ますから、素人からプロまで活用できる良いツールですよね。

ボタンやテキストボックスが標準のものより格段とカッコよくなる、という点も大きな魅力なのですが、グリッドシステムによりカラムを使って簡単にデザインが出来るようになったのが大きいですよね。

Bootstrapでは画面を12のカラム(Col) に分け、さらに列(Row) の概念を導入する事で、画面比率も複雑な段組みも簡単に実現する事が出来ます。

ref: ウェブさえ - Bootstrapのグリッドシステムの使い方を初心者に向けておさらいする

例えば最初に画像で貼ったようなHEADER/MENU/CONTENT/FOOTERの構成であれば以下のようなHTMLになります。

<div class="container">
    <div class="row">
        <div class="col-12 header">HEADER</div>
    </div>
    <div class="row">
        <div class="col-4 menu">MENU</div>
        <div class="col-8 content">CONTENT</div>
    </div>
    <div class="row">
        <div class="col-12 footer">FOOTER</div>
    </div>
</div>

テーブルレイアウトの直観性を正しい方法で実現出来るようになって、良いとこどりが出来ました。このグリッドシステムがあるおかげで、レイアウトを組むのがグッとに楽になったのは間違いないと思います。

CSS グリッドレイアウトによる標準での対応

2017年頃よりCSS グリッドレイアウトの普及が始まったようです。
https://developer.mozilla.org/ja/docs/Web/CSS/CSS_Grid_Layout
Flexible Box Layoutに続く形として横方向だけでは無く縦方向もカバーした二次元のレイアウトを制御できるのがCSS Grid Layoutのモチベーションです。Bootstrapのグリッドシステムと同じ思想ですね。


ref:ZeroPlus Media - 爆速でレイアウトを完結させるCSS Gridの使い方を丁寧に解説

先ほどのBoostrapのグリッドシステムで作ったのと同じレイアウトをCSSグリッドレイアウトでしてみましょう。

    <div class="container">
        <div class="header">HEADER</div>
        <div class="menu">MENU</div>
        <div class="content">CONTENT</div>
        <div class="footer">FOOTER</div>
    </div>
.container {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
}
.header {
    grid-column: 1/13;
}
.menu {
    grid-column: 1/4;
}
.content {
    grid-column: 4/13;
}
.footer {
    grid-column: 1/13;
}

コードの解説は後ほどしますが、HTMLがBootstrapに比べてグッとすっきりしましたね。余計なdivタグも無いですしclassにcol-12のようなデザイン情報を追加する必要もありません。一方で、CSSを書かなくて良かったBootstrapと違いCSSを記述する必要が出てきています。CSSの機能なので当たり前ではありますが。どちらが良いかは好みによると思いますが、個人的にはCSSのデザインと論理構造を分離する、という思想が好きなので装飾をHTMLからCSSに切り出せるのは好ましいです。float時代みたいに複雑じゃないしね!

英語ですが、BoostrapよりCSSグリッドレイアウトのが良いという話は以下の記事で色々書かれていて参考になります。
https://hackernoon.com/how-css-grid-beats-bootstrap-85d5881cf163

なお、気になる対応状況ですが、2022/07/30現在、スマホからPCまでほぼ全てのブラウザで利用出来きます。

ref: https://caniuse.com/css-grid

CSS グリッドレイアウトを少しだけ解説

MDNのページや他にも詳しく解説されている記事があると思うので、詳細はそちらで調べてもらうとして、簡単な解説だけしておきます。

CSS Gridでは親になるコンテナのdisplayをgridに設定する事でグリッドコンテナ化します。

.container {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
}

grid-template-columnsは画面全体をどのようなカラムに分けるか、を示していてピクセルなど任意の単位が使えます。たとえば200pxで3つに分けるなら以下のようになります。

.container {
    display: grid;
    grid-template-columns: 200px, 200px, 200px;
}

さらに新単位としてfrが導入されていて、これは空間比を表しています。つまり単純に3分割するのであれば以下のように書けます。

    grid-template-columns: 1fr, 1fr, 1fr;

ただ、Boostrapと同じように12カラムに分割、とかになるとちょっと手で書いていくのは大変です。そのためrepeatという構文があり以下のように上記のコードは置き換える事が出来ます。

    grid-template-columns: repeat(3, 1fr);

また、今回のサンプルではカラムの数しか指定していませんが、同様にRowに関しても色々と指定は可能です。コンテナにgap:10pxなどと指定する事でコンテナ内のアイテム同士の間隔を指定する事も出来ます。

さて次にコンテナの中のアイテムの配置です。実は何も指定しない場合は暗黙のうちに自動で均等割りをされます。MDNから引っ張ってきた以下の図がイメージしやすいですね。

均等割りでは無く4:8のような比率でレイアウトを組みたい場合、grid-template-columns:4fr, 8frみたいに直でカラム比率を指定しても良いのですが、Bootstrapのように細かく均等に分けて、各アイテムでどのくらいのカラムを取るか、で制御するのが分かりやすいですよね。そのような時にはgrid-column-startgrid-column-endで、どのカラムからどのカラムまでを取るのか、を指定します。

.container {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
}
.header {
    grid-column-start: 1;
    grid-column-end: 13;
}
.menu {
    grid-column-start: 1;
    grid-column-end: 4;
}
.content {
    grid-column-start: 4;
    grid-column-end: 13;
}

これでheaderは12カラムすべてを、menuは4カラム、contentは8カラム取得できます。ここでちょっと不思議なのが12分割しているのに13カラム目指定してることですよね? これはCSS Gridでは指定出来る部分が下記の図のように分割数より一つ多く出来るから、ですね。

Boostrapとは違う部分ですが、そんなに直観から外れる分けでもないので慣れるのは簡単そうですね。

さらにgrid-column-startgrid-column-endは少し書き方が冗長なので、grid-column/(スラッシュ)で開始位置と終了位置を書くシンタックスシュガーもあります。以下は上で書いているコードと等価の意味になります。

.header {
    grid-column: 1/13;
}
.menu {
    grid-column: 1/4;
}
.content {
    grid-column: 4/13;
}

最初、13個に分けたうちの1つ、という意味かと勘違いしましたが分数という分けでは無いようです。-(ハイフン)とかの方が個人的には分かりやすかったな... またカラムを複数個結合しない場合にはgrid-column: 5のように終了値を省略できます。

ちなみにGridの状況はChromeのDevToolなどで可視化する事も出来ます。便利ですね!

まとめ

このあたりちゃんと追ってなかったのでいつの間にか便利なものが入っててビックリしたので備忘としてまとめておきました。たまには新しい方法も探してみると色々見つかるものですね。90歳を超える祖母がクックパッド等で新しいレシピ手順アップデートしていたのを思い出します。

自分はあまり凝ったデザインは元より作れないので、Water.cssと組み合わせてBootsrap-lessなページも作っていこうかと思います。

それではHappy Hacking!

参考

https://developer.mozilla.org/ja/docs/Web/CSS/CSS_Grid_Layout
https://zenn.dev/umatoma/articles/b970bdd3a148cd

Discussion