レイアウトに特化し見た目はcssを使っていくという、elm-neat-layoutというレイアウトライブラリを使ってみました。
前回のelm-uiから、今回はスクロールに挑戦してみようとしたのですが、けっこう敗北しました。
ウィンドウサイズを変えて要素が並び替えられても下の余白もきっちり且つスクロールも、とやってみようとしたのですが諦めてしまいました。
メモ
なんとなく、こういうふうに使ってみたと書いてみます。
きっと間違っている部分が多々あります。
作者のarowMさんがそのうちドキュメントを書いてくださるそうです。
フレームワーク
elm-neat-layoutはレイアウト担当でcssはcssにというものらしいので、ライブラリのようにちょっと使ってみようとしたのですがelm-uiよりもフレームワーク感覚がありました。
よく見たらframeworkと書いてありました。
main
main : Program () Model Msg
main =
Neat.element
{ init = \_ -> init
, view = view
, update = update
, subscriptions = subscriptions
, renderer = \_ -> defaultRenderer
}
まずこのようにBrowser.element
でなくNeat.element
などで置き換えます。
view
view : Model -> View NoGap Msg
view model =
Layout.column
[ menu model
, tab
, body |> setLayout Layout.fill
]
|> setClass "main"
viewもこのようにModel -> View NoGap Msg
となります。
パイプ
標準のelmならば
div
[ class "hoge" ]
[ text "hello" ]
こうですが、elm-neat-layoutでは属性はあとから追加していくみたいです。
Layout.column
[ Neat.textBlock "hello"
]
|> setClass "hoge"
もっと複雑になったときなど、メリットがあるんだと思います。
きっちりした余白
余白を型で管理するようで、View NoGap Msg
はViewにNoGapという余白がついているイメージだと思います。
余白のない余白です。
余白定義
type MenuGap
= MenuGap
menuGap : Neat.IsGap MenuGap
menuGap =
Neat.IsGap
{ width = 0.8
, height = 0.8
}
menuGapという0.8remの余白ができました。
仕組み
余白が0.8なら(0.8[item1]0.8)(0.8[item2]0.8)
このように、端は0.8で真ん中は1.6になってしまいそうですが、そのへんをうまくやってくれるみたいです。
(0.4(0.4[item1]0.4)(0.4[item2]0.4)0.4)
このように、item1に0.4の余白が付き、item2に0.4の余白が付き、それらを束ねるものに0.4の余白が付くのだと思います。
余白適用
menu : View NoGap Msg
menu =
Layout.column
[ Neat.textBlock "item1"
|> fromNoGap menuGap
, Neat.textBlock "item2"
|> fromNoGap menuGap
]
|> setBoundary menuGap
fromNoGap menuGap
これによって、item1に余白が0.4付きます。
item2も同様です。
Listに異なる型を含めることができないように、item2に余白が設定されていなかったり、別の余白が設定されるとコンパイルエラーが出ます。
setBoundary menuGap
これによって、itemを束ねるcolumnに0.4の余白が付き、外から見たら一塊の余白がないものとしてmenuはView NoGap Msg
となります。
クラス適用
menu : View NoGap Msg
menu =
Layout.column
[ Neat.textBlock "item1"
|> setClass "menu_item"
|> fromNoGap menuGap
, Neat.textBlock "item2"
|> setClass "menu_item"
|> fromNoGap menuGap
]
|> setBoundary menuGap
|> setClass "menu"
fromNoGap
によって特別なものに変わってしまうので、その前にsetClassでクラスを設定します。
もともとNoGap型にしか適用できません。
fill
menu : View NoGap Msg
menu =
Layout.column
[ Neat.textBlock "item1"
|> setClass "menu_item"
|> fromNoGap menuGap
, Neat.textBlock "item2"
--|> setLayout Layout.fill
|> setClass "menu_item"
--|> setLayout Layout.fill
|> fromNoGap menuGap
|> setLayout Layout.fill
]
|> setBoundary menuGap
|> setClass "menu"
--|> setLayout Layout.fill これは間違い
fillはcolumnなどの中で要素を拡大させるために使うみたいです。
elm-uiで自分は、なんだかとにかく大きくしたいからwidth fill
としていたような気がしますが、なるほどと思いました。
columnの中といっても、どこに書くのがいいんだろうと思いましたが、どこでも変わらなそうです。
column{display: flex}
menuGap{}
menu_item{}
menuGap{flex-grow: 1}
menu_item{}
どこに書いても最終的にこうなるイメージだと思います。
スクロール
row内部の要素にスクロールバーをつけてみようとしました。
main{height: 100vh}
header
body
footer
まずこのように上の要素に勝手に拡大しないheightを指定しなければならないとならないみたいです。
arowMさんに聞いてしまって(ありがとうございました)その時は解決したのですが、その後rowのなかに入れたり余白を適用させたり、wrapで改行させたりすると、うまく行かなくなってしまいました。
あちらを立てればこちらが立たずといった感じで、cssなどの知識も足りずそこそこで諦めました。
NoGap
NoGap{overflow-y: auto}
内部であってもこのようなときなら良さそうです。
それから、rowやcolumnを改行させないNoWrapでも良さそうです。
敗北
elm-neat-layoutの作ったdivにブラウザのdev toolでoverflow: hidden
をつけまくるとうまく動いたような気がしたのですが、どういう理屈・意味でそうなるのかはよくわかりませんでした。
hight: auto
hight: 100%
それから、これは何がどういうことになるのかもわかりませんでした。
たぶん100%とあっても上で具体的な値が設定されていないのでautoになるのかもしれません。
トップダウンなんだか、ボトムアップなんだかややこしいです。
逃げ道
スクロールをつけたい要素にmax-height: 80vh
のようにしてしまいました。
というわけで、下はきっちりな余白を諦めました。
そもそもrowにwrapで改行させるようなことをせずoverflow: hidden
でなんとかなった気がします。
まとめ
殆どの時間をcssに苦しめられていました。
たしかにきれいに見えて余白は重要そうです。