4 Templating Systems to Write Quicker, Cleaner HTML
Alternatives to vanilla HTML
Published on
Apr 11, 2019
Read time
9 min read
Introduction
HTML is the first language that many developers learn. While learners of CSS and JavaScript soon encounter tools to augment these languages — such as Sass (for CSS) or Babel (for JavaScript) — the same is rarely true of HTML.
Since many HTML learners are total beginners, introducing new technologies would probably feel like too much too soon. But that means systems used to enhance and improve HTML get left off the curriculum, and many beginner-to-intermediate developers may not realise the options available to them.
So, in this article, we’ll explore four of the most popular templating engines for HTML. We’ll look into why you might choose to use them, and where you’re likely to encounter them in other tech-stacks. I’ll also provide sample CodePens for each one. By the end of the article, you should feel equipped with several options for writing faster, more concise HTML in your projects, whether your go-to programming language is JavaScript, Ruby or something else. Let’s dive in!
The problem with vanilla HTML
HTML stands for Hypertext Markup Language, and as a markup language, it does not have the functionality of a typical programming language. Markup languages are designed to be easy-to-read by humans as well as machines, and they typically use tags to define elements within a document.
But what makes HTML easy-to-read is also one of its limitations:
- Any interactive elements, such as the
onclick
event, must be defined in the language in advance; in vanilla HTML, new events cannot be added by users. - It is not simple to add dynamic data into vanilla HTML.
- If you want to generate repeated elements, there are no in-built shortcuts in the form of loops (
for
,while
and so on). Nor is there an in-built method for handling conditionals (if … else
orswitch
statements). - Vanilla HTML doesn’t allow users to define new, re-usable tag types.
- Lastly, even though HTML is simple to read, it could be faster to write. Opening and closing tags can be a pain to type again and again, and parts of HTML may seem verbose, e.g.
button type="button" /
.
No templating system or HTML-like syntax solves all of these issues — in part because there’s no need for HTML to become a complete programming language. But these systems do intend to make writing HTML faster and more capable!
The alternatives to HTML templating systems
Before moving on to the four HTML templating systems, it’s worth mentioning a couple of alternatives ways to improve on vanilla HTML. Depending on what technologies you use, these may be all you need.
Emmet Abbreviations
These provide a much quicker way of writing vanilla HTML, and so it solves one of HTML’s main shortcomings: speed of writing. Emmet is available as a plugin for pretty much every major code editor — and as a bonus, it even offers snippets for CSS.
As an example of what Emmet can do for you, take this abbreviation: navigation#main>img.logo+ul#navigation>li*5>a{Link $}
.
The abbreviation above produces the following HTML code, but it takes a fraction of the time to write:
<navigation id="main">
<img src="" alt="" class="logo"></img>
<ul id="navigation">
<li><a href="">Link 1</a></li>
<li><a href="">Link 2</a></li>
<li><a href="">Link 3</a></li>
<li><a href="">Link 4</a></li>
<li><a href="">Link 5</a></li>
</ul>
</navigation>
Here, #
denotes ID, .
denotes class, +
signifies a sibling, and >
signifies a child. You can specify internal text with curly braces {}
, use *
to multiply elements, and use $
to number your repeated elements.
For a list of what Emmet abbreviations can do, check out the official cheat sheet. You can add Emmet abbreviations to your code editor-of-choice using one of the links below:
- VSCode / Sublime Text / Atom / Vim / Other Platforms
(Often, through the use of extensions or a bit of extra configuration, you can also use Emmet Abbreviations to write JSX. I explained how to do this with Visual Studio Code in a previous article.)
HTML in other languages
There are several technology-specific solutions to writing HTML. React.js has JSX, Ruby has eRuby (or ERB), and PHP has, well, “HTML in PHP”. For Java, there’s JSP (JavaServer Pages), while ASP.NET uses so-called Razor syntax to demarcate HTML code. The list goes on.
These solutions solve many of the limitations of vanilla HTML, mainly by allowing the possibility of loops, conditionals, and other programming-language features.
However, we won’t look into these solutions in detail because — unlike the remainder of technologies in this article — you don’t really have a choice whether or not to use these in your projects. You could use React without JSX, but that’s not what it’s built to do: you’d be missing out on a lot of great features, and probably causing yourself more trouble than if you just used JSX. As such, you’ll pick up these solutions as and when you choose to learn the technologies.
The remainder of this article focuses on templating systems, which mostly come into play in situations where you’d otherwise be using plain old vanilla HTML.
1. Pug (a.k.a Jade)
Underlying Language: JavaScript
Pug is the main focus of this article because it is built on top of JavaScript — the language of web development, and a popular choice here on Medium!
The markup used by Pug.js is much simpler than regular HTML, but it can take a little while to get used to. It, like most of the templating systems we’ll be discussing, achieves much of its simplicity by relying on line breaks and indentation.
So, whereas many languages allow you to get away with non-standard formatting and still work correctly, Pug does not. Changing the indentations will change the functionality of the code. Pug looks like this:
article#main h1 The Title h2 The Sub-title div(class="article-body") p The main body.
This is equivalent to the following regular HTML:
<article id="main">
<h1>The Title</h1>
<h2>The Sub-title</h2>
<div class="article-body">
<p>The main body</p>
</div>
</article>
It’s clear from even a small example that Pug.js takes up less space and — without carets or closing tags — it is a lot quicker to write. The best place to learn about Pug is from its official docs, but here we’ll explore a couple of useful features.
Loops in Pug
Pug allows you to write inline JavaScript code, which is demarcated by using -
, =
and !=
— depending on whether you want to use buffered, unbuffered, or unescaped unbuffered JavaScript.
One of the most useful outcomes of this is the ability to write loops. So, for example, we can use a for
loop to make a simple list of 3 items and number them accordingly:
- for (let x = 0; x 3; x++) li= 'Item ' + (x + 1)
This is equivalent to the following HTML.
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
Or, to iterate through the items in an array, we can use:
- var colors = ["Red", "Yellow", "Green", "Blue"] each item in colors li= item
This would be the same as writing:
<li>Red</li>
<li>Yellow</li>
<li>Green</li>
<li>Blue</li>
Conditionals in Pug
Another useful feature is the ability to use conditionals within the markup code. We can render one of two alternatives using a simple boolean, such as:
- var isTrue = true if isTrue p Boolean is TRUE else p Boolean is FALSE
Or, for a more complex example, you can use case
, which is shorthand for JavaScript’s switch
statements:
- var raceResult = 7 case friends when A p You won the race! when 1 p You were the runner up! default p You finished the race after #{raceResult - 1} other runners!
Pug.js ScratchPad
To try Pug.js yourself, you can use the following CodePen.
- Above the horizontal line, you can see your rendered Pug.js.
- Below the line, you can see the equivalent HTML markup.
See the Pen Pug Scratchpad by Bret Cameron (@BretCameron) on CodePen.
Another way to test Pug is to go to the Pug website and use your browser’s console: type pug.render("p Hello World!")
and press enter!
2. HAML
Underlying Language: Ruby
HAML stands for HTML Abstraction Markup Language. Like Pug, it uses indentations to define nested elements. It was developed as an alternative to Ruby’s ERB, but it can also be used in place of PHP, ASP, and — of course — vanilla HTML.
The main difference between HAML and Pug.js is that programming in HAML is done via Ruby. So, if you’re using JavaScript-based tech stack, Pug may be the safer choice.
In order to loop through items in HAML, we’d need to borrow from Ruby syntax, like so:
- (1..10).each do |i|
%div #{i}
This prints the numbers 1 to 10, each in a separate div.
Or, to demonstrate a simple conditional, we could use the following. Notice that all the logic is preceded by a dash -
.
- isSunny = false
- if isSunny
%p Let's go outside!
- else
%p I'd rather stay inside.
HAML Scratchpad
This CodePen demonstrates the exact same capabilities as Pug’s above.
See the Pen HAML Scratchpad by Bret Cameron (@BretCameron) on CodePen.
Notice that comments in Pug become part of the rendered HTML while they do not in HAML.
3. Slim
Underlying Language: Ruby
Slim is another popular choice, and it has a lot in common with HAML: that’s because they’re both based around Ruby. Like HAML, it is possible to embed JavaScript in Slim, and the thorny question of whether to choose one over the other should probably be left as a topic of debate for the Ruby community!
On the surface, Slim seems to use slightly more minimalist syntax than HAML. Perhaps the most significant syntactic difference is that Slim uses |
for each block of text, while HAML uses %
before each tag.
/ Slim tag(attr= “value”) | text-## HAML %tag{attr: “value”} text
Because the differences between Slim and HAML are minimal, you probably don’t need any further guidance before trying it out:
See the Pen Slim Scratchpad by Bret Cameron (@BretCameron) on CodePen.
4. Markdown
Finally, we come to Markdown. This is not like the other systems discussed so far, as it doesn’t come with any programming-language capabilities, and you’ve almost certainly encountered it before. Most README files on GitHub are written using Markdown (using the .MD
file extension ).
Though Markdown lacks programming features like loops and conditionals, it is superior to vanilla HTML by being both extremely simple to write and highly-readable by others — whether or not the code is actually rendered. It is also a lot easier to read than .txt
, the file extension traditionally used for READMEs.
In Markdown h1
, h2
, and h3
are written as #
, ##
and ###
. A single line of code is distinguished using `
while a block of code uses ```
, and links are written using a combination of square brackets and parentheses. For a fuller list of the shortcuts, check out the official cheat sheet.
Tables are probably the most fiddly part of Markdown, but if you search “generate markdown table”, you’ll find plenty of tools to make the process easier. To see examples of all of these features and more, check out the CodePen below.
See the Pen Markdown Scratchpad by Bret Cameron (@BretCameron) on CodePen.
Conclusion
I hope this article was useful, and that it has opened your eyes to the world of HTML templating.
The four templating systems chosen for this article are just a handful of what’s on offer. They were chosen partly for their popularity, and partly because you can easily try them out in CodePen.
I’d also like to give an honourable mention to Handlebars.js. It allows you to write code identical to vanilla HTML, except that you can insert JavaScript expressions using single, double or triple curly braces {}
, making it pretty similar to JSX, but without requiring React.
Bonus: Get Pug.js running on your local machine
CodePen makes it easy to try out the various templating systems described in this article, but what if you want to use them on your local machine? As an example, I’ll walk you through one way to test out Pug.js in a local project.
One of the places you’re most likely to encounter Pug is Express.js. So, to test it out, let’s create a simple Express project. If you’ve never done this before, I’ll provide all the necessary to code to set up a very simple server.
1. Ensure you have Node installed, then navigate to a folder of your choice in the terminal and type:
$ npm init
You can accept all the defaults except, for the sake of convention, let’s useserver.js
— rather than index.js
— as our main file.
2. Next, we’ll want to install a minimum of three dependencies: Express (to set up a simple server), Nodemon (to automatically refresh that server), and Pug. To do that, type the following in the terminal.
$ npm i -s express pug nodemon
3. Let’s create our server.js
file. This article isn’t a back-end tutorial, so feel free to copy and paste the following code without changing anything. This will set up a simple server on port 1337 of your localhost.
// Import Express
const express = require("express");
const app = express();
// Import Pug
const pug = require("pug");
// Choose a port
const port = 1337;
// Listen for connections on the specified port
app.listen(port, () => console.log(`Listening on port ${port}!`));
// Routes HTTP GET requests to the root path
app.get("/", (req, res) =>
res.send(
pug.renderFile("template.pug", {
name: "John Smith",
})
)
);
The key things to note are that we are importing pug using require()
, and we’re then using the renderFile()
method to display the contents of a file called template.pug
. This method the only part of the file you might want to change, so you can add or remove dynamic data like name: 'John Smith'
.
4. Now let’s create template.pug
. This is your Pug sandbox to try whatever you like! If you need some inspiration, why not grab a block of code from the section on Pug, above? Try inserting #{name}
to access your dynamic variable!
5. Before running your program, add the following to the scripts
object in package.json
, to allow the server to reload automatically whenever you make a change.
"scripts": {
"nodemon": "nodemon server.js"
},
5. Lastly, type nodemon
into the terminal. You can now navigate to http://localhost:1337
on your web browser to see your Pug.js code being rendered!
Related articles
You might also enjoy...
How To Make Lava Lamp-Style Blob Animations With HTML and CSS
No JavaScript needed with the power of SVG filter elements
3 min read
Create Interactive Visuals with JavaScript and HTML5 Canvas
How to Make Two Animated, Interactive Hero Sections
12 min read
How To Automatically Resize an iframe
Use HTML and Vanilla JavaScript to create dynamic iframes, acting as if they’re part of the parent window
21 min read