Haml: HTML Abstraction Markup Language

:: Development
September 13, 2006 - over 3 years ago
Platform: Ruby on Rails v1.1.6
Tested Browsers: All
Tag As: Rails, template engine, ERb
Editor: Pete Forde
Project Homepage: http://haml.hamptoncatlin.com/
Plugin Installation: ./script/plugin install svn://hamptoncatlin.com/haml/trunk haml
Thanks to everyone that came out for Hampton's talk at RailsConf Europe!
Haml is a new templating engine for Ruby on Rails. It is designed to be a high-level semantically awesome templating language that you would use in preference to RHTML in certain highly structured instances.
Abstracted from real projects, Haml encourages view/controller separation while rendering perfectly formatted, human readable XHTML with a minimum of overhead or learning curve.
Haml was created by , a developer with Unspace in Toronto. Previously, Hampton contributed find by hash condition searching to ActiveRecord.
Background
Frustrated with inconsistent and invalid markup that is generally symptomatic of the output of dynamic programming languages, Hampton decided that enough was enough, and set out to make "separation of content and code" more than just hyperbole by creating a templating engine that ties block level content elements with their corresponding CSS style definition information.
Ruby on Rails pushes so many boundaries: RJS, migrations, and partials were new concepts that blew our minds, and made other platforms try to catch up. RHTML didn't blow your mind at all; it's just JSP/ASP/PHP/etc all over again. Boring! Rails deserves a ground-breaking templating language.
What about "One language to rule them all"?
Part of the elegance of Ruby on Rails is that for most tasks you use one programming language - Ruby. Rails projects now mercifully include little if any hand-written SQL (thanks, ActiveRecord) and JavaScript (thanks, Prototype and RJS). However, the status quo today is that developers are still writing XHTML.
Haml is not an entirely new language, but an abstraction of XHTML for your views. It combines structured XHTML creation with inline Ruby, but also borrows the same language used to define CSS. Note that while there are several alternative template languages on the landscape, like Rails Haml is abstracted from real production code with the singular focus of making life better not just for developers, but for designers as well.
Haml is remarkably quick and simple to learn, and our experience is that interface developers find it a more natural way to think about building a page. claims that his productivity doubled using Haml, after factoring in how much harder it is to make markup errors.
Whitespace Active
One important design decision that Hampton made when designing Haml was to make it "whitespace active". This means that, unlike Ruby or XHTML, the whitespace in your view counts. Python is this way — tabs are crucial parts of the syntax. Hampton elected to use 2 spaces to signify a level of indentation. Be sure to setup your text editor carefully.
Enforcing DOM hierarchy with whitespace allows the template parser to make intelligent assumptions about where XHTML nodes are intended to close; it is this process that allows us to strip out most of the redundancy involved in writing XHTML.
As a bonus, a well formatted view is easy to interpret at a glance.
Let's see it
Haml provides a highly compact and elegant way to describe XHTML at an abstracted level, defaulting to norms where possible. As an example, pictured here is an admin layout abstracted from a real project:
Haml
!!!
%html
%head
%title Client Admin Site
%meta{"http-equiv"=>"Content-Type",
:content=>"text/html; charset=utf-8"}/
= stylesheet_link_tag 'tabbed'
= javascript_include_tag 'tabbed'
%body
#application
#header
.container
.statusbar
.logo
%strong Admin Interface
.menu= link_to 'logout',
:controller => 'account', :action => 'logout'
%br{:style=>"clear:both;"}/
.tabs
%ul.navigation
%li= link_to 'Member Approval', member_admin_url
%li= link_to 'User Management', user_admin_url,
:class => 'selected'
%li= link_to 'Pages', page_admin_url
%li= link_to 'Reports', reports_url
%li= link_to 'Help', '/'
#page
#content
//These will only render if there is
a non-false value returned from the helper
#errors= print_flash(:error)
#notice= print_flash(:notice)
= @content_for_layout
#sidebar= @content_for_sidebar || false
%hr/
#footer
%p= "Copyright Hampton Catlin 2006"
HTML Output
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Client Admin Site</title>
<meta content='text/html; charset=utf-8' http-equiv='Content-Type' />
<link href="/stylesheets/tabbed.css" media="screen" rel="Stylesheet" type="text/css" />
<script src="/javascripts/tabbed.js" type="text/javascript"></script>
</head>
<body>
<div id='application'>
<div id='header'>
<div class='container'>
<div class='statusbar'>
<div class='logo'>
<strong> Admin Interface</strong>
</div>
<div class='menu'>
<a href="/logout">logout</a>
</div>
</div>
<br style='clear:both;' />
<div class='tabs'>
<ul class='navigation'>
<li><a href="/admin/members">Member Approval</a></li>
<li><a href="/admin/user">User Management</a></li>
<li><a href="/admin/page" class="selected">Pages</a></li>
<li><a href="/admin/reports">Reports</a></li>
</ul>
</div>
</div>
</div>
<div id='page'>
<div id='content'>
<!-- This will only render -->
<div class="flash notice">Page Deleted</div>
//Content goes here
</div>
</div>
<div id='footer'>
<p>Copyright Hampton Catlin 2006</p>
</div>
</div>
</body>
</html>
Rendered Output
Not only can you use a combination of Haml, RHTML, and RXML templates interchangeably, but as an added bonus Haml automatically adjusts rendered output to the proper indentation level — even across partials!
Finally, any text content rendered inside a block level element is automatically line broken at 50 characters — going far to guarantee that the output of a Haml rendering will likely be the cleanest, easiest to read XHTML on the web.
Conclusion
Many ideas start out as an experiment, or a proof of concept. We can't wait for widespread adoption of Haml! By creating a culture of template language polyglots, Rails programmers will have a superior understanding of the framework they are using.
Haml as a case study represents a rare opportunity for anyone considering experimentation with ERB template parsing to see such a concept presented in working condition.. and with very usable results.
The first live client site to use Haml in production launched in August 2006.
Try it for yourself:
./script/plugin install svn://hamptoncatlin.com/haml/trunk haml