0からはじめるelm-ui#5-聖杯レイアウト

# 今日覚えること

- `width <| px 100`で固定幅にすること
- `width fill`で残りの領域いっぱいに伸ばすこと
- `explain Debug.todo`でワイヤーフレームが書きやすい

[成果物](https://ellie-app.com/5bxjDvtzFJna1)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/74093/88f7799b-c734-38b7-5c67-989abf678f9d.png)

```elm
import Element exposing (..)


main =
    layout [] <|
        column [ width fill, height fill, explain Debug.todo ]
            [ row [ width fill, height <| px 100 ] [ text "header" ]
            , row [ width fill, height fill, explain Debug.todo ]
                [ column [ width <| px 100, height fill ] [ text "nav" ]
                , column [ width fill, height fill ] [ text "main" ]
                , column [ width <| px 100, height fill ] [ text "ad" ]
                ]
            , row [ width fill, height <| px 100 ] [ text "footer" ]
            ]

```

# はじめに

`#0`から`#4`でelm-uiの基本的な関数を学べたと思います
ということで今回は実践編として聖杯レイアウトを組んでみようと思います

詳しくは[この記事](https://hashrock.github.io/solved-by-flexbox-ja/demos/holy-grail/)を参考にしました

> - 伸縮する中央のコンテナと、固定幅のサイドバーを持つこと。
- 中央のカラム（メインコンテンツ）はHTMLソースの最初に登場すること。
- すべてのカラムは、どのカラムが一番高いかに関係なく、同じ高さであること。
- 最小限のマークアップしか必要にならないこと。
- コンテンツの量が少なかったとしても、フッターはページの下部に"固定"されること。

これらの条件を満たしていこうと思います。が、２つ目の条件はelm-ui的にできないのでちょっと諦めます。HTMLの意味論とかあまり知ったことじゃないです

では聖杯レイアウトを組んでいきます。5ステップです

# 1. 大まかに縦横に分割する

![image.png](https://qiita-image-store.s3.amazonaws.com/0/74093/f9e5973b-ff5b-6599-1989-07863d84db2b.png)

まず聖杯レイアウトはこんな感じです。`row`と`column`を使って組んでいくので縦横を見定めます

![image.png](https://qiita-image-store.s3.amazonaws.com/0/74093/e79ee98d-5e3a-96df-69e9-4f5e5645c9a0.png)

青 緑 オレンジで縦に積まれてます。ここは`column`にしましょう

![image.png](https://qiita-image-store.s3.amazonaws.com/0/74093/5de2c95b-bc19-0873-e484-37c6fff9d40b.png)

緑の部分はさらにピンク 黄色 紫で横に並んでいます。ここは`row`ですね

ここまでで一旦組んでみましょう

[デモ](https://ellie-app.com/5bwcpDZD27xa1)

```elm

main =
    layout [] <|
        column []
            [ text "header"
            , row []
                [ text "nav"
                , text "main"
                , text "ad"
                ]
            , text "footer"
            ]

```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/74093/b5026031-01aa-daa7-5ae8-72e06ca5655f.png)

各コンテンツにはとりあえずテキストを入れてみました
最低限レイアウトは組めてますね。上にヘッダーがあって下にフッター、真ん中左はナビゲーションの右広告、中央にメインコンテンツです

# 2. 仮組を分かりやすくする

ここから調整していくんですが、先にどういうレイアウトになってるかわかりやすいようにしましょう

`explain Debug.todo`をつかいます

```diff:
main =
    layout [] <|
-        column []
+        column [ explain Debug.todo ]
            [ text "header"
            , row []
                [ text "nav"
                , text "main"
                , text "ad"
                ]
            , text "footer"
            ]
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/74093/36c9a97e-34fb-50cf-7bd2-583d1cab2c3e.png)

`explain`をつけた要素には茶色の枠線、その子要素には青緑？の破線を付けます
こうすると要素が三つ縦に並んでることが分かりますね

真ん中の段にも`explain`を付けましょう

```diff:
```diff:elm
main =
    layout [] <|
        column [ explain Debug.todo ]
            [ text "header"
-            , row []
+            , row [ explain Debug.todo ]
                [ text "nav"
                , text "main"
                , text "ad"
                ]
            , text "footer"
            ]
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/74093/0d0d7238-8df4-c3f3-eaf8-b3d5dd04f27b.png)

茶色の線は被って消えてるみたいですが、これで各要素がどうなってるか見えるようになりました

# 3. 固定幅の部分を指定する

上記の条件によるとサイドバーは固定幅らしいです。フッターヘッダーはコンテンツの中身によって高さは変わるものだと思いますが、今回は中身までは作らないのでとりあえず固定幅にしておきましょう

```elm
main =
    layout [] <|
        column [ explain Debug.todo ]
            [ row [ height <| px 100 ] [ text "header" ]
            , row [ explain Debug.todo ]
                [ column [ width <| px 100 ] [ text "nav" ]
                , column [] [ text "main" ]
                , column [ width <| px 100 ] [ text "ad" ]
                ]
            , row [ height <| px 100 ] [ text "footer" ]
            ]
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/74093/19a42982-268d-af3a-d593-5e8b61e2caeb.png)

各テキストを`row`や`column`で囲ってサイズを指定してみました

固定幅は指定しましたが、そのほかの要素は画面端までめいっぱい伸びて欲しいですね

# 4. 幅をのばす

幅を伸ばすのは簡単です。`width fill`で埋めればいいです

```diff:
main =
    layout [] <|
        column [ explain Debug.todo ]
-            [ row [ height <| px 100 ] [ text "header" ]
+            [ row [ width fill, height <| px 100 ] [ text "header" ]
            , row [ explain Debug.todo ]
                [ column [ width <| px 100 ] [ text "nav" ]
                , column [] [ text "main" ]
                , column [ width <| px 100 ] [ text "ad" ]
                ]
-            , row [ height <| px 100 ] [ text "footer" ]
+            , row [ width fill, height <| px 100 ] [ text "footer" ]
            ]
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/74093/59c5ba2b-b94b-5443-5dc8-3bb06f4beba5.png)

はい伸びました。`fill`は親要素の幅いっぱいに伸ばしてくれます
まだ一番上の`column`を伸ばしてないので画面端までいきませんでした
伸ばしましょう

```diff:
main =
    layout [] <|
-        column [ explain Debug.todo ]
+        column [ width fill, explain Debug.todo ]
            [ row [ width fill, height <| px 100 ] [ text "header" ]
            , row [ explain Debug.todo ]
                [ column [ width <| px 100 ] [ text "nav" ]
                , column [] [ text "main" ]
                , column [ width <| px 100 ] [ text "ad" ]
                ]
            , row [ width fill, height <| px 100 ] [ text "footer" ]
            ]
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/74093/bdfb426a-5e7d-17b9-bb70-9ed08cdc19e4.png)

伸びました
あとは真ん中の段とmainカラムを伸ばしましょう

```diff
main =
    layout [] <|
        column [ width fill, explain Debug.todo ]
            [ row [ width fill, height <| px 100 ] [ text "header" ]
-            , row [ explain Debug.todo ]
+            , row [ width fill, explain Debug.todo ]
                [ column [ width <| px 100 ] [ text "nav" ]
-                , column [] [ text "main" ]
+                , column [ width fill ] [ text "main" ]
                , column [ width <| px 100 ] [ text "ad" ]
                ]
            , row [ width fill, height <| px 100 ] [ text "footer" ]
            ]
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/74093/50dc62a1-a59a-5de8-c2d5-64beff55ff91.png)

これで大体できました
あとはフッターが一番下に固定されればいいんではないかと思います

# 5. フッターを下に固定する

要するに真ん中の段を伸ばしてフッターを下にやればいいです
`width fill`をつけまくったのと同様に`height fill`をつけまくればいいです

```diff
main =
    layout [] <|
-        column [ width fill, explain Debug.todo ]
+        column [ width fill, height fill, explain Debug.todo ]
            [ row [ width fill, height <| px 100 ] [ text "header" ]
-            , row [ width fill, explain Debug.todo ]
+            , row [ width fill, height fill, explain Debug.todo ]
-                [ column [ width <| px 100 ] [ text "nav" ]
-                , column [ width fill ] [ text "main" ]
-                , column [ width <| px 100 ] [ text "ad" ]
+                [ column [ width <| px 100, height fill ] [ text "nav" ]
+                , column [ width fill, height fill ] [ text "main" ]
+                , column [ width <| px 100, height fill ] [ text "ad" ]
                ]
            , row [ width fill, height <| px 100 ] [ text "footer" ]
            ]
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/74093/88f7799b-c734-38b7-5c67-989abf678f9d.png)

完成です！

# 今日覚えたこと

- `width <| px 100`で固定幅にすること
- `width fill`で残りの領域いっぱいに伸ばすこと
- `explain Debug.todo`でワイヤーフレームが書きやすい

# おわりに

実践編ということで聖杯レイアウトを組んでみました
`row`と`column`で組んでいくやり方をわかってもらえたかなーと思ってます

elm-ui使ってみましょう！