Hiccup Lightning Tutorial

Iwo Herka
Iwo Herka
Sep 15, 2019 · 4 min read
Image for post
Image for post

Hiccup is a Clojure DSL for writing HTML. Here is a quick tutorial for the busy. It contains most of the information you’re going to need in a typical project.

Introduction

Hiccup is a domain-specific language for generating HTML in Clojure. In other words, it turns Clojure into HTML. Let’s look at an example:

As you can see, it uses literal data structures — in fact, it’s just Clojure’s vectors containing keywords (representing tags) and maps (for HTML properties). The above example compiles down to:

…which is simple div with a single button which increments some atom counter. Everything is represented as a plain Clojure data-structure.

The advantages

  1. No need to create separate files for templates. Hiccup is typically used in Reagent/re-frame projects, where views are just Clojure functions returning HTML (or functions returning functions).
  2. HTML represented as plain vectors which can be easily processed and generated using all the tools of the host language. This means that repetitive code can be abstracted away into functions and mechanically manipulated.
  3. A thin layer of abstraction allows improving HTML semantics while not being new enough to require re-learning.

The gist of it

Vectors and maps

If you’re building front-end using Reagent/re-frame, you will probably spend most of the time using Hiccup’s literals. In Hiccup, HTML nodes are represented as Clojure’s vectors. The first element of the vector is always a keyword (e.g. :div) designating HTML tag. Immediately after the tag, we specify special options which act as a syntactic sugar (explained below). The second argument is an optional map of the tag’s attributes. We will specify here things such as inline styles, classes, event listeners, and so on. Lastly, we pass arguments to the element itself, such as a string for the label. Putting it all together, we have:

For example:

Tip: Because Hiccup uses vectors to represent HTML trees, use lists to represent sequences. Mixing vector sequences with HTML vectors may confuse Hiccup.

Constructor functions

Hiccup provides constructors for many of the standard HTML elements. Use them to remove some of the boilerplate. For example, instead of slightly verbose:

…we can do:

For a comprehensive listing, consult the API documentation.

Inline styling

Styles can be added on the fly to elements via the :style map:

By default, integers are interpreted as pixels. If you want to use a different unit, use a string instead: {:padding "50rem"}.

Sugar for the id and class attribute

Hiccup provides a convenient syntax for adding id and class attributes to an element. The following code:

…can be rewritten as:

The word after the # denotes the element’s ID, and each word after a dot corresponds to one of the element’s classes. The ID must always come first.

Tip: Specify permanent classes using sugar and dynamic ones via :class. Sometimes you will use a particular class only in certain conditions. For example, the class "active" may depend on the Boolean active?:

(Strings to :class are concatenated, so we need whitespace to separate classes). My suggestion is to specify classes that are static using sugar notation and leave everything else in the attribute map:

Conditional rendering

nil values are ignored. This means that we don’t have to worry about them slipping into our HTML. For example, Clojure’s function (when test & body) will return body if test is true and nil otherwise. Therefore, we can do:

If is-true? is false, the value of the expression will simply be ignored, and only element a will end up in the output.

Sugar for nested tags

To avoid repetitive nesting of HTML tags:

…you can use the > sugar:

Escape strings with h to avoid XSS

Hiccup concatenates strings without asking questions. Therefore, whenever you receive a string from unsafe sources (such as user form or foreign API) you should escape the string with hiccup.core/h:

Abstraction

One of the biggest advantages of using Hiccup is the ability to abstract away all the repetitiveness of manual HTML-writing. Instead of typing each li, we can use a loop:

Often, it’s a good idea to write a generator function for a commonly occurring element. For example:

…which yields a button with an internal counter variable. We can stack and nest those endlessly. However, as Eric Normand points out, there is one problem:

[..] because the Hiccup compiler doesn’t do a full examination of your code, it can’t compile everything. It inserts run time fallbacks for stuff it can’t handle at compile time which will interpret it at run time. So, for instance, if you’re calling a function that returns some Hiccup, it can’t compile that automatically. It has to wait till the function returns to know what it is. That is, unless . . .

The fix: The way to get Hiccup to compile something is with the hiccup.core/html macro. That’s the macro that does the compilation and it will do it anywhere.

For most projects, this shouldn’t be a problem; however, a large codebase may lose some performance. To avoid this, we can do:

Rendering

To force HTML generation directly, use hiccup.core/html function:

Image for post
Image for post

That’s it — the gist of Hiccup. Thanks for reading. Take a look at the resources below if you want to delve deeper and maybe my other stuff. If you have any questions, please feel free to send me an e-mail or leave a comment.

Makimo Tech Blog

Makimo, a bespoke software development house @ Łódź, PL

Thanks to Marcin Struś

Iwo Herka

Written by

Iwo Herka

Senior software developer at makimo.pl. Functional programming enthusiast. You can find me on github.com/iwoherka.

Makimo Tech Blog

Makimo is a bespoke software development house located in Lodz, Poland with main focus on web development with Python & Clojure. Here we share what we know, learn, discover or struggle with when we craft our software.

Iwo Herka

Written by

Iwo Herka

Senior software developer at makimo.pl. Functional programming enthusiast. You can find me on github.com/iwoherka.

Makimo Tech Blog

Makimo is a bespoke software development house located in Lodz, Poland with main focus on web development with Python & Clojure. Here we share what we know, learn, discover or struggle with when we craft our software.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store