CSS グリッドレイアウトはいいぞ


[![thumbnail](https://files.speakerdeck.com/presentations/dc9034da963d4fc68ce9fb28c94d0001/slide_0.jpg?16172624)](https://speakerdeck.com/yotahada3/cssguritudoreiautohaiizo)
↑社内LTで喋った時のスライド
https://speakerdeck.com/yotahada3/cssguritudoreiautohaiizo

`display: flex:`はめちゃめちゃ使ってたが grid 使ったことなかったなぁと思い、今更ながら調べてみた

## 結論

**grid-template-areas は神**
css ライブラリにあるグリッドシステムに頼らなくても簡単に実装できるぞ！！

## 注意事項

雑多にまとめたので、少し助詞・副詞が足りてない部分があります
この記事に書いてあることはググれば大体出てきます
[ここら辺](https://qiita.com/yotahada-nus3/items/b9a20ba26eb69c1c6f43#%E4%B8%8B%E8%A8%98%E3%81%AF%E5%85%A8%E9%83%A8%E5%90%8C%E3%81%98%E3%83%AC%E3%82%A4%E3%82%A2%E3%82%A6%E3%83%88%E3%81%AB%E3%81%AA%E3%82%8B)は全部、一緒の箇所に書かれてる記事あんまりなかったので何かの参考になる可能性がありそうな気もしたり、しなかったり

## 基本

[参考にした記事](https://developer.mozilla.org/ja/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout)

小要素の div が親要素の幅いっぱいに縦に並ぶ

```html
<div class="container">
  <div>いち</div>
  <div>に</div>
  <div>さん</div>
  <div>よん</div>
</div>
```

```css
.container {
  display: grid;
}
```

## grid-template-

明示的に小要素の幅や高さを指定する場合

### grid-template-columns

指定した大きさ分、横に小要素が並ぶ

下記の場合、`いち`、`に`が 200px で横に並び、
`さん`、`よん`は折り返されて下に 200px で横に並ぶ

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

#### fr

親要素の幅にいっぱいに指定した割合で小要素を横に並べてくれる

下記の場合、幅が 2 等分された小要素が横に並ぶ

```css
.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
}
```

fr と px 指定は両方織り交ぜて指定が可能

#### repeat()

```css
.container {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  /* grid-template-columns: 1fr 1fr; と同義 */

  /* いろんなパターンつ使える */
  /* grid-template-columns: repeat(2, 1fr 2fr); */
  /* grid-template-columns: repeat(2, 1fr) 20px; */
}
```

### grid-template-rows

grid-template-columns の高さ版

行の高さが一行目 300px, 二行目 500px, 三行目 200px になる

```css
.container {
  display: grid;
  grid-template-columns: 300px 500px 200px;
}
```

## grid-auto-

暗黙的に幅や高さを指定する場合

幅 200px 高さ 200px の小要素になる

```css
.container {
  display: grid;
  grid-auto-columns: 200px;
  grid-auto-rows: 200px;
}
```

### minmax

css の min-height や min-width と同じ感じ
子要素の高さが 100px よりも小さくならずに、大きくなると auto で広げてくれる

```css
.container {
  display: grid;
  grid-auto-rows: minmax(100px, auto);
  grid-template-columns: repeat(3, 1fr);
}
```

## グリッドの配置

`grid-column-`は横線の位置から数える
`grid-row-`は縦線の一から数える
グリッドは四角形で構成される
**L 字の形を作るには力技が必要かも**

```html
<div class="container">
  <div class="box1">いち</div>
  <div class="box2">に</div>
  <div>さん</div>
  <div>よん</div>
</div>
```

```css
.container {
  display: grid;
  grid-auto-rows: 100px;
  grid-template-columns: repeat(3, 1fr);
}

/* 幅は親要素の横幅いっぱい */
/* 高さは2行分 100px * 2 = 200px */
.box1 {
  grid-column-start: 1;
  grid-column-end: 4;
  grid-row-start: 1;
  grid-row-end: 3;
}

/* 幅は親要素を三等分した時の1/3 */
/* 高さは2行分 100px * 2 = 200px かつ 3行目から始まる */
.box2 {
  grid-column-start: 1;
  grid-column-end: 2;
  grid-row-start: 3;
  grid-row-end: 5;
}
```

## グリッドの間隔

グリッドの間の横線(`column-gap`)でも指定できるし
縦線(`row-gap`)でも指定できる
両方(`gap`)もいける

```css
.container {
  display: grid;
  grid-auto-rows: 100px;
  grid-template-columns: repeat(3, 1fr);
  gap: 3px;
  /* column-gap: 3px;
  row-gap: 1px; */
}
```

## grid のネスト

```html
<div class="container">
  <div class="box1">
    <div>いちのいち</div>
    <div>いちのに</div>
    <div>いちのさん</div>
  </div>
  <div>に</div>
  <div>さん</div>
  <div>よん</div>
</div>
```

```css
.container {
  display: grid;
  grid-auto-rows: 100px;
  grid-template-columns: repeat(3, 1fr);
}

.box1 {
  grid-column-start: 1;
  grid-column-end: 4;
  grid-row-start: 1;
  grid-row-end: 3;
  /* box1の横幅を三等分にしたbox1の子要素が並ぶ  */
  display: grid;
  grid-auto-rows: 100px;
  grid-template-columns: repeat(3, 1fr);
  /* gapも継承されない */
  gap: 3px;
}
```

## z-index

z-index 使って重なり順を指定できるよ

```html
<div class="container">
  <div class="box1">いち</div>
  <div class="box2">に</div>
  <div>さん</div>
  <div>よん</div>
</div>
```

```css
.container {
  display: grid;
  grid-auto-rows: 100px;
  grid-template-columns: repeat(3, 1fr);
}

/* 幅は親要素の横幅いっぱい */
/* 高さは2行分 100px * 2 = 200px */
.box1 {
  grid-column-start: 1;
  grid-column-end: 4;
  grid-row-start: 1;
  grid-row-end: 3;
  z-index: 1;
}

/* 幅は親要素を三等分した時の1/3 */
/* 高さは2行分 100px * 2 = 200px かつ 2行目から始まる */
/* 2行目はbox1のがz-index上なのでbox2が見えない */
.box2 {
  grid-column-start: 1;
  grid-column-end: 2;
  grid-row-start: 2;
  grid-row-end: 4;
}
```

## flex vs grid

行又は列のみによってレイアウトを制御する必要がありますか → `display: flex;`
行及び列によりレイアウトを制御する必要がありますか → `display: grid;`

## grid-template-area

[参考にした記事](https://qiita.com/kura07/items/e633b35e33e43240d363#%E3%82%B9%E3%83%86%E3%83%83%E3%83%97%EF%BC%93---%E6%96%B9%E6%B3%95%EF%BD%82-%E3%82%A8%E3%83%AA%E3%82%A2%E3%81%AB%E5%90%8D%E5%89%8D%E3%82%92%E4%BB%98%E3%81%91%E3%81%A6%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B)

`grid-template-row`と`grid-template-columns`を明示的に表した感じのもの

`.`が一つ以上ある場合、空とみなされる

```
  grid-template-areas:
    "Box1 Box1 Box1"
    "Box1 Box1 Box1"
    "Box2 Box3 Box4"
    "Box2 Box5 ....";
```

```html
<div class="container">
  <div class="box1">いち</div>
  <div class="box2">に</div>
  <div class="box3">さん</div>
  <div class="box4">よん</div>
  <div class="box5">よん</div>
</div>
```

### 下記は全部同じレイアウトになる

```css
.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 100px;
  gap: 3px;
}

.box1 {
  grid-column-start: 1;
  grid-column-end: 4;
  grid-row-start: 1;
  grid-row-end: 3;
}

.box2 {
  grid-column-start: 1;
  grid-column-end: 2;
  grid-row-start: 3;
  grid-row-end: 5;
}
```

`grid-area: grid-row-start / grid-column-start / grid-row-end / grid-column-end;`
的な指定もできる

```css
.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 100px;
  gap: 3px;
}

.box1 {
  grid-area: 1 / 1 / 3 / 4;
}

.box2 {
  grid-area: 3 / 1 / 5 / 2;
}
```

```css
.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 100px;
  grid-template-areas:
    "Box1 Box1 Box1"
    "Box1 Box1 Box1"
    "Box2 Box3 Box4"
    "Box2 Box5 ....";
  gap: 3px;
}

.box1 {
  grid-area: Box1;
}

.box2 {
  grid-area: Box2;
}

.box3 {
  grid-area: Box3;
}

.box4 {
  grid-area: Box4;
}
```