TheSeamau5/flex-html fork This library contains several affordances for laying out Html with elm-html using flexbox.
To illustrate how it works, here is an example of how to do the holy grail layout using flex-html
background : Float -> String -> Html
background grow color =
let
backgroundStyles =
("background-color", color)
:: Flex.grow grow
in
div
[ style backgroundStyles ]
[]
holyGrail : Html
holyGrail =
let
topSection = background 1 "red"
bottomSection = background 1 "black"
leftSection = background 1 "blue"
rightSection = background 1 "yellow"
centerSection = background 4 "green"
styleList =
Flex.direction Flex.Horizontal
++ Flex.grow 8
++ Flex.display
mainSection =
div
[ style styleList ]
[ leftSection
, centerSection
, rightSection
]
mainStyleList =
[ ("width", "100vw")
, ("height", "100vh")
]
++ Flex.display
++ Flex.direction Flex.Vertical
in
div
[ style mainStyleList ]
[ topSection
, mainSection
, bottomSection
]
main : Html
main =
holyGrailWe populate the page with distinctly colored backgrounds (hence, the use of a background function).
The holy grail layout has 5 sections: a top row section, a bottom row section, a left column section, a right column section, and a center content section.
Each section is created as a background with a unique color to distinguish them:
topSection = background 1 "red"
bottomSection = background 1 "black"
leftSection = background 1 "blue"
rightSection = background 1 "yellow"
centerSection = background 4 "green"An then we simply lay them out. We first consider the vertically flowing sections. So we lay the top section atop a main section atop a bottom section as follows:
mainStyleList =
[ ("width", "100vw")
, ("height", "100vh")
]
++ Flex.display
++ Flex.direction Flex.Vertical
{-| ... -}
div
[ style mainStyleList ]
[ topSection
, mainSection
, bottomSection
]Where the main section is a horizontal layout of the left section, the center section, and the right section (from left to right) and is defined as follows:
styleList =
Flex.direction Flex.Horizontal
++ Flex.grow 8
++ Flex.display
mainSection =
div
[ style styleList ]
[ leftSection
, centerSection
, rightSection
]And that's how one would implement the holy grail with flex-html.
flex-html is implemented as a collection of mixins. Each mixin allows you to define a flex property for a parent or child.
To illustrate how you can use these mixins, here is an example of positioning labels in a manner which would otherwise be insanely difficult:
label : String -> Html
label value =
let
labelStyle =
[ ("background-color", "red")
, ("color", "white")
, ("padding", "5px")
, ("font-weight", "bold")
]
in
div
[ style labelStyle ]
[ text value ]
main : Html
main =
let
containerStyle =
("width", "100vw")
:: ("height", "100vh")
:: Flex.justifyContent Flex.Surround
++ Flex.alignItems Flex.Center
++ Flex.wrap Flex.NoWrap
++ Flex.display
innerContainerStyle =
("height", "100%")
:: Flex.flow Flex.Vertical Flex.NoWrap
++ Flex.justifyContent Flex.Surround
++ Flex.alignItems Flex.Center
++ Flex.display
in
div
[ style containerStyle ]
[ label "I am on the left"
, div
[ style innerContainerStyle ]
[ label "I am on top"
, label "I am absolutely centered"
, label "I am down below"
]
, label "I am on the right"
]So, as you may see, we have a helper function called label to create our labels.
We then layout the left label, the three central labels and the right label horizontally with:
containerStyle =
("width", "100vw")
:: ("height", "100vh")
:: Flex.justifyContent Flex.Surround
++ Flex.alignItems Flex.Center
++ Flex.wrap Flex.NoWrap
++ Flex.displaywhere:
justifyContent Surroundimplies that the children will be equally spaced along the main axis (in this case, the horizontal axis)wrap NoWrapimplies that the children will not wrap if there isn't enough space to flex (not a concern in this example)alignItems Centermakes sure to center the itemsdisplayapplies flex display on the divhorizontalis the default direction and thus main axis
And the central section (containing the top, centered, and bottom labels) are laid out using:
innerContainerStyle =
("height", "100%")
:: Flex.flow Flex.Vertical Flex.NoWrap
++ Flex.justifyContent Flex.Surround
++ Flex.alignItems Flex.Center
++ Flex.displaywhere:
flow Vertical NoWrapsets Vertical as the direction, making that the main axis and disable wrapping as seen previously
There are more mixins available. You can learn about these in the documentation as a reader exercise.