auto-fit/fillでレスポンシブなタイルレイアウトにするやつの理解

![CleanShot 2024-08-29 at 12.23.05.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3571075/85723f31-ae23-27f3-e1d3-81bb8fe4c157.gif)


上のgif画像のような、コンテナ幅に合わせてカラム数を勝手に調整してくれるタイルレイアウトを実装してみました。記事一覧とかをレスポンシブにする時に使われるやつです。
実装の方法自体は簡単なもので、
```diff_css
.container{
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
```
この二行をコンテナに追加するだけです。しかし、実装はできても、その仕組みのところまで一発で理解することができなかったので、立ち止まって自分なりに整理してみることにしました。


## なんでその1　なんでauto-fit？

そもそも`auto-fit`ってなんぞ？ってレベルだったので、まずはGoogle検索で調べてみることにしました。すると、大抵の記事で`auto-fill`との比較によって`auto-fit`を説明していました。
どちらも、`repeat()`の第一引数に指定するためのもので、**コンテナ幅 / 第二引数の数（小数点以下切り捨て）だけグリッドのカラム（行）を生成する**というものです。両者の違いは、以下の点にあります。

**`auto-fill`**
![CleanShot 2024-08-27 at 17.38.52@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3571075/feb77845-acf9-b521-9e1d-9e45f407defa.png)
余白ができる場合、余白を埋めるためにカラム（行）が追加され、**要素がなくてもそのカラム（行）は保持される**（画像は`grid-template-columns: repeat(auto-fill, 150px);`とした場合）。

**`auto-fit`**
![CleanShot 2024-08-27 at 17.39.38@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3571075/3417b982-fbc0-b060-4f4a-802593f53633.png)
コンテナ幅 / 第二引数の数分のカラム（行）を生成するが、**要素がないカラムは自動的に非表示になる**（画像は`grid-template-columns: repeat(auto-fit, 150px);`とした場合）。

`auto-fit`と`auto-fill`の違いについては、既存のソースでも十分に分かりやすかったのですが、むしろ二つの値に共通する、**コンテナ幅 / 第二引数**という具体的な算出方法が書いてあるソースが、ちょっと探しただけだと見当たらなかったため、理解に至りにくかったように思います。ただこれで、確かにレスポンシブには使いやすそうだなーというのは理解できました。**PC幅からスマホ幅に変わればコンテナ幅も大きく変わるため、コンテナ幅 / 第二引数の結果＝カラム数が変動する**わけですね。


## なんでその2　なんでminmax(150px, 1fr)？

私はここがなかなか理解できませんでした。最小値`150px`の方はなんとなく分かるけど、最大値が`1fr`ってどういうこと？？なんでそれであの挙動になるの？？って感じでした。
ここは字面だけ眺めていても理解しにくい部分なのかなと思います（私だけかも）。なので、実際に手を動かし、`repeat()`の第二引数を`minmax(150px, 1fr)`とした場合とそうでない場合を比較してみることにしました。

**①`grid-template-columns: repeat(auto-fit, 1fr);`とした場合（あんまり意味なさそう）**
![CleanShot 2024-08-27 at 18.27.03.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3571075/24ed17d8-603b-7d5b-823a-5cd10d71b524.gif)


**②`grid-template-columns: repeat(auto-fit, 150px);`とした場合**
![CleanShot 2024-08-27 at 18.28.27.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3571075/06f01c7c-db4a-2610-4529-64a28e7d6dd2.gif)


**③`grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));`とした場合**
![CleanShot 2024-08-27 at 18.24.52.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3571075/761405ed-761e-32f9-c664-c5401080c19d.gif)


②と③の比較で、各アイテム幅がビヨーンって変化している時間帯に、最大値に指定した1frが適用されているんだなあと、なんとなくですが視覚的に分かりました。そして、もっと細かく見ていくと、**②でも③でも、コンテナ内に新しいカラムが生成されるタイミング（コンテナ幅が150n pxになった瞬間）は変わらない**、ということも分かりました。



「なんでその1」の内容と合わせて考えると、`grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));`の処理内容をこんな感じに分解できるはずです。

:::note info
**まず最初に、`コンテナ幅 / 150px`によって、`auto-fit`のとる値=カラム数が算出される。
↓
カラム数によって、最大値に指定した`1fr`の値も決まってくる。
↓
`1fr`の値が決まったことで、 `minmax(150px, 1fr)`の計算が行われ、各カラムの幅が決定される**
:::


例えば、
**コンテナが`599px`の時は、カラム数が`3`で、各カラムの幅は`599/3 px(1fr)`となる
コンテナが`600px`の時は、カラム数がひとつ増えて`4`に、各カラムの幅は`150px`となる
コンテナが`601px`の時は、カラム数が`4`で、各カラムの幅は`601/4 px(1fr)`となる**

というわけですね。

### `minmax(固定値,可変値)`の考え方
そして、私はここから、もうひとつ重大な気づきを得ることができました。
私はこれまで、`minmax(150px, 1fr)`を「<INS>最小値が150pxで、最大値が1fr</INS>」とそのまま読み替えていたのですが、これが直感的な理解を妨げる要因となっていたのです。
最大値が可変、って、なんかちょっとイメージしづらくないですか？たとえば、`minmax(150px, 200px)`というような、`(固定値,固定値)`の組み合わせであれば、（最小値が`150px`、最大値が`200px`で、その間を行き来するんだな……）と置き換えやすいのですが。

なので、`minmax(固定値,可変値)`の場合は、こんな風に言い換えてしまいましょう。

:::note info
「<INS>**常に`可変値`が適用され、その最小値が`固定値`となる**</INS>」
:::

`minmax(150px, 1fr)`の場合ですと、「<INS>常に`1fr`が適用され、その最小値が`150px`となる</INS>」となるわけです。これで少し直感的に理解しやすくなったのではないでしょうか？


## おわりに
一つの「分からん」から副次的に色々な「分からん」が出てきて、それらも ついでに解消することができたので、やはり立ち止まって（<INS>手は動かしながら</INS>）考えることは大事だなあと思いました。
ご感想やご指摘などあれば、コメント欄にお書きいただけますと幸いです🙇

## 参考

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