Creating UIs with CSS is rarely as straightforward as you expect.
A few weeks ago I wanted to make the navigation on my site responsive, having it switch from a row of links to a hamburger slideout menu. Seems like a reasonable thing to do with CSS, right?
Not really. As often happens, I tried a few reasonable things – they didn’t work. I started searching for solutions – most involved JavaScript.
I finally found a solution that was CSS-only, and then spent a couple of hours trying different combinations of styles to get it to (mostly) work in the context of my site.
How many times did you find yourself doing something totally reasonable that should be simple with CSS, only to find yourself getting derailed in bizarre ways? Maybe the text just won’t align vertically, or you just can’t seem to get the width of the elements right, or the style you’ve added doesn’t seem to have any effect at all.
That seems to be a common experience with CSS, which is why I’m excited about an Elm package called elm-ui
. Its goal is to allow you to build UIs in pure Elm, with HTML and CSS generated for you behind the scenes.
The approach taken by elm-ui
is based on four ideas:
In elm-ui
, all of the layout and visual styling is done within your view
function, with the “gross morphology” of layout made explicit through the functions exposed by this package. Style attributes can be specified for each element in the layout.
To see elm-ui
in action, let’s implement a simplified version of the Slack UI:
First off, let’s initialise the project:
$ elm init
$ elm install mdgriffith/elm-ui
Then, let’s make the smallest increment towards our layout:
module Main exposing (main)
import Element exposing (..)
import Element.Background as Background
import Element.Border as Border
import Element.Events exposing (..)
import Element.Font as Font
import Element.Input as Input
import Html exposing (Html)
channelPanel : Element msg
channelPanel =
column
[ height fill
, width <| fillPortion 1
, Background.color <| rgb255 92 99 118
, Font.color <| rgb255 255 255 255
]
[ text "channels" ]
chatPanel : Element msg
chatPanel =
column [ height fill, width <| fillPortion 5 ]
[ text "chat" ]
main : Html msg
main =
layout [] <|
row [ height fill, width fill ]
[ channelPanel
, chatPanel
]
Here is the page produced by this code: