Conditional CSS Classes in HAML

I have been working on a new Rails side project called Your Congress, and decided to use HAML instead of the standard Rails templating language (ERB). Why? Good question. Actually, I just wanted to learn how to use it to add a new technology to my skills for the Job Search.

What is HAML

According to the HAML website:

Haml (HTML abstraction markup language) is based on one primary principle: markup should be beautiful. It’s not just beauty for beauty’s sake either; Haml accelerates and simplifies template creation down to veritable haiku.

For those not familiar with Rails templating, HAML is very similar to Pug. The difference is that it allows injections of embedded Ruby commands.

A few rules:

HTML tags are preceded by % and include no closing tag:

%button "Click here"

or with classes attached and separated by a dot. Also, notice the second line is indented. This is important with HAML, Pug, and other languages like Python.

%button.btn.btn-primary
"Click here"

Problem

My problem was that I needed to apply a custom class based on whether the user was logged in. In ERB, this may look like so, using Tailwind classes:

  <button class="<%= 'cursor-not-allowed' if logged_in? %>">

My beginning HAML string was the following:

%button{type: "button", class: "text-white py-3 px-4 rounded-lg bg-indigo-700"}
"Button text"

You can string different elements together within { }.

HAML solution

As it turns out, HAML has a special syntax for embedding logic in a tag string.

  • First, you need to enclose your classes within square brackets [].
  • Inside the brackets, you enclose the default classes within ( ) followed by a ,.
  • The logic expression is enclosed in a second pair of ( ).
class: [("text-white py-3 px-4 rounded-lg bg-indigo-700"), ("rounded opacity-50 cursor-not-allowed" unless logged_in?) ]}

Notice in the second expression that if the user is not logged in? We are using the additional classes.

So, the complete logic is:

%button{type: "button", class: [("text-white py-3 px-4 rounded-lg bg-indigo-700"), ("rounded opacity-50 cursor-not-allowed" unless logged_in?) ]}
%p.work-sans.font-semibold.text-sm.tracking-wide
- if !logged_in?
'Log in to save to a follow list'
- else
=link_to 'Add to Follow List', edit_user_follow_list_path(mem_id: @senator[:member_id], user_id: current_user[:id])

After I figured this out, I can tell you I am liking HAML even more. I find it to be a concise, elegant way to develop views in Rails.