Type less! Use Pug Templates!
Tags: dohackathon, tutorial, html, webdev
Published: 2021-01-07 18:28:13

While I was working on the 24 CSS artworks for my [CSS Christmas Calendar](https://csschristmascalendar.com) 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 in yellow jacket](https://dev-to-uploads.s3.amazonaws.com/i/806qkeffssi8or6szn90.jpg)
<figcaption>Photo by <a href="https://unsplash.com/@charlesdeluvio" target="_blank">Charles Deluvio</a> on <a href="https://unsplash.com/s/photos/pug" target="_blank">Unsplash</a></figcaption>

[Pug.js](https://pugjs.org) 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](https://codepen.io) without any local setup.

Just create a new pen, go to the settings, and enable the Pug templating engine.

![Enable Pug templating engine on Codepen](https://dev-to-uploads.s3.amazonaws.com/i/wml7hurwu1ujqnqe65ch.png)

So how to write pug templates?

Here's a simple example:
```pug
.hot-chocolate
  .mug
    .mug__grip
    .mug__contents
```
<figcaption>Code from the <a href="https://codepen.io/johnnyfekete/pen/VwKKMKE" target="_blank">Hot chocolate with marshmallows</a> CSS art</figcaption>

that compiles to

```html
<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:
```pug
.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:

```pug
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:
```pug
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.

```pug
- 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*

```pug
- 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:

```pug
.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:
```pug
- 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:

```pug
- const menuItems = ['intro', 'about', 'portfolio', 'contact'];

ul
  each menuItem in menuItems
    li
      a(href=`#${menuItem}`)= menuItem
```

This will compile to:

```html
<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:

```pug
.sky
  - for (var i = 1; i <= 10; i++)
    .star
```

This will create 10 `<div class="star"></div>` elements inside the sky <div>.

I used this trick in almost all items, often combined with more complex parameters:

```pug
.sparkler-light
  - for (var spark = 1; spark <= 36; spark++)
    .spark(
      class=`spark-${spark}`
      style=`--spark-rotate: ${spark * 10}deg;
        --spark-delay: ${Math.round(Math.random() * 1000)}ms`
    )
```
<figcaption>Code from the <a href="https://codepen.io/johnnyfekete/pen/MWjveNj" target="_blank">Animated Christmas Sparkler</a> CSS art</figcaption>

This creates the following HTML
```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:

![Christmas Sparkler made with CSS](https://dev-to-uploads.s3.amazonaws.com/i/3pd7q5led9vodf5mdu7e.gif)
<figcaption><a href="https://codepen.io/johnnyfekete/pen/MWjveNj" target="_blank">Animated Christmas Sparkler</a></figcaption>

## 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](https://pugjs.org/api/getting-started.html). 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](https://www.ubercompute.com/pug-to-html) 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](https://devhints.io/pug).
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.