We're planting a tree for every job application! Click here to learn more

Rapid Web Prototyping with Elm

Jonathan Reeve

24 Nov 2021

•

5 min read

Rapid Web Prototyping with Elm
  • Elm

About

Developers typically encounter Elm when they want to make a dynamic web application—something Elm excels at. There are already great guides which introduce Elm for that purpose. The very first example in the Elm Guide is a counter app that lets you increment and decrement a number.

But maybe you haven't considered Elm for the use-case of rapidly prototyping a web page. In other words, what do you reach for when you want to create a static web page quickly? Do you use a static site generator, like Jekyll, Hugo, or Next.js? Or do you hand-write HTML, CSS, and JavaScript? Either way, Elm is an improvement. Elm is a functional programming language for the web, which replaces HTML, CSS, and Javascript. I want to show you how much of a joy it is to write, and how it can be your next tool for rapid creation of web pages.

The Problem

The problem with web development is that its fundamental languages—HTML, CSS, and JavaScript—each have their idiosyncrasies. Making a web page usually means being trilingual with these technologies and their syntaxes. HTML is verbose, and isn't programmable, which means you end up repeating yourself. Imagine if you're writing a list of three fruit. In HTML, that's:

<ul>
  <li>apples</li>
  <li>oranges</li>
  <li>bananas</li>
</ul>

Why can't we just write <li> for item in ["apples", "oranges", "bananas"]</li>? HTML isn't very DRY.

CSS has many of the same limitations. While new CSS features like CSS variables certainly mitigate the issue of code reusability, it still isn't a programming language. CSS nesting, for instance, is still a working draft, and not yet implemented in any browser. This is why there have been so many HTML and CSS preprocessors: SASS/SCSS for CSS, Pug for HTML. Each tries to make HTML and CSS into more of an actual programming language.

A further problem is that JavaScript is a bit of a mess. It's clunky, and not type-safe. This means that if you write some JavaScript, you're always in danger of unexpected input throwing exceptions. CoffeeScript and TypeScript were meant to solve these issues, but they only serve to add to your stack of preprocessors. Even if you write HTML with Haml, CSS with SASS, and JavaScript with CoffeeScript, you're still wrangling three languages. Some static site generators make a stack like that relatively easy, but generate a lot of complexity.

Introducing Elm

Enter Elm. It's a delightful language for modern web programming. Elm has Haskell-inspired syntax, and takes inspiration from other languages, as well. It's type-safe, but with optional type annotations. This means that errors are usually discovered at compile time, rather than at runtime. That means that if it compiles, it's very likely to run without errors from then on. The compiler error messages are friendly, and so is the community, which is very open and supportive. Even though it's a new language, it has seen a lot of adoption already in the industry, and has a ton of packages available for it. Elm compiles to HTML, CSS, and JS, so instead of wrangling those three languages (or three analogous preprocessor languages), you just write Elm, and it handles the rest.

Hello world

Here's the bare minimum web page you can make with Elm.

module Main exposing (..)

import Html exposing (..)

main = text "hello world!"

You can run this example here on Ellie, if you don't yet have Elm installed.

What's happening here?

  1. Ellie requires you to declare that your file is a module called Main.
  2. The function text, as well as the other Html functions we'll use, are in the HTML Module, which we have to import.
  3. Function calls in Elm look like they do in Haskell, so write text "hello world" instead of text("hello world") as it would look in Python-like languages.

Puppies or kittens?

Now let's prototype a toy web page, about whether puppies or kittens are cuter:

module Main exposing (..)

import Html exposing (..)
import Html.Attributes exposing (..)

main = main_ []
  [ h1 [ style "color" "red" ] [ text "Puppies or kittens?" ]
  , p [] [ text "This page considers the problem of whether puppies or kittens are cuter." ]
  , img [ src "https://placekitten.com/g/400/400" ] []
  ]

Run this example here on Ellie.

Here's what's going on here:

  • Lists in Elm look like this: [ a, b, c ]
  • HTML functions usually take two arguments: a list of attributes, and a list of contents: p [ attribute1, attribute2 ] [ element1, element2 ]. Thus, the main_ function has no attributes, but has three children: h1, p, and img.
  • CSS is written in the same way. style takes two arguments, the CSS selector, and its value.
  • Whitespace doesn't matter, so we can indent this any way that makes sense.

Functions

We can DRY out this website, by abstracting away functionality that repeats. For instance, if we want two kitten photos, instead of writing two <img src=""/> tags, we can write a function that will do both.

Functions that take parameters look like this: greet name = "Hello" ++ name ++ "!". The greet function takes the name argument, and inserts it into the greeting, such that calling greet "Jonathan" returns "Hello Jonathan!".

So if we want to have two images, one which loads a placeholder kitten image from https://placekitten.com/g/400/400 and another from https://placekitten.com/g/300/300, we can write that like this:

module Main exposing (..)

import Html exposing (..)
import Html.Attributes exposing (..)

kitten size = img [ src ("https://placekitten.com/" ++ size ++ "/" ++ size)
                  , style "border" "1px solid red" ] []

main = main_ []
  [ h1 [ style "color" "red" ] [ text "Puppies or kittens?" ]
  , p [] [ text "This page considers the problem of whether puppies or kittens are cuter." ]
  , kitten "400"
  , kitten "300"
  ]

Run this example here on Ellie.

Markdown example

Alternatively, you can write your site in Markdown:

module Main exposing (..)

import Html exposing (..)
import Html.Attributes exposing (..)
import Markdown exposing (toHtml)

content : Html msg
content = toHtml [] """

# Apple Pie Recipe

  1. Invent the universe.
  2. Bake an apple pie.

"""

main = content

To run this example in Ellie, you should install the package Markdown using the sidebar to the left.

  • Triple-quotes """ are for multi-line literal strings.

I love it. How can I learn more?

Once you've outgrown Ellie, and want to build pages locally, download installers from here. Or install via npm if you already have node: npm install -g elm. That enables you to run elm build to generate your site from a Main.elm file.

The official Elm guide is also wonderful, and eminently readable. There's also the book Elm in Action, if you prefer learning from books.

Did you like this article?

Jonathan Reeve

Computational literary analyst, digital humanist, English PhD student at Columbia.

See other articles by Jonathan

Related jobs

See all

Title

The company

title

Remote

Title

The company

title

Remote

Title

The company

title

Remote

Title

The company

title

Remote

Related articles

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

•

12 Sep 2021

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

•

12 Sep 2021

WorksHub

CareersCompaniesSitemapFunctional WorksBlockchain WorksJavaScript WorksAI WorksGolang WorksJava WorksPython WorksRemote Works
email iconhello@works-hub.comUK flag

Ground Floor, Verse Building, 18 Brunswick Place, London, N1 6DZ

US flag

108 E 16th Street, New York, NY 10003

Subscribe to our newsletter

Join over 111,000 others and get access to exclusive content, job opportunities and more!

© 2022 WorksHub

Privacy PolicyDeveloped by WorksHub