gridでつくる不揃いの画像ギャラリー

# はじめに

画像ギャラリーをgridで実装しました。
7枚の画像が不揃いに並んでいるレイアウトです。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3557619/90738eed-b00b-c81a-abd2-01a2bf1629d0.png)
デザインカンプに準じて、
①gridを使う、
②画像の増減でレイアウト崩れしないように、
という指示のもと行ったコーディングです。

「画像が不揃い」というだけでも難しかったのですが、
「画像の増減でレイアウトが崩れないようにする」というのがさらに難しく、時間がかかりました。
その時のコードを見直し、違いを比較してみました。

# 読者対象
・HTML/CSSでコーディングをしている人
・gridレイアウトに不慣れな人


# 開発環境
用意するファイルはindex.htmlとstyle.cssです。
index.htmlからstyle.cssを読み込みます。

# 実装手順
・gridで画像を不揃いに並べる。
・画像の増減でレイアウトが崩れないようにする。

## gridで画像を不揃いに並べる

### HTML
HTMLは非常にシンプルで、画像を囲む親要素がひとつあればOKです。
HTMLで多くの要素を作らなくて済むのは、gridを使うメリットの一つですね。
```html
<div class="gallery">
    <img src="" alt="" width="" height="">
    <img src="" alt="" width="" height="">
    <img src="" alt="" width="" height="">
    <img src="" alt="" width="" height="">
    <img src="" alt="" width="" height="">
    <img src="" alt="" width="" height="">
    <img src="" alt="" width="" height="">
 </div>

```
### 最初のCSS
```css
.gallery {
    max-width: 500px;
    width: 100%;
    margin-inline: auto;
    /* 以下gridレイアウト用 */
    display: grid;
    gap: 10px;/* 画像間の余白 */
    grid-auto-flow: dense; /* 隙間を埋めながら配置 */
    grid-template-columns: repeat(7, 1fr); /* カラム数を設定 */
}
img:first-child {
	grid-column: 1/4;
	grid-row: 1/3;
}
img:nth-child(2) {
	grid-column: 4/8;
	grid-row: 1/2;
}
img:nth-child(3) {
	grid-column: 4/8;
	grid-row: 2/3;
}
img:nth-child(4) {
	grid-column: 1/5;
	grid-row: 3/5;
}
img:nth-child(5) {
	grid-column: 1/5;
	grid-row: 5/7;
}
img:nth-child(6) {
	grid-column: 5/8;
	grid-row: 3/4;
}
img:nth-child(7) {
	grid-column: 5/8;
	grid-row: 4/7;
}
/* アスペクト比設定 */
img {
    display: block;
    aspect-ratio: 300/200;
    width: 100%;
    height: 100%;
    object-fit: cover;	
}
img:first-child {
  aspect-ratio: 200/400;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
img:nth-child(7) {
  aspect-ratio: 200/300;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
```

各画像`:nth-child(n)`に、
`grid-column: ○/○;`
`grid-row: ○/○;`
で、画像が並ぶ位置を指定しました。

最初は、ノートに手書きしてイメージをつかみました。
![5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3557619/c8d4959d-a847-a306-4527-d1218cb173f5.jpeg)


### 結果
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3557619/b101e291-ad94-27b8-03f9-b318d7201f3a.png)
7枚目までは問題なく並べることができました！
しかし！
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3557619/bc50f594-5507-d042-bad7-a55b8f085f18.png)

8枚目以降の画像には何も指定をしていないため、画像が増えたとき、一つ分のグリッドセルに自動配置されてしまいました。
この書き方で画像が増えても崩れないようにするためには、`:nth-child(8)`、`:nth-child(9)`、`:nth-child(10)`・・・と、CSSを永遠に用意しておかなければならず現実的ではありません。（※「画像が絶対に増えない」と決まっている場合は、ここまでのコードで完成としても問題ないと思います！）


## 画像の増減でレイアウトが崩れないようにする

まず、`:nth-child(n)`を見直す必要がありました。
`:nth-child(n)`から`:nth-child(7n+1)`、`:nth-child(7n+2)`・・・と変更しました。
すると、、、
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3557619/b5b25b9d-cd8b-09ca-699a-c78511cedf33.png)
8枚目が1枚目に、9枚目が2枚目に、10枚目が3枚目に置き換わってしまいました。

このように置き換わったことで、
`grid-column: 1/4;`
`grid-row: 1/3;`
↑この書き方は絶対値での書き方であることが分かりました。

ということで、
`grid-column: ○/○;`
`grid-row: ○/○;`
これらをすべて相対値で書き直します。
相対値にはspanを使います。

### 修正後のCSS
```css
img:nth-child(7n+1) {
  grid-column: span 3;
  grid-row: span 2;
}
img:nth-child(7n+2),
img:nth-child(7n+3) {
  grid-column: span 4;
  grid-row: span 1;
}
img:nth-child(7n+4) {
  grid-column: span 4;
  grid-row: span 2;
}
img:nth-child(7n+5) {
  grid-column: span 4;
  grid-row: span 2;
}
img:nth-child(7n+6) {
  grid-column: span 3;
  grid-row: span 1;
}
img:nth-child(7n+7) {
  grid-column: span 3;
  grid-row: span 3;
}
```

### コードのちがい
```css
img:first-child {
	grid-column: 1/4;
	grid-row: 1/3;
}
```
上記の書き方は、グリッドラインと呼ばれるラインの数字を指定します。
`grid-column: 1/4;`は「グリッドライン1からグリッドライン4まで」という意味です。（columnなら横方向→、rowなら縦方向↓にカウント）
```css
img:first-child {
    grid-column: span 3;
    grid-row: span 2;
}
```
spanを使った書き方では、グリッドセルの数を指定します。
`grid-column: span 3;`は「グリッドセル3つ分」という意味です。（columnなら横方向→、rowなら縦方向↓にカウント）

### 結果
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3557619/dda38f5a-35d3-befb-1845-60f80314e443.png)
これで、8枚目以降の画像も、表示崩れすることなく表示されるようになりました！！
（画像のアスペクト比も設定していますので、サイズの違う画像を入れても崩れることはありません。）

今回のように要素の増減を考慮しておく必要がある場合は、相対値での実装が適していることがわかりました！！

# 最後に
今回はgridレイアウト+spanを使うことで「画像の増減でレイアウトが崩れないように」実装できました。
制作当時はヒントをもらいながら実装したものでしたが、今回改めて振り返って自分で言語化してみることでコードの違いを理解することができました。


# 参考文献
gridの基本概念

https://developer.mozilla.org/ja/docs/Web/CSS/CSS_grid_layout/Basic_concepts_of_grid_layout

参考

https://www.webcreatorbox.com/tech/css-grid-layout

https://zenn.dev/umatoma/articles/b970bdd3a148cd

フリー画像

https://www.pexels.com/ja-jp/

https://picsum.photos/