DEV Community

Jesse Wei
Jesse Wei

Posted on

Supercharge Your HTML&CSS Workflow With Pug and TailwindCSS

Coding in HTML and CSS can be time-consuming. For large HTML and CSS files, they can be hard to maintain as well.

A much better approach is to use HTML templating languages, such as Pug and CSS frameworks, such as Tailwind CSS, to generate your HTML and CSS code on the fly.

In this tutorial, I'll show you how to bootstrap such a project in no time using the create-pug-tailwindcss-app package I built and how to really leverage the power of Pug and Tailwind CSS to make your life easier.


Table of Contents


Prerequisites

  • You're expected to have basic knowledge about HTML templating languages. If not, I have a post covering the basics of Pug so feel free to check it out. You can also take a look at the official docs of Pug. I'll cover some more advanced usage of Pug in this tutorial too.
  • You're expected to have basic knowledge about Tailwind CSS. If not, check out its official docs, especially the Get Started and Core Concepts sections. They also have an interactive playground where you can try Tailwind CSS out easily.
  • I use VSCode as my editor with the Live Server extension installed. Any other editors that the extension supports should work as well. But if there's no compatible Live Server extension for your editor, you'd need to do a bit research to find a dev server with hot reload support.

How Pug Works

Pug is a templating language that when compiled, outputs HTML code. So instead of writing HTML directly, you write Pug code and then compile it to generate HTML.

For example, this Pug snippet,

doctype html
html
  head
    title My Site
  body
    h1 Hello, World!
    p This is my site.
Enter fullscreen mode Exit fullscreen mode

generates the following HTML:

<!DOCTYPE html>
<html>
  <head>
    <title>My Site</title>
  </head>
  <body>
    <h1>Hello, World!</h1>
    <p>This is my site.</p>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

If you want to know more about Pug, check out my post.


How Tailwind CSS Works

Tailwind CSS is a utility-first CSS framework. It provides a set of pre-defined CSS classes that can be used directly in HTML markup without having to write any CSS code from scratch (mostly).

Let's say I want to give the p element in the following markup a font size of 20px and a color of dark red, I can do,

<p class="text-xl text-red-900">Hello World</p>
Enter fullscreen mode Exit fullscreen mode

When compiled, Tailwind CSS adds the text-xl and text-red-900 classes to the output stylesheet (the CSS file we link in the head of our HTML) where the CSS of the classes are specified:

.text-xl {
  font-size: 1.25rem; /* 20px */
  line-height: 1.75rem; /* 28px */
}

.text-red-900 {
  color: rgb(124 45 18);
}
Enter fullscreen mode Exit fullscreen mode

You can see it's no magic here. We're still using CSS to style our page, just that instead of defining the classes and writing the CSS ourselves, Tailwind CSS does the heavy lifting for us.


Build and Deploy an Example in <10 Minutes

Now we've seen how Pug and Tailwind CSS work separately, it's time to put the pieces together. We'll build a sample page and this is how it looks like when finished:

Sample page to build

Sample page to build(Photo by Marek Piwnicki on Unsplash)

It's simple but looks good enough. More importantly, you can build it in less than 10 minutes without writing a single line of HTML or CSS!

Get Started

Bootstrapping a project that uses Pug and Tailwind CSS for the first time can be a bit tricky, so I created an npx tool to make your life easier.

To get started, just run the following command in your terminal (remember to replace your-project-name with your real project name):

npx create-pug-tailwindcss-app your-project-name
Enter fullscreen mode Exit fullscreen mode

Now, your project structure should look like this:

.
├── README.md
├── bin
│   └── cli.js
├── images
├── node_modules
├── package-lock.json
├── package.json
├── src
│   ├── index.pug
│   └── input.css
└── tailwind.config.js
Enter fullscreen mode Exit fullscreen mode

You would work with,

  • src/. This is where your Pug files and input CSS file (the CSS file to be compiled) reside.
  • images/. This is where you put your images.
  • tailwind.config.js. This is where you configure your Tailwind CSS or add global styles, if necessary.

You can ignore all the other directories and files in the project.

Pug to HTML

Open the src/index.pug file and replace its content with the following:

//- 1. We can define variables in Pug just like we do in Javascript
- var navItems = ['Top', 'Services', 'About Us', 'Contact'] 

doctype html
html(lang='ja')
  head
    meta(name="viewport", content="width=device-width, initial-scale=1")
    title Foo Company
    link(rel="stylesheet" href="style.css")
  body
    header
      div
        a(href="#") Foo Company
        nav 
          ul
            //- 2. Iteration makes code more concise and readable
            each item in navItems
              li
                a(href="#")= item
    main
      section
        img(src="kv.jpg", alt="key visual of Foo Company")
        h1 Foo Company
      section
        h2 Our Services
        div
          div
            h3 Service 1
            p Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi accumsan, sem et porttitor placerat, lacus risus molestie ligula, congue venenatis augue ante ac dui. Aliquam ipsum neque, tempus id magna eget, fringilla sollicitudin nunc. Phasellus non eros maximus, posuere elit in, vestibulum orci. Phasellus eget pellentesque ligula.
          div
            h3 Service 2
            p Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi accumsan, sem et porttitor placerat, lacus risus molestie ligula, congue venenatis augue ante ac dui. Aliquam ipsum neque, tempus id magna eget, fringilla sollicitudin nunc. Phasellus non eros maximus, posuere elit in, vestibulum orci. Phasellus eget pellentesque ligula.
          div
            h3 Service 3
            p Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi accumsan, sem et porttitor placerat, lacus risus molestie ligula, congue venenatis augue ante ac dui. Aliquam ipsum neque, tempus id magna eget, fringilla sollicitudin nunc. Phasellus non eros maximus, posuere elit in, vestibulum orci. Phasellus eget pellentesque ligula.
    footer
      div
        a(href="#") Foo Company 
        nav 
          ul
            each item in navItems
              li
                a(href="#")= item
      small Copyright © 2023 Foo Company
Enter fullscreen mode Exit fullscreen mode

Some interesting points to be noted:

  • At 1, we defined the items of our nav in an array just like we'd normally do in Javascript.
  • At 2, we used each expression to iterate our navItems variable which made the code much more concise and readable.

Now download the key visual image here, rename it as kv.jpg and put into the images/ directory.

Then run this command in your terminal to compile our Pug file into HTML:

npm start
Enter fullscreen mode Exit fullscreen mode

You should notice a dist/ directory is generated automatically in our project root. Within it, there is the compiled index.html and style.css files along with our key visual image.

Start your editor's Live Server extension and in the opened browser, click the dist directory. Our page should be displayed and should look like this by this point:

Sample page before CSS is applied

Sample page before CSS is applied

Add Tailwind CSS Classes

Now it's time to add Tailwind CSS classes to our markup to give our page a cool style. Due to the limit of the length of this tutorial, I cannot go through all the classes used to style our page. But as an example, let's give our header a light grey background color:

...
header.bg-slate-100
...
Enter fullscreen mode Exit fullscreen mode

Save your changes and the background color of the header should be changed in real-time in the browser. You can find more about the default colors you can use out of the box here.

As you saw above, styling our page is as easy as attaching Tailwind CSS classes to Pug tags. Our final src/index.pug looks like this:

- var navItems = ['Top', 'Services', 'About Us', 'Contact'] 

doctype html
html(lang='ja')
  head
    meta(name="viewport", content="width=device-width, initial-scale=1")
    title Foo Company
    link(rel="stylesheet" href="style.css")
  body
    header.w-full.bg-slate-100.fixed.top-0.left-0.z-10
      .container.flex.justify-between.items-center
        a.font-bold(href="#") Foo Company
        nav 
          ul.flex.justify-end
            each item in navItems
              li
                a.block.p-4(href="#")= item
    main
      section.relative.mb-12
        img.w-full.h-screen.object-cover.brightness-50(src="kv.jpg", alt="key visual of Foo Company")
        h1(class="text-6xl font-bold text-white absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2") Foo Company
      section.container.mb-12
        h2.text-4xl.font-bold.mb-6 Our Services
        .grid.grid-cols-3.gap-12
          div
            h3.text-2xl.font-bold.mb-3 Service 1
            p Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi accumsan, sem et porttitor placerat, lacus risus molestie ligula, congue venenatis augue ante ac dui. Aliquam ipsum neque, tempus id magna eget, fringilla sollicitudin nunc. Phasellus non eros maximus, posuere elit in, vestibulum orci. Phasellus eget pellentesque ligula.
          div
            h3.text-2xl.font-bold.mb-3 Service 2
            p Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi accumsan, sem et porttitor placerat, lacus risus molestie ligula, congue venenatis augue ante ac dui. Aliquam ipsum neque, tempus id magna eget, fringilla sollicitudin nunc. Phasellus non eros maximus, posuere elit in, vestibulum orci. Phasellus eget pellentesque ligula.
          div
            h3.text-2xl.font-bold.mb-3 Service 3
            p Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi accumsan, sem et porttitor placerat, lacus risus molestie ligula, congue venenatis augue ante ac dui. Aliquam ipsum neque, tempus id magna eget, fringilla sollicitudin nunc. Phasellus non eros maximus, posuere elit in, vestibulum orci. Phasellus eget pellentesque ligula.
    footer.w-full.bg-slate-900.text-white
      .container.flex.justify-between.items-center.mb-6
        a.font-bold(href="#") Foo Company 
        nav 
          ul.flex.justify-end
            each item in navItems
              li
                a.block.p-4(href="#")= item
      small.block.text-center Copyright © 2023 Foo Company
Enter fullscreen mode Exit fullscreen mode

For the other classes I used in the page, check out Tailwind CSS docs. Just hit CMD + / (Mac OS) or Ctrl + / (Windows) and type in the property you want style (e.g. text color).

Go to Production

To bring our page to production, just run:

npm run build:prod
Enter fullscreen mode Exit fullscreen mode

The dist/ directory is re-generated. The only difference of this version of dist/ and the dev version is the index.html in the production dist/ is minified.

Now you can pick your favorite hosting service and upload the generated HTML, CSS and image files to it to publish your page.


Conclusion

It can sound daunting to build a website using multiple new technologies other than HTML and CSS. But as I showed you in this tutorial, with a bit of good tooling, we can create a modern page times faster with Pug and Tailwind CSS than with traditional HTML and CSS workflow.

The benefit of generating HTML and CSS dynamically doesn't stop here. When the codebase of your page is large, for example, it makes sense to componentize your page. This involves creating reusable partials and mixins which Pug supports out of the box. This way, when you want to make a change to a part which is used in multiple places across the page, you only have to make the change once to the relevant partial or mixin. This makes your code much more maintainable.

Also, by leveraging the functionality of Pug to pass data or data file to the compiler, you can separate the data and UI layer of your code, which makes it far easier to generate versions of the same page in different languages, for example.

Latest comments (2)

Collapse
 
bassohr profile image
Michael

Uhh. Its less to write — but hard to read.

Collapse
 
ryzhykovoleksandr profile image
ryzhykovoleksandr

How can I add screen sizes for this project?