株式会社グローバルゲート公式ブログ

CSS Gridでいろいろなレイアウトを作ってみた

こんにちは。株式会社グローバルゲート制作部のモーリーです。 
 
当ブログのリニューアルオープンから早3年となりました。ネタ探しで苦労することもありますが、当社サイトを含めて順調にアクセスは伸び、ブログを契機とした当社商品・サービス導入のご相談やWebサイト制作についてお問い合わせもいただき感謝いたしております。
当社で働きたいというデザイナーやエンジニアの方からのお問い合わせをいただくこともあり、同業の方からそのように思っていただけるのは光栄なことだと思います。
 
企業がブログの運営をすることについては、記事を書く時間や人員の確保など及び腰になることもあると思います。
執筆内容についても完全に放任というわけにもいきません。ですが技術的な内容なら社員のスキルアップにつながり、ゆるふわな内容であっても自社の人となりをお客様に知ってもらうというメリットがあり決して無駄にはならないでしょう。ただ、ブログは定期的に更新することで効果が発揮されますので、とにかく継続して更新することが大切です。 
 
そんなわけで、リニューアル4年目の当ブログも硬軟交えつつお届けできればと思います。よろしくお願いします。 
 
 

 
さて、今回はCSS Gridについて実際のWebサイトでもよく使われるレイアウトの作成方法を例としてご紹介したいと思います。 
 
CSS Gridはdisplay: gridを指定することで要素内を縦横に区切って配置することができるプロパティです。 
CSSのレイアウト手法ではこれまで横か縦一方向だけを制御する方法が主でしたが、CSS Gridは縦と横の2次元を制御してレイアウトを実装します。 
タグを入れ子にすることなく複雑なレイアウトを作ることができるため、HTMLの管理やSEO対策にも効果を発揮することができます。

従来よく使われていたレイアウトの手法

CSS Gridの説明の前に、これまで使用されてきたレイアウトの手法についてご紹介したいと思います。 

table 

<table>によるレイアウト構築の例

インターネットが普及しはじめた初期のころに用いられていた方法で、表を表示する<table>タグを用いて画像をジグソーパズルのように細切れにしてマス目に配置したり、大きなtableの中にさらにtableを詰め込んでレイアウトを構築していました。

本来「表」のためのタグである<table>をレイアウトのために用いるというのは適切でなく、CSSによる装飾の自由度もあまりない、ということで現在は廃れた手法ですが、CSS Gridの考え方は<table>に似ている部分もあります。

float

floatは要素を右や左に寄せる指定です。
単なる行揃えと異なり、寄せることで生まれた余白には後に続くコンテンツが回り込むことになります。
かつてはこの指定を使い、カラム型のレイアウトを作成していました。

Internet Explorerにはfloatを指定された要素の解釈で多くのバグがあり、キャリアの長いWeb技術者はfloatの問題に苦しんだ経験を持つ人が多いです。

floatによるレイアウト構築の例

FlexBox

FlexBoxの例

FlexBoxは現在でも使用されている手法です。
display: flexを指定することで配下要素を横や縦に並べることができます。

単に並べるだけでなく、配下要素の幅を自動的に調整したり折り返したりCSSのみで順番を並べ替えたりと柔軟なレイアウトをつくることができました。
作りたいレイアウトによってCSS GridとFlexBoxを使い分けたり、併用したりすることが多いです。

基本的な考え方 

では、CSS Gridの基本についてご説明します。 
 
まず親要素に対し、display: gridを指定します。 
そうするとこの要素はグリッドとなります。 

div { 
 display: grid; 
}

次に、このグリッドをどのように分割するかを指定します。 
列の分割数はgrid-template-columns、行の分割数はgrid-template-rowsというプロパティで指定します。 
 
たとえば、4✕3に区切りたい場合は以下のように指定します。 
1fr」というのは余ったスペースを比率で指定する単位です。 

div { 
 display: grid; 
 grid-template-columns: 100px 1fr 1fr 100px; 
 grid-template-rows: auto auto auto; 

/* 同一の値を繰り返す場合はrepeatという記述が使えます。 */ 
 
div { 
 display: grid; 
 grid-template-columns: 100px repeat(2,1fr) 100px; 
 grid-template-rows: repeat(3,auto); 
}

これだけで内部の要素は4✕3のグリッドに沿って配置されます。 
親要素にプロパティを指定するだけで済むという簡単さはFlexBoxにはない利点です。 

Chrome/Firefoxの開発者ツールを使うとCSS Gridを視覚的にわかりやすく確認することができます。

よく使われるレイアウトを実装してみる 

それでは実際にWebサイトで頻出するレイアウトをCSS Gridを用いて構築してみましょう。 

デモページを作成しましたのであわせてご覧ください。

左側が固定幅、右側は可変幅の2カラム

かつてはよく見られた2カラムのレイアウトを作ってみます。 

HTML

<div class="grid grid-2clm"> 
    <div class="bg-red"> 
        サイドカラム(固定幅200px) 
    </div> 
    <div class="bg-green"> 
        メインカラム(余った幅全部) 
    </div> 
</div>

CSS

.grid-2clm { 
    grid-template-columns: 200px 1fr; 
}

※.gridにはdisplay:gridのみ指定してあります。以下の見本でも同様です。 

全体を2列のグリッドとし、1列目を固定幅、2列目をfrによって可変幅とします。 
CSSは1行だけ、HTMLも最小限で済むのでとても簡単です。 

両サイド固定の3カラム

似たパターンで3カラムのレイアウトを作ってみます。 
こちらも両サイドのカラムは固定幅、中央を可変とします。 

HTML

<div class="grid grid-3clm"> 
    <div class="bg-red"> 
        左カラム(固定幅150px) 
    </div> 
    <div class="bg-green"> 
        メインカラム(余った幅全部) 
    </div> 
    <div class="bg-blue"> 
        サイドカラム(固定幅150px) 
    </div> 
</div>

CSS

.grid-3clm { 
    grid-template-columns: 150px 1fr 150px; 
}

3行必要なのでgrid-template-columnsの値も3つになりました。 

聖杯レイアウト

3カラムにヘッダーとフッターがついたレイアウトです。現在でも情報量の多いポータルサイトでよく見られます。 
かたちが盃に見えることから聖杯レイアウト(英語でHoly Grailとも)と呼ばれています。 

HTML

<div class="grid grid-hg"> 
    <div class="bg-orange clmn-header"> 
        ヘッダー 
    </div> 
    <div class="bg-red"> 
        左カラム(固定幅150px) 
    </div> 
    <div class="bg-green"> 
        メインカラム(余った幅全部) 
    </div> 
    <div class="bg-blue"> 
        サイドカラム(固定幅150px) 
    </div> 
    <div class="bg-orange clmn-footer"> 
        フッター 
    </div> 
</div> 

CSS

.grid-hg { 
    grid-template-columns: 150px 1fr 150px; 

 
.clmn-header, 
.clmn-footer { 
    grid-column: 1 / 4; 
}

親要素のグリッドは3カラムと同じですが、ヘッダーとフッターは列をまたいで配置されないといけません。 
その場合は列をまたぎたい子要素にgrid-columnというプロパティを指定します。 
 
上記の例のように1/4と指定した場合、1列目から4列目までを占めるように配置されます。 
グリッドの開始位置と終了位置を指定します。 
エクセルのセル結合を想像すると分かりやすいかもしれません。 
 
行をまたぐ場合(縦方向に結合する場合)、grid-rowという指定になります。 

左写真、右テキスト、下揃えでボタン

左に写真があり、右に文字、そして文字の最下段にリンクを設置するレイアウトです。 

HTML

<div class="grid grid-photo"> 
    <div class="clmn-photo"> 
        <img src="https://placehold.jp/3d4070/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
    </div> 
    <div class="clmn-text"> 
        説明文が入ります。説明文が入ります。説明文が入ります。説明文が入ります。説明文が入ります。 
    </div> 
    <div class="clmn-button"> 
        <a href="#">ボタン</a> 
    </div> 
</div>

CSS

.grid-photo { 
    grid-template-columns: 1fr 1fr; 
    grid-template-rows: 1fr auto; 
    grid-gap: 0 1rem 

 
.clmn-photo { 
    grid-row: 1 / 3; 
}

この場合は2✕2のグリッドを定義し、写真側は縦方向に結合するという考え方で作成します。 
grid-template-rows1fr autoと指定することで、2行目(リンクボタンが来るグリッド)の高さを最小限に、テキストが入るグリッドの高さを余った分だけというレイアウトが実現できます。

写真の左右を入れ替える

このようなレイアウトを複数並べる場合、写真の位置を左右で互い違いに配置したくなるでしょう。 
その場合は写真が入るグリッドの開始位置を2列目からはじまるようにします。 

CSS

.grid-photo-reverse .clmn-photo { 
    grid-column: 2 / 3; 
}

grid-column/grid-rowは列・行をまたぐための指定のほか、開始位置をずらすための役割もあります。 

左大バナー、右小バナー✕4

左側に大きなバナーを配置し、右側に高さ1/4となる小さなバナーを配置するレイアウトです。 
マガジンスタイルと呼ばれる密度の高いWebサイトやショッピングサイトで見かけることがあります。 

HTML

<div class="grid grid-banner"> 
    <div class="clmn-banner-l"> 
        <img src="https://placehold.jp/3e7061/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
    </div> 
    <div class="clmn-banner-s"> 
        <img src="https://placehold.jp/ff61a0/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
    </div> 
    <div class="clmn-banner-s"> 
        <img src="https://placehold.jp/ff8861/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
 
    </div> 
    <div class="clmn-banner-s"> 
        <img src="https://placehold.jp/ff61a0/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
 
    </div> 
    <div class="clmn-banner-s"> 
        <img src="https://placehold.jp/ff8861/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
 
    </div> 
</div>

CSS

.grid-banner { 
    grid-template-columns: 2fr 1fr; 
    grid-auto-rows: 0.25fr 

 
.clmn-banner-l { 
    grid-row: 1 / 5 

 
.clmn-banner-s { 
    overflow: hidden; 

 
.clmn-banner-s img { 
    object-fit: cover; 
    width: 100%; 
    height: 100%; 
    object-position: center center; 
}

従来の手法では隙間なく配置することが結構難しかったのですが、CSS Gridと画像へのobject-fitというプロパティを使うことできれいに並べることができます。 
object-fitは画像のサイズを親要素内に収める(contain)か、余白ができないようにはみ出して配置するか(cover)を指定することができます。 

折り返しのある一覧

商品一覧、ショッピングサイトなどで利用頻度の高いレイアウトです。 
150pxの列を繰り返し、親要素の幅を超えたら折り返します。 
auto-fillは要素が足りない場合(3行で子要素が5個の場合など)、足りない部分に架空のグリッドを配置する指定です。

HTML

<div class="grid grid-list"> 
    <div class="clmn-list"> 
        <img src="https://placehold.jp/ff8861/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
        あいうえお 
    </div> 
    <div class="clmn-list"> 
        <img src="https://placehold.jp/ff8861/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
        あいうえお 
    </div> 
    <div class="clmn-list"> 
        <img src="https://placehold.jp/ff8861/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
        あいうえお 
    </div> 
    <div class="clmn-list"> 
        <img src="https://placehold.jp/ff8861/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
        あいうえお 
    </div> 
    <div class="clmn-list"> 
        <img src="https://placehold.jp/ff8861/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
        あいうえお 
    </div> 
</div>

CSS

.grid-list { 
    grid-template-columns: repeat(auto-fill, 150px); 
    grid-gap: 20px; 

 
.clmn-list { 
    padding: 10px; 
    border: 1px solid #ddd; 
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); 
    border-radius: 4px; 
}

grid-gapという指定で行列間の余白を指定することができます。 
簡単そうに見えますが、子要素すべてにmarginを指定すると最終列や最終行でズレが生じますので、従来はnth-childを駆使したり親要素にマイナスのマージンを設定したりと苦労していました。

隙間なくランダムなサイズの画像を敷き詰める

写真家やイラストレーターのサイトで見かけるテクニックです。
アニメーションをあわせて設定すればインパクトのあるWebサイトになります。

HTML

<div class="grid grid-tile"> 
    <div class="clmn-tile"> 
        <img src="https://placehold.jp/40baa2/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
    </div> 
    <div class="clmn-tile"> 
        <img src="https://placehold.jp/3d4070/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
    </div> 
    <div class="clmn-tile"> 
        <img src="https://placehold.jp/3e7061/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
    </div> 
    <div class="clmn-tile"> 
        <img src="https://placehold.jp/3e7061/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
    </div> 
    <div class="clmn-tile"> 
        <img src="https://placehold.jp/40baa2/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
    </div> 
    <div class="clmn-tile"> 
        <img src="https://placehold.jp/ff61a0/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
    </div> 
    <div class="clmn-tile"> 
        <img src="https://placehold.jp/ff61a0/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
    </div> 
    <div class="clmn-tile"> 
        <img src="https://placehold.jp/40baa2/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
    </div> 
    <div class="clmn-tile"> 
        <img src="https://placehold.jp/3d4070/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
    </div> 
    <div class="clmn-tile"> 
        <img src="https://placehold.jp/3e7061/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
    </div> 
    <div class="clmn-tile"> 
        <img src="https://placehold.jp/ff8861/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
    </div> 
    <div class="clmn-tile"> 
        <img src="https://placehold.jp/ff61a0/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
    </div> 
    <div class="clmn-tile"> 
        <img src="https://placehold.jp/3e7061/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" class="fluid"> 
    </div> 
</div>

CSS

.grid-tile { 
    grid-template-columns: repeat(4, 1fr) 

 
.clmn-tile:nth-child(5n - 4) { 
    grid-row: auto / span 2; 
    grid-column: auto / span 2; 

 
.clmn-tile:nth-child(5n - 1) { 
    grid-row: auto / span 2; 

 
.clmn-tile img { 
    width: 100%; 
    height: 100%; 
    object-fit: cover; 
    object-position: center; 

まずは4列の均等幅グリッドを作成します。 
そして子要素が5個おきに(nth-child(5n - 4))2行2列分のサイズになるように指定します。 
さらに4個おき(nth-child(5n - 1))1行2列のサイズになるように指定します。 

画像サイズについてはランダム感を出すと面白さが出ると思います。
 
子要素内の画像はobject-fitを用いて隙間が出ないようにします。

CSSだけで順番反転

CSS Gridの子要素はorderというプロパティを指定することで順番を変更することができます。 
その機能を利用して、CSSだけで順番を反転させる方法です。

HTML

<input type="checkbox" name="sort" id="sort"> 
<label for="sort"> 
    順番を入れ替える 
</label> 
<div class="grid grid-sort"> 
    <div class="grid clmn-sort"> 
        <div>1</div> 
        <div><img src="https://placehold.jp/40baa2/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" 
                class="fluid"></div> 
        <div>これは1の商品です。</div> 
    </div> 
    <div class="grid clmn-sort"> 
        <div>2</div> 
        <div><img src="https://placehold.jp/3d4070/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" 
                class="fluid"></div> 
        <div>これは2の商品です。</div> 
    </div> 
    <div class="grid clmn-sort"> 
        <div>3</div> 
        <div><img src="https://placehold.jp/ff8861/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" 
                class="fluid"></div> 
        <div>これは3の商品です。</div> 
    </div> 
    <div class="grid clmn-sort"> 
        <div>4</div> 
        <div><img src="https://placehold.jp/3e7061/ffffff/600x600.png?text=%E7%94%BB%E5%83%8F" 
                class="fluid"></div> 
        <div>これは4の商品です。</div> 
    </div> 
</div>

CSS

.grid-sort { 
    grid-template-columns: 1fr; 

 
.clmn-sort { 
    grid-template-columns: auto 100px 1fr; 
    align-items: center; 
    grid-gap: 1rem; 

 
.clmn-sort+.clmn-sort { 
    border-top: 1px solid #ddd; 

 
 
#sort:checked~.grid-sort .clmn-sort:nth-child(1) { 
    order: 4; 

 
#sort:checked~.grid-sort .clmn-sort:nth-child(2) { 
    order: 3; 

 
#sort:checked~.grid-sort .clmn-sort:nth-child(3) { 
    order: 2; 

 
#sort:checked~.grid-sort .clmn-sort:nth-child(4) { 
    order: 1; 
}

すべての子要素に対してorderを指定しないといけないのでちょっと大変で、さらに単純な反転でしかないので実用性はないかもしれません。
まぁこんなこともできるということで…。

まとめ

ということで、今回は最近採用率が増えつつあるCSS Gridによるレイアウト手法を実例を交えてご紹介しました。 
実際に使ってみてもシンプルなHTMLで複雑なレイアウトを実現できるというメリットは大きく、今後は私自身も積極的に使っていこうと思いました。 
 
ブラウザがアップデートされるたびにCSSの機能は現在進行系で増え続けています。 
私達も新しい情報をキャッチしつつ、実務で使えるように日々勉強しつつ、ご依頼いただいたWebサイトのクオリティを上げていけるようにがんばります。

【関連記事】

ご相談・お問い合わせ

当社サービスについてのお問い合わせは下記までご連絡下さい。

お電話でのお問い合わせ

06-6121-7581 / 03-6415-8161