Type less! Use Pug Templates!
Johnny Fekete
Posted on January 7, 2021
While I was working on the 24 CSS artworks for my CSS Christmas Calendar I quickly realized that I would have to write <div>
and </div>
a million times.
Besides being very monotone, it is also extremely error-prone. It's so easy to forget closing a div
, or other elements.
I wanted to save myself from a lot of unnecessary keystrokes and headaches.
That's why I decided to give Pug - a HTML templating engine -
a try.
What Is Pug?
Pug.js is a HTML templating engine, which translates pug code to HTML tags.
It requires some configuration in your backend, so it gets compiled. But luckily, it's easy to get started on Codepen without any local setup.
Just create a new pen, go to the settings, and enable the Pug templating engine.
So how to write pug templates?
Here's a simple example:
that compiles to
<div class="hot-chocolate">
<div class="mug">
<div class="mug__grip"></div>
<div class="mug__contents"></div>
</div>
</div>
Let's highlight some important things here:
-
indentation is everything! if you start the next line under the previous, it will be a sibling HTML element. But if you press a
TAB
, it will be the children of it. - no need for closing tags. The proper indentation will take care of them automatically.
- use your existing CSS knowledge: if something starts with a
.
, it will be a class.#
stands for id.
Easy Peasy. Something More Complex?
So far we only worked with empty div
s.
But you can add content to them:
.title Santa Claus
.description.
a plump, white-bearded, red-suited, and jolly old man
in modern folklore who delivers presents to
children at Christmastime
As you could see, multiline content needs to be indented one level, and the element definition needs a .
at the end.
Changing the tag from div
is just as simple:
a.link I'm a link
span.highlight I'm a highlighted text
footer I don't even have a class
Finally, you can edit the elements attributes the following way:
input(type='text' name='address' autofocus)
a(href='https://csschristmascalendar.com' target='_blank')
Mixing Pug with JavaScript
As I mentioned, Pug is a templating engine written in JavaScript.
Therefore, you can combine it with any Javascript code, and that's where it's superpower begins.
- let authenticated = false;
.login(class=authenticated ? 'hidden' : 'visible')
Here the class changed based on a JavaScript variable. Notice, how class
is used as an attribute, and not in the selector.
Also, the plain JavaScript line starts with a dash -
to mark that it's not a template
- let length = 10;
ul.items(style=`height: ${Math.min(length * 2, 10)}rem`)
Here the height will be a maximum of 10rem.
Finally, one thing I found quite useful is combining pug with the random()
function:
.star(style=`transform: rotate(${Math.random() * 360}deg)`)
This will set a random rotate transform on the div
.
Conditional Rendering
One of the cool things in Pug is that it can conditionally render elements.
Here's an example:
- let authenticated = false;
.header
if (authenticated)
a(href='/logout') Sign out
else
a(href='/login') Sign in
This example will render either the Sign in or Sign out button, depending on the authenticated variable.
Loops That Will Save Your Time
If you have to render the same block of code multiple times, loops will save you from unnecessary repetition.
Let's start with a simple case, looping through an array of items:
- const menuItems = ['intro', 'about', 'portfolio', 'contact'];
ul
each menuItem in menuItems
li
a(href=`#${menuItem}`)= menuItem
This will compile to:
<ul>
<li><a href="#intro">intro</a></li>
<li><a href="#about">about</a></li>
<li><a href="#portfolio">portfolio</a></li>
<li><a href="#contact">contact</a></li>
</ul>
Notice, how I added an equal character =
after the <a>
tag. That to tell Pug that what comes after is a JavaScript variable, so it doesn't print the word menuItem for each link.
For loop is another one that I used heavily in the CSS arts. It repeats the same content n times.
It's important to note that for is not a Pug technique, but plain JavaScript. However, that's the beauty of it all: you can combine the two, without any problems:
.sky
- for (var i = 1; i <= 10; i++)
.star
This will create 10 <div class="star"></div>
elements inside the sky
I used this trick in almost all items, often combined with more complex parameters:
This creates the following HTML
<div class="sparkler-light">
<div class="spark spark-1" style="--spark-rotate: 10deg;
--spark-delay: 359ms"></div>
<div class="spark spark-2" style="--spark-rotate: 20deg;
--spark-delay: 887ms"></div>
...
<div class="spark spark-36" style="--spark-rotate: 360deg;
--spark-delay: 121ms"></div>
</div>
With the for loop I could add 36 sparks rotated by 10 degrees each, and with a random delay in their animation, that - combined with CSS - resulted in this:
Sounds Cool! What's Next?
Now you are ready to enable your Pug templating engine!
You can make more use of it by including other pug files, creating complex layouts, or even including markdown files.
Adding Pug to your projects is very easy, just follow the official documentation. It has very straightforward steps about the setup and integration.
If you just want to manually convert a Pug template to HTML, I found this online converter that did an amazing job for me, and it will certainly make it for you too.
Finally, if you need a quick overview of the most common Pug syntaxes, check this cheat sheet.
You can come back to it anytime you need a specific syntax, especially for the more complex elements.
I'd love to hear from you, and see how you implemented Pug in your projects.
Leave a comment below, and I'd be glad to answer your questions and comments.
Posted on January 7, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.