DEV Community

loading...

Learn HAML in 5 Minutes [2021]

Mark
・2 min read

Originally posted on my website

HAML is a faster way to write HTML and is very common in Ruby applications.

Take the following HTML:

<section class="banner">
  <h1 class="banner__title">
    Hello World!
  </h1>

  <a href="/about" class="button primary">
    Find out more
  </a>
</section>
Enter fullscreen mode Exit fullscreen mode

Now convert it to HAML:

%section.banner
  %h1.banner__title Hello World!

  %a.button.primary(href="/about") Find out more
Enter fullscreen mode Exit fullscreen mode

As you can see HAML is much slimmer, due to the fact you don't need to closed HTML tags.

How to Use HAML

It's easy to write HAML in Ruby on Rails, simply change your .html.erb files to .html.haml.

You can use the haml-rails gem to automatically convert your .html.erb files to .html.haml from the terminal. It will also set the default view file template to HAML, meaning generators will create .html.haml files.

You can install haml-rails by running bundle add haml-rails in your terminal.

How to Write HAML

Comments in HAML

/ Single line comment

/
  Multi
  line
  comment

-# Comment that won't show up in the HTML
Enter fullscreen mode Exit fullscreen mode

HTML Tags in HAML

/ <div> tag
%div

/ <div> tag with a class
.test

/ <section> tag with an id and a class
%section.test#test

/ <a> tag with HTML attributes
%a(href="/" target="_blank" data-turbo="false")

You can also write it in a hash:

%a{ href: "/", target: "_blank", data: { turbo: false } }

/ <h1> tag with single line of content
%h1 Hello World

/ <p> tag with multi line of content
%p
  Hello world, how are you today? I'm doing just fine,
  especially when I'm writing HAML.

/ <h1> tag with <br> inside it
%h1
  Hello
  %br/
  World

/ <h1> tag with a non-HTML element inside it
%h1
  Hello
  \-
  World
Enter fullscreen mode Exit fullscreen mode

Writing Ruby in HAML

/ Variable with default attribute
- bg_color = local_assigns.fetch(:bg_color, "#000")

/ Dynamic content
%h1= @project.title

/ Dynamic content with static content
%p Written by #{@project.author_name}

/ HTML content (usually from a WYSIWYG)
%div
  != @project.body

/ Loop
- @project.tags.each do |tag|
  %span= tag

/ Conditional content (if/else)
- if @project.author_image?
  = image_tag(@project.author_image)
- else
  = image_pack_tag("default-author.png")

/ Partial
= render("comments/form", project_id: @project.id)

/ Form
= form_with(model: @project, local: true) do |f|
  = f.text_field(:title)
  = f.button("Save project", class: "button success")

/ Link
= link_to("View project", project_path(project), class: "link")
Enter fullscreen mode Exit fullscreen mode

The Downsides of HAML

There's a few downsides to HAML, the biggest I've come across are issues with onboarding developers and the following:

Readability issues with long HTML attributes:

/ HAML
%div{ data: { controller: "map", map_initial_lat_value: "123", map_initial_long_value: "456" } }
  %iframe

<!-- HTML !>
<div
  data-controller="map"
  data-map-initial-lat-value="123"
  data-map-initial-long-value="456"
>
  <iframe></iframe>
</div>
Enter fullscreen mode Exit fullscreen mode

As you can see HAML is far less readable than basic HTML

Readability issues with Tailwind CSS:

%section.bg-gray-900
  .max-w-5xl.mx-auto.px-4.py-24(class="sm:px-6 lg:px-8")
    %h1.text-4xl.font-bold.tracking-wide.uppercase.text-center.text-white(class="sm:text-6xl")
      Hello World
Enter fullscreen mode Exit fullscreen mode

This isn't easy to read, and it's only a small example

Discussion (0)