All Articles

How to configure TailwindCSS with Angular and why you should use it

TL;DR: This configuration is tested on Angular 9. It is also working on the previous version of Angular such as 8.x.x. It is also working with AOT when you do ng build --aot=true

Update Aug 2020

My friend @nartc Just released an @angular schematics to add @tailwindcss to your @angular/cli projects.

  • Setup Custom Webpack
  • Enable purge for TS and HTML files
  • Update angular.json and styles.scss
  • Support Nx Workspace

Usage

Simply run a single command on your Angular CLI project, and you are all set!

ng add @ngneat/tailwind

See more ➡ https://github.com/ngneat/tailwind

Problem

Everyone has a different way of organizing and working with CSS. I always encounter some use case where I need to set a simple padding-left: 5px, or margin: 0 auto, or to make an element to have cursor: pointer.

I have a few options for doing so.

1. Quick and dirty way: inline style

<button style="padding-left: 5px;">Submit</button>
<i style="cursor: pointer;"></i>

2. Create a new class for each element, such as

<button class="my-button">Submit</button> <i class="fa fa-help my-icon"></i>

And write a corresponding CSS for them.

.my-button {
  padding-left: 5px;
}

.my-icon {
  cursor: pointer;
}

Because Angular has encapsulated the stylesheet, it will ensure that these classes will be available only in the component itself. I don’t have to worry about polluted the global CSS.

3. Create a common CSS on a top-level component

Suppose you see they are repeating again and again on a different component. In that case, I could also bring all of that classes into app.component.scss and set the ViewEncapsulation.None to use in all the other components. But, the class name has to be changed because Those classes will be reused in many places.

.pl-1 {
  padding-left: 5px;
}

.icon-active {
  cursor: pointer;
}

If I need a padding-left: 10px, I can just add new class .pl-2 { padding-left: 10px } to app.component.scss. In real life I will use SCSS loop to generate them, but let assume I do it manually for now.

It is convenience, but many problems arise with this approach

  • How to document these comment CSS so that all the team member can use.
  • If your team member needs a style that doesn’t have a corresponding class, and he adds a new one that doesn’t follow your team standard. People might not know about that. It might also create duplication in the future.

That’s when you come to use TailwindCSS. I have been using it quite sometimes, and it is amazing.

TailwindCSS is a highly customizable, low-level CSS framework that gives you all of the building blocks you need to build bespoke designs without any annoying opinionated styles you have to fight to override.

In short, TailwindCSS create all the utility class for you. What you need to do is to spend about half an hour trying TailwindCSS, know some standard classes and syntax. You are good to go.

If you’re reading this and you don’t know what TailwindCSS is, where have you been?

How to configure TailwindCSS with Angular CLI

Known issues

⚠️ The below manual approach has several issues recently due to incompatible with the new breaking changes from postcss and @angular-builders/custom-webpack. Proceed with our own risk 😂

Some known issues that I have received from people.

Schema validation failed with the following errors:
Data path "" should NOT have additional properties(customWebpackConfig).

How to configure TailwindCSS with Angular and why you should use it

We can fix it by remove the customWebpackConfig from the builder for serve.

How to configure TailwindCSS with Angular and why you should use it

But after doing it, we faced another issue below, which I was looking for online. People only mentioned about the mismatched version of CLI and TypeScript and the like. I have no idea how to solve it. If you find the solution, please leave your comment 🤣

An unhandled exception occurred: Cannot read property 'flags' of undefined

How to configure TailwindCSS with Angular and why you should use it

So I highly recommend you use ngneat/tailwind that I mentioned above for installing TailwindCSS into your Angular application.


If you are not using CLI and have your own webpack configuration. It is still applicable, though

I have prepared a simple application while writing this blog post. View the source code.

Suppose you have already had an Angular application create with Angular CLI. Follow those below steps.

1. Open the command line and go to the Angular application folder

On Windows, simple type cd path/to/your/folder.

How to configure TailwindCSS with Angular

2. Install TailwindCSS package and dependencies needed

npm i tailwindcss postcss-scss postcss-import postcss-loader @angular-builders/custom-webpack -D

We will need @angular-builders/custom-webpack for customizing the build process of Angular CLI by overriding some of the webpack configurations.

How to configure TailwindCSS with Angular

3. Import Tailwind CSS to your style.scss

Next, you need to add the following to the top of the /src/style.scss.

@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
View the screenshot How to configure TailwindCSS with Angular

4. Create a webpack.config.js file at the root of your project

This is what it should look like for [email protected]^3.0

module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        loader: 'postcss-loader',
        options: {
          ident: 'postcss',
          syntax: 'postcss-scss',
          plugins: () => [
            require('postcss-import'),
            require('tailwindcss'),
            require('autoprefixer'),
          ],
        },
      },
    ],
  },
}

If you are using [email protected]^4.0, take this config instead

Noted there is additional postcssOptions property inside options. See the detail from its documentation

module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            ident: 'postcss',
            syntax: 'postcss-scss',
            plugins: ['postcss-import', 'tailwindcss', 'autoprefixer'],
          },
        },
      },
    ],
  },
}

I have some notes on Tailwind bundle size and postcss-scss for you

Controlling file size with Tailwind

When using the default configuration, Tailwind CSS’s development build is 1996kb uncompressed, 144.6kb minified and compressed with Gzip, and 37.kb when compressed with Brotli.

When building for production, you should always use Tailwind’s purge option to tree-shake unused styles and optimize your final build size. When removing unused styles with Tailwind, it’s tough to end up with more than 10kb of compressed CSS.

To enable purge, simply add this option in your tailwind.config.js

// tailwind.config.js
module.exports = {
  purge: {
    enabled: true,
    content: ['./src/**/*.html', './src/**/*.ts'],
  },
  // ...
}

For more on that, view Tailwind documentation.

View the screenshot - See the CSS bundle size different between 1 MB and 2 KB How to configure TailwindCSS with Angular

postcss-scss

It will not compile SCSS. It simply parses mixins as custom at-rules & variables as properties so that PostCSS plugins can then transform SCSS source code alongside CSS. Mixin and for loop won’t be transformed. You have to use sass-loader or less-loader if you need to compile your SASS/LESS code into CSS, then do the postcss-loader on top of that.

See my webpack.config.js for project jira-clone-angular that use additional sass-loader

But you might ask, what is different between SCSS and PostCSS?

PostCSS is the closest thing in the CSS world to what ‘Babel’ is in the JavaScript world - it parses CSS, loads plugins that apply transformations to your code, and manages these transformations. SCSS is a preprocessor and can be loaded by PostCSS, but PostCSS can load a lot more than just SCSS :D With PostCSS you could manage SCSS and Less and Stylus code, plus other things - all in the same codebase together.

I still didn’t really get what is PostCSS 😂 In short, To make SCSS/LESS work with PostCSS, please config your webpack.config.js with an additionally needed loader I mentioned above.

View the screenshot How to configure TailwindCSS with Angular

5. Modify the angular.json file to use the custom builder and the webpack config file

{
  "architect": {
    "build": {
      "builder": "@angular-builders/custom-webpack:browser",
      "options": {
        "customWebpackConfig": {
          "path": "./webpack.config.js"
        }
      }
    },
    "serve": {
      "builder": "@angular-builders/custom-webpack:dev-server",
      "options": {
        "customWebpackConfig": {
          "path": "./webpack.config.js"
        }
      }
    }
  }
}

Important, see the "builder" has been changed from @angular-devkit/build-angular:dev-server to @angular-builders/custom-webpack:browser.

How to configure TailwindCSS with Angular

6. We are finished

Run npm start and start adding some Tailwind classes to see if it is working.

How to configure TailwindCSS with Angular

Configure to use TailwindCSS effectively in VSCode

Tailwind is great. But with hundreds of utility classes might not be easy to remember. We can configure VSCode to give us all the suggestions for Tailwind.

How to configure TailwindCSS with Angular

To do so, follow these steps.

1. Install Tailwind CSS IntelliSense

https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss

2. Create a Tailwind configuration file

Simple run npx tailwind init. It will give you a default configuration file tailwind.config.js. This extension required this file to be able to work properly.

How to configure TailwindCSS with Angular

That’s all. You can now use the power of VSCode together with Tailwind, how sweet it is!

Using TailwindCSS @apply syntax

Tailwind provides a handy @apply keyword. Think about If you have ten similar buttons on a sample page. You have to copy the HTML code ten times.

<button
  class="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded"
>
  Submit
</button>

If you need to change the color, you also have to change 10 times, which is a nightmare.

With @apply, you can create a new class .btn and put all the style you want to reuse. Tailwind will transform our code below.

<button class="btn-tailwind">
  Submit
</button>
.btn-tailwind {
  @apply bg-transparent text-blue-700 font-semibold py-2 px-4 border border-blue-500 rounded;

  &:hover {
    @apply bg-blue-500 text-white border-transparent;
  }
}

How to configure TailwindCSS with Angular

The output looks the same as we use classes. For more information on @apply.

The Intellisense doesn’t like the SCSS syntax. It gave the red error underline of the class after using @apply. But the build work perfectly fine. You should not worry about that. See more about that:

Source code

https://github.com/trungk18/angular-tailwind-css-configuration

Notes

  • I have tested using Angular version "@angular/core": "~9.1.11". It is working with the previous version of Angular such as 8.x.x as well.
  • It is also working with AOT when you do ng build --aot=true.
  • It will increase your bundle size, you should always configure purge on tailwind.config.js for production build.

Reference

A comprehensive guide of how to configure TailwindCSS - @Sean Kerwin.

Published 13 Jun 2020

Recent Posts

JavaScript: Understanding the Weird Parts Notes

Below notes were taken from an Udemy course JavaScript: Understanding the Weird Parts

What is JavaScript Closure?

In short, a closure is not the function that is returned in another function. A closure is a combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function


Follow @tuantrungvo on Twitter for more!