Setting Up Tailwind CSS in Laravel
Tags: laravel, php, tailwindcss, webdev
Published: 2021-08-31 12:35:55

## Introduction

<a href="https://tailwindcss.com/" target="_blank" rel="noopener noreferrer">Tailwind CSS</a> is a really cool CSS framework that you can use when building your applications and websites. In fact, I think it's that cool that since it's release, I've switched away from using <a href="https://getbootstrap.com/" target="_blank" rel="noopener noreferrer">Bootstrap</a> as my go-to framework for new projects and use Tailwind instead.

In this article, we're going to take a quick look at what Tailwind CSS is and why I think it's useful. We're then going to step through two different ways of how to set up Tailwind in your <a href="https://laravel.com/" target="_blank" rel="noopener noreferrer">Laravel</a> projects.

## What is Tailwind CSS?

Tailwind is a utility-first CSS framework that you can use to style your website directly in your HTML. As an example, it provides you with CSS classes such as `flex`, `pt-4`, `text-center` so that you can have granular control.

To give an example, let's look at how you might make a button using Tailwind:

```
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
  Button
</button>
```

If we wanted to make this same style button using Bootstrap, we'd probably do something like this:

```
<button class="btn btn-primary">
  Button
</button>
```

As you can see, we're adding individual CSS classes to the markup, rather than having one or two classes like you would in Bootstrap.

Now, don't worry, I know what you're thinking... "That HTML looks really messy and overcomplicated. The Bootstrap version looks so much better and easier to understand!". I thought the same thing when I first started using Tailwind. I just thought that it was a bit of a fad that would probably die down after a few months. But, I gave it a try anyway so that I could make a more informed decision. I loved it!

Of course, it felt a little bit weird at first, but after an hour or two it felt really natural to use. When I was using Bootstrap, I always felt like I was fighting the built-in CSS styles to get anything done. It was great for throwing together sites really quickly, but to tailor them to my own liking, I had to override a lot of styles. But with Tailwind, if I wanted to quickly add a style to a button, it was as easy as adding it straight to the HTML.

If you're interested in reading more about why Tailwind is useful, Adam Wathan (the creator of Tailwind) has a <a href="https://adamwathan.me/css-utility-classes-and-separation-of-concerns/" target="_blank" rel="noopener noreferrer">really interesting article</a> about it that I'd recommend reading.

## Using the CDN

The easiest (but not necessarily the best) way to get started with Tailwind is to add the stylesheet to your HTML using the CDN. This is particularly useful if you want to quickly prototype an idea or just have a play around with the framework.

To get started, you just need to add the following line to into the `<head>` section of your HTML:

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

Although this is the quickest way to add Tailwind to your project, I'd probably advise against it for any live projects, because:

- The size of the CSS file is larger than it would be if bundled after installing via NPM.
- You can't customize Tailwind's default theme.
- You can't use any directives like @apply, @variants, etc.
- You can't enable additional variants like `group-focus`.
- You can't install third-party plugins.
- You can't tree-shake unused styles.

## Using NPM

If you're intending on using Tailwind in a project that's going to be live, it's much better to install it using NPM. By doing this, you aren't affected by the downsides that I stated above like when using the CDN. So, let's take a look at how to get started:

### Installing Tailwind

To install Tailwind, you'll just need to run the following command:

```
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
```

### Setting up Your Tailwind Config

Now that we have Tailwind installed, we can run the following command to create a blank `tailwind.config.js` file:

```
npx tailwindcss init
```

You should now have a `tailwind.config.js` that looks like this:

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

This is the file that you might use when you need to make changes to your theme or install plugins. As an example, if we wanted to define 'Poppins' as our default 'sans' font, we could update the file like so:

```
module.exports = {
  purge: [],
  darkMode: false, // or 'media' or 'class'
  theme: {
    fontFamily: {
      'sans': ['Poppins', 'ui-sans-serif', 'system-ui'],
    },
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
}
```

### Configuring Laravel Mix

Now that we have Tailwind installed and configured ready to go, we can set up <a href="https://laravel-mix.com" target="_blank" rel="noopener noreferrer">Laravel Mix</a> so that our CSS is bundled whenever we build our assets.

I'm going to make the assumption here that you're using the default `app.css` file here that comes with a fresh Laravel installation. But if not, you can update the first parameter in the `postCss()` method to match your main CSS file path.

I'm also going to make the assumption that your `webpack.mix.js` file still looks the same as the one that comes in the fresh default Laravel installation.

Let's add the necessary `require()` method to our `postCss()` method in the `webpack.mix.js` file like so:

```
const mix = require('laravel-mix');

mix.js('resources/js/app.js', 'public/js')
    .postCss("resources/css/app.css", "public/css", [
        require("tailwindcss"),
    ]);
```

### Adding Tailwind to Your Application's CSS

We're almost there! Now that we've installed and configured Tailwind, we need to add the styles to our main CSS file.

I'm going to make the assumption here that we're using the `resources/css/app.css` CSS file mentioned above. All we need to do is open up the file and add the following to the top:

```
@tailwind base
@tailwind components
@tailwind utilities
```

Tailwind should now be added to your project's CSS file and you should be able to start using it right away. You'll also need to remember to add it to the top of your HTML:

```
<!doctype html>
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
```

Congratulations, you've now got Tailwind installed ready to use in your project!

## Purging Unused CSS Classes

I'd recommend configuring Tailwind to purge unused CSS classes from your application's CSS file.

As a really basic example, let's imagine that you're only using the `text-blue-500` class in your application. It wouldn't make sense for us to include all of the other classes that Tailwind provides in our application's CSS. If we included all of the unused classes, we would be increasing the size of our CSS file which can have a negative effect on search rankings in Google.

So, to purge any unused CSS classes, we can update our `tailwind.config.js` file to look similar to the following:

```
 module.exports = {
   purge: [
     './resources/**/*.blade.php',
     './resources/**/*.js',
     './resources/**/*.vue',
   ],
    darkMode: false, // or 'media' or 'class'
    theme: {
      extend: {},
    },
    variants: {
      extend: {},
    },
    plugins: [],
  }
```

As you can see, we've added three new lines to the `purge` section of the file. These lines allow us to preserve any CSS classes that are found in any files inside our `resources` folder that end with `.blade.php`, `.js` or `.vue`.

But, it's really important to make sure that you write your styles in your markup in a way that can be preserved. Let's take a look at the example that the Tailwind documentation gives of how NOT to write your classes.

Because of the way that the regex rule works that is used to detect the CSS classes, it will detect strings that aren't separated by spaces, quotes or angle brackets. This means that if you have any of these in your classes (for example, if you were adding conditional classes), they might get ignored and purged.

For example, let's say that in a Vue.js file, you were adding conditional CSS classes. If there's an error, you want to add the `text-red-600` class, but if there's no error, you want to add `text-green-600`. You could potentially write it like so:

```
<div class="text-{{ error ? 'red' : 'green' }}-600"></div>
```

However, this would detect `text-{{`, `error`, `?`, `red`, `:`, `green`, `}}-600`. As you can probably guess, this means that because it didn't detect `text-red-600` or `text-green-600`, the classes you need would be purged from your CSS (assuming that they aren't included elsewhere in your markup somewhere).

Instead, to write the classes in a way that can be detected and not purged, you would write the conditional like so:

```
<div class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>
```

To learn more about this, I'd recommend giving the official Tailwind documentation's section about <a href="https://tailwindcss.com/docs/optimizing-for-production#writing-purgeable-html" target="_blank" rel="noopener noreferrer">writing purgeable HTML</a> a read.

## Splitting HTML into Components

As your application grows, you'll likely find that you'll be reusing common parts of your markup in a lot of different places. So, in a similar way that you'd tend to try and keep your code DRY (don't repeat yourself), you can do the same in Laravel with your views.

In this particular section, we'll be using Blade components as examples, but the concept can still be applied if you're building your frontend using something like Vue.

So, to get a bit of context, let's imagine that we have a button that we use in many places across our frontend that has the following markup:

```html
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
  Button
</button>
```

Now, let's say that a few months after releasing the original website, we want to update all of the buttons to be green rather than blue. Of course, we could do a 'find and replace' across all of our Blade files. But, as you can probably guess, that would be cumbersome and would leave room for error. What would happen if you forgot to change one of them? Or if you accidentally changed another element that was using the `bg-blue-500` class but that wasn't meant to be updated?

To get around this, we can make use of Laravel components. Components allow us to create reusable elements that we can use in our Blade files.

To get a better idea of what they are and how to use them, let's imagine the following HTML:

```html
<div>
  <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
    Button One
  </button>

  <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
    Button Two
  </button>
</div>
```

We're going to take these two buttons and split them into components that we can use instead. Let's start by creating our component by making a new `resources/views/components/button.blade.php` file.

We can then move the button's HTML into our new `button.blade.php` file like so:

```html
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
  Button One
</button>
```

But, we'll need to make sure that we make the button text dynamic so that we can reuse this component across our system. We can do that by outputting a `$text` attribute that we'll be passing to the component. Our new button markup would then look like this:

```html
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
  {{ $text }}
</button>
```

Now we can update our original HTML with the two buttons to use our new components rather than the button's duplicated markup:

```html
<div>
  <x-button text="Button One"/>
  
  <x-button text="Button Two"/>
</div>
```

This now means that if we want to update the colours of our buttons from blue to green, all we'll need to do is change it once in our `resources/views/components/button.blade.php` file.

You might find that in one part of your frontend that you'd like to keep the general look of the button but change something (the font size as an example). Instead of needing to create a new component or manually create the button without a component, we can make our component's CSS classes dynamic.

To do this, we can update our component like so:

```html
<button {{ $attributes->merge(['class' => 'bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded']) }}">
  {{ $text }}
</button>
```

We could then call our component:

```html
  <x-button text="Button One" class="text-xl"/>
```

This would result in the following HTML being output:

```html
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded text-xl">
  Button One
</button>
```

To find out more about components in Laravel, I'd definitely recommend giving the <a href="https://laravel.com/docs/8.x/blade#components" target="_blank" rel="noopener noreferrer">official documetation</a> a read. It shows the different types of things that you can do with components and gives some really useful examples.

## Conclusion

Hopefully, this article should have given you an overview of how you can set up Tailwind CSS for your Laravel applications and websites. It should have also shown you how to set up Laravel Mix to purge any unused CSS and then briefly showed you how to split your reusable HTML into components.

If this post helped you out, I'd love to hear about it. Likewise, if you have any feedback to improve this post, I'd also love to hear that too.

If you're interested in getting updated each time I publish a new post, feel free to [sign up for my newsletter](https://ashallendesign.co.uk/blog).

Keep on building awesome stuff! 🚀