[CSS]レスポンシブ対応のグリッド システムを実装する時に絶対覚えておきたいテクニックを詳しく解説

HTMLとCSSでグリッド システムを実装する際、何から始めればいいのか、どういうことを考え、決めて、どんな手順で進めるのか。
カラムの幅のつくり方、溝はmarginとpaddingのどちらがよいか、レスポンシブはどう対応するのかなど、グリッド システムを実装するテクニックを詳しく解説します。

かなり長いので、時間のある時に読んでいただければと思います。

レスポンシブ対応のグリッド システムを実装する方法

How to build a responsive grid system

下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。

グリッドの実装に必要な準備

グリッド システムを実装する前に、3つ準備しておくことがあります。

1. グリッドのデザインを決める

カラムの幅はすべて同じ、それとも異なりますか? カラムの数はいくつですか? カラムと溝のサイズはいくつですか?

これらの質問に答えられないと、正しいグリッドの計算をすることができません。
グリッドを設計することについては「Designing Grids」を書きました。もしグリッドを設計することを学ぶ必要がある時は、目を通してください。

2. 異なるビューポートでグリッドがどのように振る舞うか

ビューポートの幅が変化するとき、それに合わせてカラムと溝の幅を変えますか? 特定のブレイクポイントでカラムの数を変えますか?

これらの質問の答えは決めておく必要があります。
そうすることで、カラムと溝の幅をどのように計算するべきかの手がかりになります。この点についても「Designing Grids」で触れているので、自信がないなら見ておいてください。

3. HTMLにグリッド用のclassを書くことを好みますか?

フロントエンドの制作者たちの間では、グリッドの実装方法で2つの派閥があります。

1つ目の派閥はBootstrapやFoundationのように、HTMLにグリッド用のclassを記述します。「HTML グリッド システム」と呼ばれるものです。コードを見てみましょう。

2つ目の派閥はCSSでグリッドを作ります。これは「CSS グリッド システム」と呼ばれます。

「CSS グリッド システム」のHTMLは、「HTML グリッド システム」と比較すると、よりシンプルです。同じグリッドを作成する時に必要なマークアップはより少なく、グリッドのclassが何であるか覚えておく必要はありません。

裏を返すと、「CSS グリッド システム」のCSSはより複雑です。もし初めて使うのであれば、このシンプルなテクニックを成し遂げるには、頭を使うことが必要です。

何を選びますか?

フロントエンドに携わる多くのエキスパートたちは、「CSS グリッド システム」を選びます。私も(私自身をあえてエキスパートとは呼びませんが)同様に「CSS グリッド システム」の派閥に属します。

なぜ「CSS グリッド システム」を選ぶのかについて興味があるなら、「Migrating From Bootstrap to Susy」を見てみてください。また「CSS グリッド システム」に移行するためには「Moving from HTML Grid Systems to CSS Grid Systems」が役立ちます。

読まなければならないものが多い、、、

心配しないでください!
グリッド システムを構築するために決める必要があるのは、3つだけです。

  1. あなたのグリッドのデザイン
  2. 異なるビューポートでグリッドがどのように振る舞うか
  3. HTML あるいは CSS グリッド システムのどちらを使うか

これらの必要条件が決まれば、あとは前進するだけです。
ここでは、3つの必要条件は以下のように決め、グリッドを実装します。

  1. グリッドは最大幅1,140px、カラムは幅75pxで12個、溝は20px。
    これらをどのように決めるかは、「Designing grids」を参考ください。
  2. ビューポートの幅が変化した時は、溝は20pxで固定、カラムの幅は相対的に変化。
    なぜこの振る舞いを選択したかは、「Designing grids」を参考ください。
  3. 実装には、「CSS グリッド システム」を使います。
    なぜCSSを選択したかは、「Migrating From Bootstrap to Susy」を参考ください。

これで準備は整いました、さぁ始めましょう!

グリッド システムの構築

グリッド システムを構築するには、8つのステップがあります。

  1. グリッドを作成するための仕様を選択
  2. border-boxにbox-sizingを指定
  3. グリッドのコンテナを作成
  4. カラムの幅を計算
  5. 溝の位置を決定
  6. デバッグ用のグリッドを作成
  7. レイアウトのバリエーションを作成
  8. レイアウトをレスポンシブ対応に

これらの8つのステップの大部分は、比較的簡単だと思います。知っておく必要があるすべてのことを、各ステップごとに詳しく説明します。

Step 1: グリッドを作成するための仕様を選択

何でグリッドを実装しましょう CSS Grid, Flexbox それとも昔のFloatを使いますか? 検討事項と実装の詳細は、各仕様ごとに異なります。

CSS Grid
3つの仕様の中で、グリッドを作成するために最も優れています。しかしサポートしているブラウザは現状、なしと言える状態です。そのため、ここではCSS Gridについては触れません。
もし、CSS Gridについて興味を持っているなら下記を参考にしてください。最も優れている理由が分かります。
参考: CSSの新しいレイアウトモジュール「CSS Grid Layout」を使って、レスポンシブ対応の3カラムレイアウトを実装するチュートリアル
FlexboxとFloat
これらの2つの仕様を使用する際の検討事項は似ているため、どちらかを選択してもこの論文で最後まで実装することができます。
ここでは説明しやすく、初心者に簡単なので、Floatを使います
Flexboxの場合は、微調整する必要がわずかにあると心に留めておいてください。

Step 2: border-boxにbox-sizingを指定

box-sizingプロパティには幅と高さを計算するために、ブラウザが持つデフォルトのCSSのボックスモデルを変更します。「box-sizing: border-box;」と指定することで、カラムと溝のサイズの計算が簡単になります

box-sizingプロパティに、border-boxをはじめ他の値でどのように計算されるか見てましょう。

box-sizingプロパティの各値の挙動

box-sizingプロパティの各値の挙動

content-box
幅はブルー
コンテンツの値が、幅
padding-box
幅はブルー+グリーン
コンテンツ、パディングの合計値が、幅
border-box
幅はブルー+グリーン+イエロー
コンテンツ、パディング、ボーダーの合計値が、幅

「box-sizing: border-box;」と指定することで、マージンを除くすべての合計値が幅になり、一貫した(いわゆる見た目と同じ)サイズで指定できます。
下記のように記述することで、利用できます。

box-sizingで詳細な説明が必要なら、「Understanding CSS Box Sizing Property」をご覧ください。

Step 3: グリッドのコンテナを作成

すべてのグリッドに、グリッドの最大幅を決定するコンテナがあります。このコンテナを「.l-wrap」とします。「.l-」の接頭辞はレイアウトを意味します。この命名規則は「SMACSS」を読んだときから私がずっと使っているものです。

レスポンシブ対応を考えた場合、単位にpxではなく、emやremのような相対的な単位を使うことを勧めます。ここでは初心者に理解しやすいため、すべてpxを使用します。

Step 4: カラムの幅を計算

ここで確認しておきます、カラムや溝を実装するためにここではfloatを使用しています。floatで実装する時は、5つのプロパティを使います(Flexboxではもう少し増えます)。

  • width
  • margin-right
  • margin-left
  • padding-right
  • padding-left

Step 3で作成したclassをコンテナに与え、「CSS グリッド システム」用のHTMLを記述してみます。

このHTMLでは、divで3つのカラムを実装しました。溝はdivでは実装されません。各プロパティの役割を整理しておきます。

  1. widthプロパティで、カラムの幅を作成します。
  2. margin or paddingプロパティで、溝を作成します。

カラムと溝について同時に考えると複雑になるため、まずは溝がない状態でグリッドを作成します。
溝がないグリッドは、下記のようになります。

溝がない3カラムのグリッド

まずは、溝がない3カラムのグリッド

グリッドの最大幅は1,140pxであることを知っているので、3カラムそれぞれ均等になるように380px(1140÷3)をwidthに指定してみます。

380pxに指定すると、3カラム合計で1,140pxになり、これはビューポートが1,140pxより大きい場合は美しく表示されます。しかし、ビューポートが1,140pxより小さい場合には崩れて表示されます。

ビューポートを変化させたグリッド

1,140px以下にすると崩れる

このことはカラムの幅の単位にpxを使うことができないことを意味します。

わたし達はコンテナの幅に従ってサイズを変更できる単位が必要です。それができるのは%です。
単位を%にして指定してみます。

このコードで、溝がない3カラムのグリッドが完成しました。ビューポートのサイズを変更すると、3つのカラムは相対的にサイズを変更させて表示されます。

ビューポートを変化させたグリッド

溝がない3カラムのグリッド、完成!

floatで実装する場合、一つ注意が必要です。
子要素すべてがコンテナ内にfloatで配置されると、コンテナの高さは崩壊します。この現象は「float collapse(フロートの崩壊)」と呼ばれ、コンテナに子要素が含まれていないかのように振る舞われます。

float collapse(フロートの崩壊)

参考画像: float collapse(フロートの崩壊)

これを解決するために、必要とされるのは「clearfix」です。

Sassのようなプリプロセッサを使うなら、コードをMixinに登録しておくとよいでしょう。

これでカラムの幅を実装できたので、次のステップでは溝を実装します。

Step 5: 溝の位置を決定

いよいよ、溝を実装します。溝の実装はdivではなく、marignあるいは、paddingで実装しますが、どちらを使えばよいと思いますか?

溝の実装を図にすると、可能な方法が4つあることがすぐ分かります。

溝を実装する4つの方法
  1. 溝をmarginとして、カラムの片側に配置
  2. 溝をpaddingとして、カラムの片側に配置
  3. 溝をmarginとして、カラムの両側に半分ずつ配置
  4. 溝をpaddingとして、カラムの両側に半分ずつ配置

これが溝を実装することが複雑な理由です。どの方法を使うにしても、依存するカラムの幅を計算する必要がります。

4つの方法を実際に見て、相違を確認してみましょう。
このステップは時間をかけて、ゆっくり読んでください。

方法 1: カラムの片側に配置(margin)

この方法ではmarignプロパティを使って、溝を実装します。溝はカラムの左か右に配置されます、どちら側を選択するかは、自由です。

ここでは溝を右側に配置して、実装します。

下記の図に従って、カラムの幅を計算し直します。

実装のイメージ

実装のイメージ: カラムの片側に配置(margin)

上の図から、3つのカラムと2つの溝の合計値が、1,140pxであることが分かります。

しかしここで問題があります。カラムの幅を%で指定する必要があり、溝は固定値の20pxです。異なる単位で計算することは今まではできませんでした。

しかし今はそれが可能です!

CSSのcalc()を使うことで、%の単位と他の単位をミックスして計算することができます。calc()は変化する値でも、その都度計算して値を算出します。

カラムの幅をcalc()を使って、指定し直してみます。

できました。
カラムの幅の問題はこれで解決です。

次に右端のアイテムの最後の溝は必要ないので、「:last-child」を使って削除します。

最後の溝を削除した際に、計算した値の小数点の四捨五入のエラーで、最後のアイテムが次の横列に押し出されてしまうのを阻止するために右側にフロートさせることを望むかもしれません。これは単に小数点を切り上げるブラウザを偶然発見するだけです。

グリッドの崩壊

小数点の四捨五入のエラーで、最後のアイテムが押し出される

コードにすると、こんな感じです。

グリッドが横一列だけであれば、このコードで問題はありません。

しかし、横二列以上であると、下記のように表示されてしまいます。

グリッドの崩壊

横二列以上だと、うまくいかない

私がこのコードで必要としていることは、右端のアイテムから最後の溝を削除することです。それを実現するためのベストな方法は、「nth-child()」を使うことです。

これで溝をmarginとして、、カラムの片側に配置することが実装できました。
下記ページで、実装されたデモを試すことができます。

サイトのキャプチャ

デモページ

メモ: calc()はIE8とOpera miniでは機能しません。この2つのブラウザをサポートする必要がある場合は、他の方法を検討してください。

方法 2: カラムの片側に配置(padding)

方法 1のmarginで実装したように、この方法ではpaddingプロパティを使って、溝を実装します。ここでも同様に、溝を右側に配置して、実装します。

下記の図に従って、カラムの幅を計算し直します。

実装のイメージ

幅を計算する方法が、marginとは異なっていることに気がつくでしょう。これは「box-sizing: border-box;」を指定してるため、幅の中にパディングが含まれるからです。

この場合、3つのカラムのうち2つが最後の1つより大きい幅になり、計算ができない状態になっています。

私はこの方法を試すことさえお勧めしません。
もしこの複雑な計算式に挑戦するなら、自己責任で試してみてください。

方法 3: カラムの両側に半分ずつ配置(margin)

この方法では溝を2等分し、marignプロパティを使って、溝をカラムの左と右に半分ずつ配置します。コードは、下記のようになります。

下記の図に従って、カラムの幅を計算し直します。

実装のイメージ

方法 1で使った計算式と同様に、calc()を使って計算する必要があります。
この場合、カラムの幅を得るために、100%の幅から溝3つ分を除き、それを3等分します。

できました。
この溝を半分ずつ配置する方法は、複数行のグリッド用に余計な作業をする必要はありません。
下記ページで、実装されたデモを試すことができます。

サイトのキャプチャ

デモページ

方法 4: カラムの両側に半分ずつ配置(padding)

方法 3のmarginで実装したように、この方法では溝を2等分し、溝をカラムの左と右に半分ずつ配置します。使うのは、marignの代わりにpaddingを使います。

下記の図に従って、カラムの幅を計算し直します。

実装のイメージ

方法 2のpaddingとは異なり、計算式が簡単であることに気がつきましたか?
そうです、すべてのブレイクポイントでグリッドの幅の3分の1になります。

下記ページで、実装されたデモを試すことができます。

サイトのキャプチャ

デモページ

次に進む前に、このpaddingで溝を半分にする方法を使う時に注意点があります。上記のデモページでHTMLを見ると分かりますが、「.grid-item」のdiv要素内にdiv要素が加えられています。もしコンポーネントに背景やボーダーを含むなら、この余分なdiv要素が必要になります。

これは、背景がpaddingプロパティに表示されるためです。
背景と他のプロパティの関係は、下記の図のようになります。

背景と他のプロパティの関係

背景はpaddingプロパティに対して表示されます。

溝の実装はどの方法を使う?

私が2年ほど前にグリッドをコード化し始めたときは、ほとんどがトップダウンのアプローチで設計され、ハイブリッドのシステムで構築されたグリッドをコードにしていました。その際、カラムの幅と溝は%を使用していました。

その時の実装方法は、溝をグリッドの片側に配置するシンプルさが好きでした。また数学が苦手というのも理由の一つです。溝を半分に計算するのは、面倒な作業です。

溝を片側に配置するには、右端のアイテムの処理に頭を悩ませましたが、「nth-child()」を使うことで解決しました。また、モバイルファーストのCSSを書くことの重要性も学びました。どちらの問題も新人さんに、そして経験豊富な開発者にとって大きな障害となっています。

しかし今あなたが私にどの方法を選択するか尋ねたら、溝を半分にする方法を選びます。なぜなら、CSSがとても簡単だからです。またよりクリーンなマークアップのために、marginを使う方法を好みます
しかし、marginよりpaddingで計算する方が簡単です。そのため、以下はpaddingを使う方法で残りを進めます。

Step 6: デバッグ用のグリッドを作成

レイアウトをデバッグする際に、管理するためのグリッドを用意しておくことが特に役立ちます。それがあると、正しいレイアウトを作成していることを確認できます。

この時点で、私はデバッグ用のグリッドを作成するための時代遅れの方法しか知りません。
まずは、HTMLでエレメントを用意します。

デバッグ用のグリッドために、CSSも用意します。
ここではマークアップを減らすために、溝をmarginとして、カラムの両側に半分ずつ配置します。

下記ページで、実装されたデモを試すことができます。

サイトのキャプチャ

デモページ

※最新の他の方法
極端な例ですが、デバッグ用のグリッドにSVGを使うこともできます。
参考: grid image threeish style
これのすごいところは、デバッグ用のグリッドを作成する関数を使用できることです。

Step 7: レイアウトのバリエーションを作成

このステップではいよいよ、コンテンツに基づいてレイアウトのバリエーションを作成します。ここが、CSSグリッドシステムの輝くところです。複数のグリッド用のclassを作成してレイアウトを作成するのではなく、レイアウトのために合理的な名前を作ることができます

例えば、ゲスト記事でのみ使用されるグリッドレイアウトがあるとします。デスクトップ上では、下記の図のように表示されます。

ゲスト記事用のグリッドレイアウト

ゲスト記事用のグリッドレイアウト

このゲスト記事用のレイアウトのためのマークアップは下記のようになります。

カラムは12個で、1つの幅は8.333%(100÷12)です。

「.l-guest」の幅は2カラム分で、8.333%が2つです。簡単ですね。残りもその繰り返しです。

ここでは、Sassのようなプリプロセッサを使用することをお勧めします。これは、計算を手動で行うのではなく、percentage関数で列の幅を簡単に計算できるようにします。

下記ページで、実装されたデモを試すことができます。

デモのキャプチャ

デモページ

コードが反復して利用されていることに気がついたでしょう。反復部分のコードを「.grid-item」のような別セレクタにまとめることで、より良いコードにすることができます。

コードが美しく、簡潔になりました。

Step 8: レイアウトをレスポンシブ対応に

最後のステップで、レイアウトをレスポンシブ対応にします。
さきほどのゲスト記事用のレイアウトが、どのように変化するか見てみましょう。

レイアウトの変化

ゲスト記事用のレイアウトが異なるビューポートでどのように変化するか

ゲスト記事用のマークアップは、変更すべきではありません。すでにアクセシブルなレイアウトになっています。
変更するのは、CSSであるべきです。

レイアウトをレスポンシブ対応にするためにCSSを書くときには、コードをよりシンプルに、そしてより整理できるので、モバイルファーストでCSSを書くことを強く勧めます。

さっそく、スマホ向けのレイアウトのためにCSSを書くことから始めます。

スマホでは、すべてのコンポーネントがデフォルトでいっぱいの幅で表示されるので、私たちは何もする必要はありません。しかし要素をお互いから分離するために、最後の2つのアイテムに「margin-top」を加えました。

続いて、タブレット向けのレイアウトに進みます。

このレイアウトでは、ブレークポイントを700pxにします。
「.l-guest」は12カラムのうちの4つ分で、「.l-main」と「.l-sidebar」はそれぞれ12カラムのうちの8つ分です。

「.l-main」は「.l-guest」と一直線に並んでいるので、「.l-main」から「margin-top」を取り除く必要があります。

同様に「.l-sidebar」を8つ分に指定すると、最初の横行に十分な空きがないため、自動的に2行目にフロートされます。「.l-sidebar」が2行目にあり、所定の位置に戻すために、左マージンを追加する必要があります。その代わりに、それを右にフロートさせることができます(計算する必要がないので、右にフロートさせます)。

最後に、グリッドのアイテムをフロートさせているので、グリッドのコンテナにそれ自身の子をクリアするためのclearfixを含める必要があります。

最後に、デスクトップ向けのレイアウトです。

デスクトップ向けのブレークポイントを1,200pxとします。
「.l-guest」は12カラムのうちの2つ分、「.l-main」は7つ分、「.l-sidebar」は3つ分です。

わたし達が行うことは、各グリッドのアイテム内に新しいメディアクエリを作成し、必要に応じて幅を変更することです。
「.l-sidebar」から「margin-top」を取り除く必要があることを忘れないように。

最終的なレイアウトを下記ページで、試すことができます。

サイトのキャプチャ

デモページ

Susyでもこれらを実装することができます。
参考: Understanding Gutter Positions in Susy

最後に

長い論文でした。
私はこの論文を書いていて、3回果てました。ここまで読んでくださって、本当にありがとうございます。あなたがこれを読んで、3回果てないことを願っています!

この論文で分かるように、レスポンシブ対応のグリッド システムを作成する手順は比較的簡単です。混乱するとしたら、Step 5の溝をどの方法で実装するか、Step 8のレスポンシブ対応でしょう。

Step 5は可能な方法すべてを検討すると、実はシンプルです。わたし達は一緒に学びました。
Step 8はモバイルファーストのCSSを記述する知識が十分あれば、簡単に解決できます。
参考: How To Write Mobile-first CSS

この論文で、あなた自身用のレスポンス対応のグリッド システムを構築するための知識が得られたことを祈っています。
私はあなたが次のプロジェクトのためにグリッドを作ることを期待しています。

その時がくるまで!

top of page

©2017 coliss