Learn Tailwind CSS - A Beginner's Guide
Published: 2020-11-30 18:09:30

This is a beginner-friendly guide to using [Tailwind CSS](https://tailwindcss.com/), 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](https://tailwindcss.com/docs/installation) 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](#tailwind-play)
* [CDN](#cdn)
* [PostCSS Plugin](#postcss-plugin)

## Tailwind Play
The simplest way to try out Tailwind is to use its interactive web browser mode over on [Tailwind Play](https://play.tailwindcss.com/). This allows for updates to an existing HTML page and visualizes the changes. It's a great first step along with the [Tailwind docs](https://tailwindcss.com/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.

```html
<!-- 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](https://dev-to-uploads.s3.amazonaws.com/i/tfva2qyozsihwnqqk2j0.png)

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

```html
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
```

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


```html
<!-- index.html -->
<html>
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link href="https://unpkg.com/tailwindcss@^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](https://dev-to-uploads.s3.amazonaws.com/i/gra59tiw7a3ubsiv7o4p.png)

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](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Values_and_units) 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.

```html
<!-- index.html -->
<html>
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link href="https://unpkg.com/tailwindcss@^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](https://dev-to-uploads.s3.amazonaws.com/i/6t3ihf8w95xhu4yq17e8.png)

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:

```html
<!-- index.html -->
<html>
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link href="https://unpkg.com/tailwindcss@^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](https://dev-to-uploads.s3.amazonaws.com/i/dd66p0mlwr1j4x7rrxlf.png)

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:

```html
<!-- index.html -->
<html>
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link href="https://unpkg.com/tailwindcss@^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](https://dev-to-uploads.s3.amazonaws.com/i/qnntsc33z040l1nw1cnq.png))

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](https://tailwindcss.com/docs/installation#using-tailwind-via-cdn). 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](https://youtu.be/21HuwjmuS7A) on this setup. These notes have a few updates but largely mimic his presentation.

**Note**: You'll need to [install npm](https://www.npmjs.com/get-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:

```javascript
// 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.

```javascript
// 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:

```javascript
// 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`.

```javascript
// 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
/* 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`.

```javascript
// 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.

```html
<!-- 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](https://www.npmjs.com/package/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](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]({{ site.url }}/assets/images/tailwind/button.png)

## 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](https://tailwindui.com), a set of paid pre-made UI components that can be added to a website if you aren't a designer yourself.