Writing pure HTML nowadays is very rare and I don’t think I know one person that does not use some kind of HTML preprocessor to write structure for a website. HAML is a one of these markup languages that abstract HTML and is mostly used in the Ruby on rails community but it is supported with many languages like javascript, python, lua, scala, php, .net, java.
There is no steep learning curve for HAML, so it’s just a few rules that you need to learn to get things rolling.
Doctype
!!!
3 exclamation marks takes care of the HTML5 DOCTYPE. Since XHTML is most likely not used anywhere I will not talk about those doctypes.
Automatic divs, tags, ids and classes
You can write an element with an id or a class attribute exactly as you do in CSS.
.header.main-header#header
Haml will assume that you are outputting a div tag since you did not mention any tag and it will have a class name header and main-header and an id with the value header.
<div class="header main-header" id="header">
Tags and nesting
If you would like to use other tags than divs, you should use the % before the tagname:
%span.authorname Joe Black
HAML is very much based on the indentation of the code, so it’s important to know that a nested text or element should have a 2 space indentation to work. Also tags don’t need to be closed.
%form.contact-form
%fieldset
%legend
Contact form
%input
I will also mention the empty tags like the br tag or the meta tag. To signal that this tag is empty, you need to put a / sign at the end.
%br/
%meta{"http-equiv" => "Content-Type", :content => "text/html; charset=UTF-8"}/
Composed attributes can be written in quotes and without colons.
Attributes
Adding attributes to tags in HAML can be done in 2 ways:
For the first approach, we use braces and inside we introduce each attribute with colons and the value with an arrow:
%input{:type => "email", :placeholder => ":Email"}
For composed attributes like data attributes we also write a composed syntax:
%figure{:title => "user image", :data => {:url => "./images/Pedro.jpg"}}
The second approach is more loose:
%html(xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en)
Comments
We can talk about 3 types of comments: haml comments, HTML comments and downlevel revealed comments.
Haml comments
-# This is a Haml comment in one line
-# This is a Haml comment in multiple lines
Second Line
Third Line
First of all this is already a Ruby code since it is introduced by a dash character but it only evaluates what is after the dash character and doesn’t display any code. It is also used for defining variables or doing operations like iterations. When writing multi-line comments it is very important to start de next lines aligned with the first lines text, so indentation is the key.
HTML comments
/
%p This is an HTML tag commented out
%span This is a span also commented out
By using a slash we order HAML to generate an HTML comment
Conditional comments
/[if IE]
%p This is a comment for Internet Explorer users
Variables and interpolation
Variables live in Ruby, so we introduce it by adding a dash character and we use it in interpolation with the #{ } syntax.
.target
This is a content
- id = "about"
.container{:id => "page-#{id}"
When we want to evaluate a Ruby code and also display it we should use the = sign.
- id = "about"
.target
This is a content
%p
= id
This way we display the id variable value as a text.
Loops
%ul
- list = ['Joe','Peter','Paul']
- list.each do |item|
%li
= item
The each method iterates through the list array and each item is represented one by one by the item variable. Then we display the item, introducing it with the = sign
You can also repeat n times an iteration:
- 120.times do |number|
= number
Using an interval and iterating through it, also works:
- (1..12).each do |month|
%p #{month}
Also you can set the starting point and the endpoint of the numbers that should be used.
- 10.upto(20) do |i|
= i
This will render 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 and 20.
Whitespace
You can trim a tag with the < character and take out whitespace from outside the tag with the >
%p<
%span
Hello
%pre><
Hi
Conditions
- loggedIn = true
- if loggedIn
%p This is a content for logged in users
- else
%p There is nothing for you sir, you are an outcast !
You can also write conditions inline:
- error = true
%p{"class" => "field #{"error" if error}
Of course this error variable can come from Ruby so the error variable was put there just for demonstration purposes.
In the interpolation we can use ternaries also:
- error = false
%input{"class" => "field #{error ? "error" : "success"}"}
Filters
Filters allow you to pass code from another language which will be parsed and compiled. We can write Javascript code that will be injected into a script tag, CSS code that will be injected into a style tag and also preprocessors are allowed. Markdown will be compiled into HTML and SASS into CSS.
:markdown
# Title
This is the **headline**
## Subtitle
For markdown filter you will need another extension called pandoc-ruby.
:css
body {
color: #999
}
A style attribute was introduced right on that spot with our css code.
:javascript
document.querySelector('.header').classList.add('opened');
A script tag is added and executed on that spot.
Conclusion
HAML is just another preprocessor to generate HTML easily by writing the shortest code and getting the full package in HTML code. We can write programmatically HTML code by using variables, each loops, if conditions. Also we have comments for HAML and comments for the HTML. It is mostly used in a Ruby on Rails environment because HAML is basic, but the magic comes from Ruby code. This means that in order to write a complex and advanced HAML code, you would need to know a fair amount of Ruby.