This is a beginner-friendly guide to using Tailwind CSS, a relatively new but immensely popular and likely game-changing CSS framework. Tailwind adopts a utility-first approach which makes it easy to customize and even easier to maintain as a project’s CSS grows in size.

CSS itself is difficult to manage in large projects and this is further exacerbated by traditional CSS frameworks, like Bootstrap, Foundation, and others which come with a long library of predefined components for common items like buttons, nav bars, footers, and so on. In short, CSS quickly becomes a mess: hard to write, hard to reason about, and even harder to update.

Tailwind solves many of these challenges by taking a lower-level approach: providing CSS helper classes that can be used to create and customize any design. It’s best to see this in action though by giving Tailwind a spin yourself.

Unfortunately, installing Tailwind CSS can be quite challenging as the official guide makes clear. While you might need all the bells and whistles for a full-fledged project, most of Tailwind can be used via a CDN and a single HTML file. This guide starts off showing how to use the CDN approach, then moves on to the full Node and everything else option after that.

Table of Contents

Tailwind Play

The simplest way to try out Tailwind is to use its interactive web browser mode over on Tailwind Play. This allows for updates to an existing HTML page and visualizes the changes. It’s a great first step along with the Tailwind docs to try out various features and the general Tailwind approach.

CDN

The second easiest approach–and the one I’d recommend starting with–is to use Tailwind CDN in a single HTML file. That way you have full control and can mimic a real-world development experience.

To start, create a new folder called tailwind-cdn and navigate into it. Then create a file called index.html.

$ mkdir tailwind-cdn
$ touch index.html

Let’s begin with a basic HTML5 template that will just have a div, a headline, and some paragraph text.

<!-- index.html -->
<html>
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
  <div class="container">
    <h1>Hello, Tailwind!</h1>
    <p>Let's learn how to use this new CSS framework.</p>
  </div>
</body>
</html>

From your command line, since you are in the tailwind-cdn folder, you can open this file in a web browser actually. So do that!

$ open index.html

Static HTML

To add the Tailwind CDN all we have to do is update our <head> section with the following line:

<link href="https://unpkg.com/[email protected]^2/dist/tailwind.min.css" rel="stylesheet">

Here is what the complete updated index.html file should look like.

<!-- index.html -->
<html>
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link href="https://unpkg.com/[email protected]^2/dist/tailwind.min.css" rel="stylesheet">
</head>
<body>
  <div class="container">
    <h1>Hello, Tailwind!</h1>
    <p>Let's learn how to use this new CSS framework.</p>
  </div>
</body>
</html>

If you save the file changes and refresh your web browser you’ll see that all formatting was stripped.

Static HTML

Our text is pretty cramped on the current webpage, no? It would be nice to add some margin padding horizontally to the sides of our text and vertically in between the text itself.

To add side padding to our existing <div class="container"> we merely add the class mx-5 so it becomes <div class="container mx-5">:

  • m stands for margin
  • x means apply to the x-axis
  • 5 represents the relative unit length which is rem for Tailwind

The same logic applies for adding vertical padding to the text within the <p> tags which becomes <p class="my-5">, albeit using y for the y-axis instead of x for the x-axis.

<!-- index.html -->
<html>
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link href="https://unpkg.com/[email protected]^2/dist/tailwind.min.css" rel="stylesheet">
</head>
<body>
  <div class="container mx-5">
    <h1>Hello, Tailwind!</h1>
    <p class="my-5">Let's learn how to use this new CSS framework.</p>
  </div>
</body>
</html>

Refresh your web page again and you’ll see both the horizontal and vertical margins now added.

P w/ MY

Let’s continue on by using Tailwind CSS to update the font for our <h1> text. To control the size, we’ll add text-2xl and to make the font bold we’ll add font-bold. The updated class is therefore: <h1 class="text-2xl font-bold">

Here is the complete code:

<!-- index.html -->
<html>
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link href="https://unpkg.com/[email protected]^2/dist/tailwind.min.css" rel="stylesheet">
</head>
<body>
  <div class="container mx-5">
    <h1 class="text-2xl font-bold">Hello, Tailwind!</h1>
    <p class="my-5">Let's learn how to use this new CSS framework.</p>
  </div>
</body>
</html>

Refresh your webpage again and you’ll see the changes in action.

H1

One more example to demonstrate Tailwind CSS in action is around styling buttons. In our case, let’s add a “Sign up here!” button in blue that turns darker blue upon over. The code looks like this:

<!-- index.html -->
<html>
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link href="https://unpkg.com/[email protected]^2/dist/tailwind.min.css" rel="stylesheet">
</head>
<body>
  <div class="container mx-5">
    <h1 class="text-2xl font-bold">Hello, Tailwind!</h1>
    <p class="my-5">Let's learn how to use this new CSS framework.</p>
    <button class="text-white font-bold bg-blue-600 hover:bg-blue-800 py-2 px-4 rounded">
      Button!
    </button>
  </div>
</body>
</html>

In order Tailwind is doing the following:

  • text-white sets the font text to white
  • font-bold sets the font to bold
  • bg-blue-600 sets the background color to blue with the 600 shade
  • hover:bg-blue-800 sets the hover background color to darker blue (800)
  • py-2 sets the vertical padding (py) to 2 rems
  • px-4 sets the horizontal padding px) to 4 rems
  • rounded makes the button edges rounded

Save your changes and refresh the webpage to see the changes in action:

Button

And voila! A lightning fast introduction to Tailwind and a taste for its new approach to writing CSS.

The CDN option is a great way to get started but it has some limitations as noted in the docs. The recommended approach is to use Tailwind as a PostCSS plugin to take advantage of all its features. We’ll cover that in the next section.

PostCSS Plugin

Tailwind CSS is ultimately a PostCSS plugin so to get the most of out Tailwind in terms of features and performance, it should be run as such. Doing so requires a little more setup than using a CDN but it’s very doable. Tailwind creator Adam Wathan released a YouToube series in 2019 on this setup. These notes have a few updates but largely mimic his presentation.

Note: You’ll need to install npm if you haven’t already on your local computer.

To start, create a new directory on your computer and enter into it. I’ve decided to call mine tailwind-fun.

$ mkdir tailwind-fun
$ cd tailwind-fun

The first step is to create a basic package.json file, which can be done with following command from your Terminal:

$ npm init -y

My resulting file looks as follows:

// package.json
{
  "name": "wailwind-fun",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Next, install tailwindcss as well as some tools to help process CSS through a chain of PostCSS plugins including postcss itself, postcss-cli, and autoprefixer which automatically adds vendor plugins to your CSS prefixes.

$ npm install tailwindcss postcss postcss-cli autoprefixer

Look inside your package.json file which now has a new dependencies section with these plugins. A package-lock.json file has also been created for the first time but you don’t need to inspect it.

// package.json
{
  "name": "tailwind-fun",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "autoprefixer": "^10.0.2",
    "postcss": "^8.1.10",
    "postcss-cli": "^8.3.0",
    "tailwindcss": "^2.0.1"
  }
}

In order to customize Tailwind later on, we’ll need a tailwind.config.js file which can be created with the following command:

$ npx tailwind init

Here’s the resulting file:

// tailwind.config.js
module.exports = {
  purge: [],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
}

Next, create a postcss.config.js file in your root directory (aka within tailwind-fun in this cas) to specify what PostCSS plugins to use. Currently, our two plugins are tailwindcss and autoprefixer.

// postcss.config.js
module.exports = {
  plugins: [
    require('tailwindcss'),
    require('autoprefixer'),
  ]
}

Tailwind works by looking through a CSS file for custom markers and replacing them with Tailwind’s generated code. Create a new CSS file called tailwind.css within a new css folder.

$ mkdir css
$ touch css/tailwind.css

Then within the file, add three directives for base, components, and utilities. When our CSS is compiled through PostCSS, Tailwind will find each and replace them accordingly with Tailwind code. We’ll see what this means in a moment.

/* css/tailwind.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

The last step before building Tailwind is we need a simple script to process our CSS through PostCSS plugins. In the existing package.json file, add a build script that uses postcss-cli, takes css/tailwind.css as its input file, and specifies output to a new file called public/build/tailwind.css.

// package.json
{
  "name": "tailwind-fun",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "postcss css/tailwind.css -o public/build/tailwind.css"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "autoprefixer": "^10.0.2",
    "postcss": "^8.1.10",
    "postcss-cli": "^8.3.0",
    "tailwindcss": "^2.0.1"
  }
}

Now build it! On the command line run npm run build!

$ npm run build

A newly generated CSS file processed through PostCSS is now available in our output location. Open up the file located at public/build/tailwind.css and take a look.

This is a long, long file populated by the three directives–base, components, and utilities–referenced in the tailwind.css file.

To look at what base provided, look at the top of the file which includes modern-normalize, a set of resets to try to normalize how all web browsers display CSS. The first 540 or so lines comes from base and are global resets.

If you scroll down to line 549 we see a .container class, the solo component class injected into CSS wherever we added @tailwind components. After the container class there are a bunch classes like appearance-none, bg-fixed, etc which are simple utility classes added wherever the @tailwind utilities directive was found. Note that appearance-none has vendor prefixed properties such as webkit-appearance and -moz-appearance, which were added by autoprefixer.

With this machinery in place, let’s create a simple HTML file and finally use Tailwind properly! Create a simple HTML file called index.html within the public/ folder.

$ touch public/index.html

Then fill out a basic HTML template similar to what we had in the CDN section. The only change is that we’re importing tailwind.css from the build folder, rather than via a CDN.

<!-- public/index.html -->
<html>
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link href="/build/tailwind.css" rel="stylesheet">
</head>
<body>
  <div class="container mx-5">
    <h1 class="text-2xl font-bold">Hello, Tailwind!</h1>
    <p class="my-5">Let's learn how to use this new CSS framework.</p>
    <button class="text-white font-bold bg-blue-600 hover:bg-blue-800 py-2 px-4 rounded">
      Button!
    </button>
  </div>
</body>
</html>

A nice tool to automatically reload our browser based on text changes is called live-server. It is lightweight and can be installed globally as follows:

$ npm install -g live-server

Then point it at our public folder:

$ live-server public

This will bring up http://127.0.0.1:8080 in your web browser where we can see the same basic text and styling as we had in the previous section. This confirms the installation of Tailwind is working!

Button

Conclusion

This guide is still in-progress but I hope the setup instructions helps anyone looking to learn more about Tailwind. I’ll add more content as time allows.

Note that since Tailwind does not come with a design in-and-of-itself, many developers reach for Tailwind UI, a set of paid pre-made UI components that can be added to a website if you aren’t a designer yourself.