Grid Layout


 Webデザインを始めると、まずレイアウトの問題に遭遇します。当初は、htmlのTABLEに依ったり、cssのfloatを使ってレイアウトしていました。
 しかし floatを使ったレイアウトはブラウザの違いなどによっては、段組が崩れてしまうなどするため、初心者を悩ませていました。そこで Twitter社の「bootstrap」などのグリッドシステムが開発され、脚光を浴びていました。
 2012年頃からは Flexboxが登場し、そうしたグリッドシステムを使わなくとも、CSS3とHTML5で直接段組を行うことができるようになり、レイアウト問題を解決するために活用されてきました。しかし、Flexboxでのレイアウトも、万能ではありませんでした。
 CSSグリッドレイアウトはそうした「1次元レイアウト」をベースとしたレイアウトとは違って、「2次元レイアウト」を採用し、Flexboxで起こる回り込みの不都合を解消するようになりました。

■ Grid Layoutの具体例

 Grid Layoutについて、A~Fの6個のブロックで構成される下記の具体例で説明します。
  1. Grid Layoutで配置するために、親要素に display: grid; (又は display: inline-grid;)を記述した後、grid:~; (又は grid-template:~; grid-template-rows:~;等) で [ライン番号やエリア配置を記述して] 具体的なレイアウトを記述します。(下図)
    *この例では、row方向(縦)に 40px,3rem、column方向(横)に 50px,4rem,1fr, 2frで並ぶセルを、row方向(縦)に 8px、column方向(横)に 4pxの間隔で配置します。
  2. 子要素では、
     ◆ grid-row:1 / 2; grid-column:1;のようにラインの番号を記述して、前記のグリッド枠内の個別の配置位置を指定したり、
      *この例では、子要素 .itemAを row grid 1-2間; column grid 1の後に配置する…などと記述しています。なお、各要素の記述順位は特に問われません。
     ◆ grid-template-areas: "aa bb" "cc dd";のようにエリア配置を記述して、前記のグリッド枠内の個別の配置位置を指定したりします。
  3. このように、grid線で親要素のマス目構成を設定し、その中に子要素を具体的に配置してゆきます。重ねたりすることも出来ます。
      【HTML】
<div class="grid-container">
  <div class="itemA">A</div>
  <div class="itemB">B</div>
  <div class="itemC">C</div>
  <div class="itemD">D</div>
  <div class="itemE">E</div>
  <div class="itemF">F</div>
</div>
      【CSS】(ライン番号で指定の場合)
.grid-container {
  width:200px; margin:0 auto; padding:5px 3px; background:#cef;
  display: grid;      /* Grid Layoutの利用を指定 */
  grid: 40px 3rem / 50px 4rem 1fr 2fr; /* row(行)方向(縦)厚の配分/column(列)方向(横)幅の配分 */
  gap: 8px 4px;       /* row(行)方向(縦)の間隔/column(列)方向(横)の間隔 */
}
.grid-container > div {
  border: 3px solid #c99; background:#fe6; text-align: center;  /* 子要素のプロパティ */
}
 .itemA{ grid-row:1 / 2; grid-column:1 }     /* row grid 1-2間; column grid 1後に配置 */
 .itemD{ grid-row:1; grid-column:3 / 5 }     /* row grid 1後; column grid 3-5間に配置 */
 .itemE{ grid-row:2 / 3; grid-column:3 }     /* row grid 2-3間; column grid 3後に配置 */
 .itemF{ grid-row:2; grid-column:4 / 5 }     /* row grid 2後; column grid 4-5間に配置 */
 .itemB{ grid-row:2 / 3; grid-column:1 }     /* row grid 2-3間; column grid 1後に配置 */
 .itemC{ grid-row:1 / 3; grid-column:2 / 3 } /* row grid 1-3間; column grid 2-3間に配置 */
            
 【左記の 表示1 表示2】→

  対応する CSS ↓
      【CSS】(エリア配置で指定の場合)
.grid-container {
  width:200px; margin:0 auto; padding:5px 3px; background:#cef;
  display: grid;      /* Grid Layoutの利用を指定 */
  grid: 40px 3rem / 50px 4rem 1fr 2fr; /* row(行)方向(縦)厚の配分/column(列)方向(横)幅の配分 */
  gap: 8px 4px;       /* row(行)方向(縦)の間隔/column(列)方向(横)の間隔 */
  grid-template-areas:
      "areaA areaC areaD areaD"
      "areaB areaC areaE areaF";
}
.grid-container > div {
  border: 3px solid #c99; background:#fe6; text-align: center;  /* 子要素のプロパティ */
}
 .itemA{ grid-area: areaA; }     /* .itemA に エリア名 areaAを指定 */
 .itemD{ grid-area: areaD; }    /* .itemD に エリア名 areaDを指定 */
 .itemE{ grid-area: areaE; }    /* .itemE に エリア名 areaEを指定 */
 .itemF{ grid-area: areaF; }    /* .itemF に エリア名 areaFを指定 */
 .itemB{ grid-area: areaB; }    /* .itemB に エリア名 areaBを指定 */
 .itemC{ grid-area: areaC; }    /* .itemC に エリア名 areaCを指定 */
            
 以上のように各記述は、親要素に指定するものと、子要素に指定するものが有り、その組み合わせでレイアウトされます。参考1 参考2 参考3

■ Grid Layoutと Flexboxとの違い

 Grid Layoutも Flexboxも、親要素の中に子要素を配置することでは同じですが、配置方法が根本的に異なります。
1. Grid Layoutは縦横の位置や幅を指定して、2次元的にレイアウトします。
2. Flexboxは親要素の中に、子要素を一次元的な配列として並べる方法を調整してレイアウトします。
 具体的にみてみます。
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <title>Grid Layoutの例</title>
  <style>
      main { 
        width:300px; margin:0 auto; text-align:center; 
        background:#eff; font-size:20px; 
      }
      .samp-box { border: 2px solid #d66; 
        width:290px; padding:5px 3px; 
        display: grid;      /* Grid Layoutで配置 */
        grid: 1fr 1fr / 1fr 1fr 1fr; /* row(行)方向(縦)の配分/column(列)方向(横)の配分 */
        gap: 5px 4px;       /* row(行)方向(縦)の間隔/column(列)方向(横)の間隔 */
      }
      .samp-item {          /* 子要素のプロパティ */
        height:75px; background:#fe6; border-radius:15px; 
        display:flex; justify-content:center; align-items:center;  /* 孫要素を縦横の中央に配置(flexbox) */
      }
  </style>
</head>
<body>
  <main>
    <div>Grid Layoutの例</div>
    <div style="font-size:small;">(grid: gap:等で詳細指定)</div>
    <div class="samp-box">  <!-- Grid Layoutの親要素 -->
      <div class="samp-item">1</div>
      <div class="samp-item">2</div>
      <div class="samp-item">3</div>
      <div class="samp-item">4</div>
      <div class="samp-item">5</div>
    </div>
  </main>
</body>
</html>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <title>Flexboxの例</title>
  <style>
      main { 
        width:300px; margin:0 auto; text-align:center; 
        background:#eff; font-size:20px; 
      }
      .samp-box { border: 2px solid #d66; 
        width:296px;
        display:flex; /* flexboxを指定 */
        flex-flow:row wrap; /* 子要素をrow方向に並べ、折返し可 */
        justify-content:space-around; /* 並べ方向に均等な空白 */
      }
      .samp-item { 
        width:30%; height:85px; margin:5px 0;
        background:#fc9; border-radius:15px; 
        display:flex; justify-content:center; align-items:center; /* 孫要素を縦横の中央に配置 */
      }
  </style>
</head>
<body>
  <main>
    <div>Flexboxの例</div>
    <div style="font-size:small;">(flex-flow: justify-content:等で詳細指定)</div>
    <div class="samp-box">  <!-- flexboxの親要素 -->
      <div class="samp-item">1</div>
      <div class="samp-item">2</div>
      <div class="samp-item">3</div>
      <div class="samp-item">4</div>
      <div class="samp-item">5</div>
    </div>
  </main>
</body>
</html>
 このように同じようなレイアウトが出来ますが、配置の仕方が異なるので多少の特質があります。簡単に言うと、
1. Grid Layoutは、縦横の位置を 2次元的に固定したマス目に配置する場合に適しています。
2. Flexboxは子要素の一次元的な配列を並び方を調整してレイアウトするのに適しています。(この例では中央対称にしました)

■ Grid Layoutの記述法

   【親要素(コンテナ)で全体の構成を指定】 参考1  参考2  参考3
プロパティ表 示 例説 明
grid-template:
( grid: と同じ )
◆grid:(row構成 / (column構成) 等と書いて枠組みを指定。
◆grid-template-rows, grid-template-columns, grid-template-areas を纏めて指定出来ます
◆例: grid: 1fr 2fr/ 1fr 2fr 30px 1fr
   grid:[top] "a1 a1" 10px [mdl] "a2 a3" 30px [btm] / [lft] 1fr [cnt] 2fr [rht]

 注. auto-flow **:は **幅で繰り返します 参考
grid-template-rows:
 と
grid-template-columns:
◆grid-template-rowsと grid-template-columnsをそれぞれ個別に指定します
◆例1: grid-template-rows:1fr 2fr; grid-template-columns:1fr 2fr 30px 1fr
◆例2: grid-template-rows:[top] "a1 a1" 10px [mdl] "a2 a3" 30px [btm]; grid-template-columns: [lft] 1fr [cnt] 2fr [rht]
grid-template-areas: ◆grid:(grid:grid rows) / (grid columns) で枠組みを設定する
◆grid-template-areas で子要素の配置を指定します
◆各子要素には、#itm1{grid-area:name;}のように名前を付けます
◆例:
 grid-template-areas:"hd hd hd" "mn mn sd" "ft ft ft";
 #itm1{grid-area:hd;}
  *hd mn …は各子要素の名前です
grid-auto-flow:
 (参考)
◆grid:(grid:grid rows) / (grid columns) で枠組みを設定する
◆grid-auto-flow で子要素の並べ方向を指定します
◆ディフォルト値は row(横)です
◆denseを付けると空きセルを詰めて並べます

 *この例では
   アイテム1を grid-row-start:3;
   アイテム4を grid-column-start:2; と設定した
gap:
(or grid-gap:)
◆gap: で grid-row-gap と grid-column-gap をまとめて記述出来ます
◆grid-gap: y x; で row方向に並ぶ空白yと、column方向に並ぶ空白xを指定します。yのみの時は縦横両方向に同じ空白が設定されます
◆例: gap:5px 1em;
   gap:1rem;

   【個別子要素(アイテム)に設定】 参考
プロパティ表示例説 明
grid-row:
 又は
grid-column:
◆grid-templateでレイアウトを指定し、
◆子要素 itemの縦(row)、横並び(column)の表示開始、終了位置を grid(線)番号または名前で css指定します
◆grid番号は左上より 1から始まります。負数にすると逆向き指定になります
◆子要素の領域が重複すると重なって配置されます
◆記述例:
 #itm3{grid-row:2 / 3; grid-column:2 / 4}
grid-area: ◆grid-templateでレイアウトを指定し、その網目に、
◆grid-template-areasで各子要素の配置を記述します
◆記述例:
 grid-template: 20px 1fr 25px 0px/ 60px 1fr 90px
 grid-template-areas: "hd hd hd" "nv mn sd" "ft ft ft"

   【ショートハンド記述例】 (幾つかのプロパティを纏めて一括指定する) 参考1 参考2 参考3
ショートハンド具 体 例等 価 記 述 例 等
grid;grid: [line1] 1fr [line2] 40% [line3] 20% [line4] / 2fr 50px 1fr 30%; <grid-template>
grid:repeat(2, [ln1 ln2 ln3] 50px) 1fr/ auto-flow 80px;grid-template, grid-template-rows, grid-template-columns を纏め指定
grid-template;grid-template:[l1] "a" 50px [line2] "b" 1fr [l3]/ "s1" 50px "s2" 1fr "s3" 70px;<grid-template-rows> / <grid-template-columns>
grid-template:"a a ." minmax(80px, auto) "a a ." 7em "b b c" auto/ 8em 3em auto;[ <line-names> <string> <track-size> <line-names>]+[ /<explicit-track-list>]
grid-area;grid-area: 1 / 2 / 3 / 4;<grid-row-start>[/<grid-column-start>[/ <grid-row-end>[/<grid-column-end>]]]
grid-template-rows;grid-template-rows:[l1] 2fr [l2] 8px [ln3]; grid-template-rows:1fr min-content;[ <line-names> [ <track-size> | <track-repeat> ] ]+ <line-names> など
grid-template-columns;grid-template-columns: [line8] 5rem [ln2] 8rem [ln3];上に同じ
grid-template-areas;grid-template-areas: "header header" "menu main" "footer footer";<string>
grid-rows;grid-rows: 1 / 3;縦(row)方向の開始 / 終了位置を指定
grid-columns;grid-columns: 1 / 3;横(column)方向の開始 / 終了位置を指定
gap; (grid-gap;)gap: 3rem 5px;row-gap:3rem; column-gap:5px;
grid-row;grid-row:3; grid-row:2 / 4; grid-row:span 2 / 7;<grid-row-start> [ / <grid-row-end>]など {アイテムを指定する}
grid-column;grid-column:3; grid-column:2 / 4; grid-column:span 2 / 7;<grid-column-start> [ / <grid-column-end>]等 {アイテムを指定する}

   【幅等の記述方法】
単位説 明記述例
fr(%)幅(高さ)を係数比率(%)で按分grid-template-columns:[line1] 1fr [line2] 40% [line3];、 grid:3fr 2fr/2fr 1fr 30%;
px(em,rem)幅(高さ)をピクセル(em,rem)単位で配分grid-template-rows:50px 3rem;、 grid:2rem 80px 1fr/2em 1fr 100px;
span nspan n個分grid-column: span 2 / 7;
calc( fx )計算式 fxで指定gap:calc( 1% + 2px );
min-contentコンテンツの最小サイズにするgrid-template-rows: 1.5fr min-content;
max-contentコンテンツの最大サイズにするgrid-template-columns: max-content 2fr 1fr;
minmax(n,m)n 以上 m 以下の範囲で自動調整grid-template-columns: minmax(100px, 1fr);
autoサイズを自動調整minmax(min-content,max-content)と同じ
fit-content(m)最大でも m のサイズにしますfit-content(100px)
repeat
auto-fit(auto-fill)
繰り返しを指定grid-template-columns: repeat(2, 40px) repeat(2, 2rem);
子要素個数分自動生成grid-template-columns: repeat(auto-fit, 3rem);、grid-template-rows: repeat(auto-fill, 2rem);
grid-row-startなど縦(row)方向の開始(start)位置を指定grid-row-start:2;  {grid-row-end、grid-column-start、grid-column-endも同様}
grid-column-endなど横(column)方向の終了(end)位置を指定grid-column-start:2;  {grid-column-start、grid-row-start、grid-row-endも同様}
grid-row (or column)縦(row)方向の開始 / 終了位置 などを指定grid-row: 2 / 4; grid-row: span 2 / 7;  {grid-columnも同様}
grid-areaセルを指定。セル位置を指定grid-area: 1 / 3 / 2 / 4; {<grid-row-start> [ / <grid-column-start> [ / <grid-row-end> [ / <grid-column-end>}
justify-selfjustify-self:center;コンテナ内のアイテムの主軸方向の揃え位置を指定。参考
align-selfalign-self:center;コンテナ内のアイテムの交差軸方向方向の揃え位置を指定。参考
z-indexz-index:10;重なるセルの重なり順位を指定。参考
orderorder: 2;各アイテムの配列順位を記述。参考

■ 色々なサンプル

  【レイアウトサンプル-1】 レスポンシブルにも対応した入り組んだサンプルです 【拡大表示
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <style>
    .container {
      display: grid;
      gap: 2px 6px;
      grid: 120px 80px 2fr 100px auto / 1.5fr 1fr 100px 3fr ;
    }
    .item {
      background: #fcc;
      padding: 10px;
      border-radius: 8px;
      border: 2px solid #600;
      opacity:0.5;
    }
    .box-big1 {
      grid-row: 1 / 4;
      grid-column: 1 ;
      background: #fc2;
    }
    .box-big2 {
      grid-column: 3 / 5;
      background: #0bd;
    }
    .box-big3 {
      grid-row: 3 / 5;
      grid-column: 2 / 4;
      background: #c6c;
    }
    .box-big4 {
      grid-column: 1 / 5;
      background: #0ba;
    }

    @media (max-width: 600px){
      .container {
        grid: auto / 1fr;
      }
      .box-big1, .box-big2, .box-big3, .box-big4 {
        grid-row: auto;
        grid-column: 1;
      }
    }
  </style>
</head>
<body>
<div class="container">
  <div class="item box-big1">A1</div>
  <div class="item">B</div>
  <div class="item">C</div>
  <div class="item">D</div>
  <div class="item">E</div>
  <div class="item box-big2">F2</div>
  <div class="item box-big3">G3</div>
  <div class="item">H</div>
  <div class="item">I</div>
  <div class="item">J</div>
  <div class="item box-big4">K4</div>
</div>
</body>
</html>

 【レイアウトサンプル-2】
  メニュー付きレスポンシブルページです 【動作例
 【レイアウトサンプル-3】
  自動折返しグリッドページです 【動作例

■ 参考サイト