An Introduction to Haml

Haml is an XHTML Abstraction Markup Language that, according to haml-lang.com:

functions as a replacement for inline page templating systems such as PHP, ASP, and ERB

It can be used in many Ruby frameworks, such as Rails and Sinatra, in Node.js, PHP and .NET.

This article is going to introduce you to writing your HTML as Haml. As such it’s not going to contain much Ruby code. But if you’d like a more in-depth look at how Haml works under the covers, have a read of Xavier Shay’s excellent Code Safari articles on Haml: Getting Started in Haml and Haml, Compiling to Completion.

Installing Haml

To use Haml you’ll first need to install it. This shouldn’t be any harder than opening up your command line and typing:

gem install haml 

Now, lets look at how we can write some HTML using Haml.

!DOCTYPE

By default Haml usually defaults to the XHTML DOCTYPE. I say usually because if you’re using Rails 3 then Haml defaults to HTML5. You can change the default DOCTYPE using the :format option but, as this article is dealing with standalone Haml, we’ll look at how to write the DOCTYPE manually in our template:

  • HTML5 DOCTYPE

    !!! 5 

    Will produce:

    <!DOCTYPE html> 
  • XHTML Strict DOCTYPE

    !!! Strict 

    This gives us:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
  • XML DOCTYPE

    !!! XML 

    Will output:

    <?xml version="1.0" encoding="utf-8" ?> 

Tags and Attributes

Now we’ve taken care of the DOCTYPE, let’s look at how we can construct our HTML. We’ll start the basic template of a HTML document which in Haml looks like this:

%html 
  %head 
    %title Our Awesome Haml Template 
  %body 
    Abstracting HTML since 2006 

When the above is compiled it will give us the following HTML:

<html> 
  <head> 
    <title>Our Awesome Haml Template</title> 
  </head> 
  <body> 
    Abstracting HTML since 2006 </body> </html> 

You may have noticed that:

  • Haml uses whitespace and indenting to format the HTML.
  • Tags are prefixed with a %. Closing tags aren’t required.

So far, so good. But we’ll need to add a bit more content to our page and, with it, some more structure and semantics:

%body 
  #container 
    %header 
      %h1 Our Awesome Haml Template 
    #main Abstracting HTML since 2006 
    %footer 
      %address Ian Oxley 

This gives us the following HTML:

<body> 
  <div id="container"> 
    <header> 
      <h1>Our Awesome Haml Template</h1> 
    </header> 
    <div id="main"> 
      Abstracting HTML since 2006 
    </div> 
    <footer> 
      <address>Ian Oxley</address> 
    </footer> 
  </div> 
</body> 

With more tags being added it should become more apparent how Haml uses whitespace and indentation to work out the structure of your HTML. But did you notice anything about how we got our

and
tags on to the page?

  • Haml assumes you are outputting a
    tag unless you specify otherwise
  • id attributes are specified in the same way you write an id rule in CSS i.e. #container

You can also add class attributes to an element the same way you add an id attribute:

%footer 
  %address 
    .hcard 
      .fn Ian Oxley 
      .adr 
        .locality Newcastle-upon-Tyne 
        .country-name England 

If you’ve been paying attention, you’ll have probably guessed that this will compile to:

<footer> 
  <address> 
    <div class="hcard"> 
      <div class="fn">Ian Oxley</div> 
      <div class="adr"> 
        <div class="locality">Newcastle-upon-Tyne</div> 
        <div class="country-name">England</div> 
      </div> 
    </div> 
  </address> 
</footer>

But what about other attributes that we will need to add to our markup? Things like lang, src, rel and href? Well that’s easily done using one of two methods:

  • You can use curly braces and specify your attributes with a Ruby hash. For example:

    %img{ :src => "/path/to/image", :alt => "Description of image" } 
  • Or you can use parentheses and use a more HTML-like foo=”bar” approach:

    %img ( src="/path/to/image", alt="Description of image") 

Both of these will output the following HTML:

<img src="/path/to/image" alt="Description of image"> 

Using this approach we can easily add CSS, JavaScript and any meta tags we need to our templates:

%meta{ :charset => "utf-8" } 
%link{ :rel => "stylesheet", :href => "/css/master.css" } 

Will give us:

<meta charset="utf-8"> 
<link rel="stylesheet" href="/css/master.css"> 

And:

%script{ :src => "/js/site.js" } 

Will give us:

<script src="/js/site.js"></script> 

Comments

Haml lets you add three types of comments to your markup:

  1. HTML comments
  2. Conditional comments
  3. Haml comments

HTML comments can be added using a forward slash ‘/’ but depending on where you place it will affect what gets wrapped in comments:

/ A forward slash at the start of a line wraps that line in a comment  
%blockquote  
  %p Roads? Where we're going we don't need roads
  
/  
  A forward slash at the start of a nested block wraps the whole block in a comment  
  %blockquote  
    %p Roads? Where we're going we don't need roads 

Once compiled our output will be:

<!-- Only this line will be wrapped in a comment --> 
<blockquote> 
  <p>Roads? Where we're going we don't need roads</p> 
</blockquote> 

<!-- 
  Now the whole block will be commented out 
  <blockquote> 
    <p>Roads? Where we're going we don't need roads</p> 
  </blockquote> 
--> 

Conditional comments can be added by placing the condition in square brackets after the ‘/’:

/[if IE] %link { :rel => "stylesheet", :href => "/css/ie.css" } 

This gives us the following HTML:

<!--[if IE]> <link href="/css/ie.css" rel="stylesheet"> <![endif]--> 

Haml comments are comments that included in the template file but not rendered in the final output. You specify them with -# and the same rules that applied to HTML comments apply here too:

%p The line below won't appear in the HTML 
-# The rest of this line is a comment 
%p The line above won't appear in the HTML, nor will the lines underneath 
-# 
  None of this nested text will appear 
  in our rendered output either 

This produces:

<p>The line below won't appear in the HTML</p> 
<p>The line above won't appear in the HTML, nor will the lines underneath</p> 

Adding Some Ruby Code

Whilst this article has focused on how you can write HTML using Haml, we couldn’t finish it without a brief bit on how to get some Ruby code into your template.

To insert some Ruby code, just add the '=' sign followed by the code. For example:

%p= Time.now 

The code will be evaluated and output into the markup wrapped in

tags like so:

<p>Sat Aug 06 15:06:09 +0100 2011</p> 

Running Haml from the Command Line

A great way to experiment with Haml is to run it from the command line. Just bung all your Haml code in one file and you can output the compiled template into another file like so:

haml input.html.haml output.html 

So, that was a quick look at how you can use Haml when writing your HTML. If you’ve not used Haml yet hopefully it’ll encourage you to give it a try. Don’t forget to check out the Haml website at http://haml-lang.com where you can find loads more info, a complete language reference and can even take Haml for a test drive.

Update: I’ve put all the Haml snippets from the article into a Gist on GitHub. Feel free to fork away: https://gist.github.com/1147666

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://jimlabs.heroku.com Jim Ruther Nill

    Hi!

    Nice article. However, I noticed one thing regarding the first example in the Comments section. I don’t think that code will compile successfully. Line 1 is commented out while line 2 is indented. I think that will raise an Illegal nesting error.

    • http://ianoxley.com Ian Oxley

      Yep, my bad. I think I’d got a bit carried away fixing some formatting issues in the example code :) I’ve corrected it in the article now and included a link at the end of the article to a Gist on GitHub with all the example code in.

  • http://mulleronrails.info Nick

    I see how HAML outputs all the html, but I’m a bit confused on how it runs the Ruby.

    The example you gave %p= Time.now is all fine and good, but what if I want to run ruby code that I don’t want to be in the html?

    In erb, this is easy. For example:

    Only the middle line is actually rendered to html.

    How would this look in HAML?

    • Michael Sell

      Prefix code you want to execute with a – if you don’t want it rendered.

      Eg:

      %p This is a paragraph
      - code to be executed
      = code to be displayed
      %p= code to be displayed in a paragraph

      • http://ianoxley.com Ian Oxley

        Thanks Michael. @Nick: it’s exactly as Michael says

  • alex

    Really cool ruby haml tutorial for sharing :D great job!

  • http://www.ApproachE.com/ Dmytrii Nagirniak

    I like HAML to such an extent that I want to use it for client-side development.

    So I created the project that seamlessly integrates with Rails 3.1.

    On the client you can now just write:

    JST.comment({name: ‘Dima’, text: ‘Awesome’})

    This will produce HTML based on the plain HAML template that is *precompiled* to native JavaScript.

    Have a look at the project: https://github.com/dnagir/pakunok

    I would appreciate some feedback.

    Cheers.

  • Munish

    Nice Article… thanks Ian