UPDATED: Angular 11 and TailwindCSS 2

Jacob Neterer
4 min readAug 13, 2020

--

This tutorial has been updated to support Angular 11 and TailwindCSS 2. TailwindCSS is a hot topic in the web development world and Angular devs want in on the action. I’ve been seeing developers asking how to use Angular and TailwindCSS together all over the internet, from Stack Overflow, to Twitter and blog post comments. If you haven’t heard of TailwindCSS, it is a fantastic utility-first CSS framework. If you want to build Angular apps fast, this is the framework for you! Continue reading for a simple explanation on how to integrate TailwindCSS with Angular.

Create Your Angular App

First, let’s create our angular application.

ng new tailwindcss-angular-app

When the CLI asks you which styling framework to use, choose SCSS.

Set Up TailwindCSS

Install dependencies

Next, let's install TailwindCSS.

npm install tailwindcss -D

Now we will install @angular-builders/custom-webpack for a custom webpack build step and postcss for building Tailwind.

npm install @angular-builders/custom-webpack postcss -D

Create webpack.config.js

Create a webpack.config.js file at the root of your project with the following contents:

function patchPostCSS(webpackConfig, tailwindConfig, components = false) {
if(!tailwindConfig){
console.error('Missing tailwind config :', tailwindConfig);
return;
}
const pluginName = "autoprefixer";
for (const rule of webpackConfig.module.rules) {
if (!(rule.use && rule.use.length > 0) || (!components && rule.exclude)) {
continue;
}
for (const useLoader of rule.use) {
if (!(useLoader.options && useLoader.options.postcssOptions)) {
continue;
}
const originPostcssOptions = useLoader.options.postcssOptions;
useLoader.options.postcssOptions = (loader) => {
const _postcssOptions = originPostcssOptions(loader);
const insertIndex = _postcssOptions.plugins.findIndex(
({ postcssPlugin }) => postcssPlugin && postcssPlugin.toLowerCase() === pluginName
);
if (insertIndex !== -1) {
_postcssOptions.plugins.splice(insertIndex, 0, ["tailwindcss", tailwindConfig]);
} else {
console.error(`${pluginName} not found in postcss plugins`);
}
return _postcssOptions;
};
}
}
}
module.exports = (config) => {
const tailwindConfig = require("./tailwind.config.js");
patchPostCSS(config, tailwindConfig, true);
return config;
};

HUGE shoutout to the @ngneat/tailwindcss team for figuring out postcss with this integration. I have been stumped on it ever since the update to postcss v4!

Modify angular.json

This will tell our application to use our custom builder for Angular’s CLI build and serve commands.

ng config projects.<your-project>.architect.build.builder @angular-builders/custom-webpack:browserng config projects.<your-project>.architect.build.options.customWebpackConfig.path webpack.config.jsng config projects.<your-project>.architect.serve.builder @angular-builders/custom-webpack:dev-serverng config projects.<your-project>.architect.test.builder @angular-builders/custom-webpack:browserng config projects.<your-project>.architect.test.options.customWebpackConfig.path webpack.config.js

Initialize TailwindCSS

To create the configuration file for TailwindCSS, execute the following:

npx tailwind init

TailwindCSS ships with default styles, but you can use this file to customize themes, breakpoints, colors, spacing, and more!

Inject Tailwind’s Styles

In your root style sheet src/styles.scss inject Tailwind’s base, component, and utilities styles:

@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';

Test it Out!

Paste the following code into your app.component.html file, run your app ng serve, and see TailwindCSS working in your own Angular application!

<h1 class="my-8 text-center text-6xl font-bold"><span class="text-green-600">TailwindCSS</span> and <span class="text-red-600">Angular</span> is awesome!</h1>
<p class="text-center text-3xl">Thanks for reading!</p>

Bonus: Purge Unused TailwindCSS Classes

At this point, when building our application for production ng build --prod, you will see a whopping 2.71MB styles.css file 😳.

Bundle Without Purging Unused TailwindCSS Classes

In general, you are only going to use a fraction of the classes that TailwindCSS provides, so we can safely purge any unused classes.

First, install dotenv.

npm install dotenv -D

We will use dotenv for loading an environment variable that tells Tailwind if we need to purge unused classes or not.

Next, let’s modify our tailwind.config.js file to purge any unused classes. We simply require dotenv, access the ENABLE_PURGE environment variable (if not found, say in your local environment, defaults to false), set purge enabled to true if purge is true, and search any *.html and *.scss files for classes that we’ve used.

+require('dotenv').config();
+const enablePurge = process.env.ENABLE_PURGE || false;
module.exports = {
- purge: [],
+ purge: {
+ enabled: enablePurge,
+ content: [
+ './src/**/*.html',
+ './src/**/*.scss'
+ ]
+ },
theme: {
extend: {},
},
variants: {},
plugins: [],
}

Lastly, don’t forget to create your .env file with ENABLE_PURGE set to true. As a note, you don’t need to do this for local development, but I do urge purging any unused classes in higher environments like test and production.

ENABLE_PURGE=true

Now if you run ng build --prod your styles.css file will look much, much smaller, a solid 2.98KB 😁.

Bundle With Purging Unused TailwindCSS Classes

Check out my GitHub repo that demonstrates this tutorial!

Final Thoughts

Integrating TailwindCSS into your Angular app is as simple as that. I use it for almost all of my Angular applications. It makes development lightning fast and I would recommend it to everyone! Do you have any additional questions regarding using TailwindCSS with Angular? Post your questions in the comments and I’ll get back to you! Thanks for reading!

You can find me on Twitter, GitHub, LinkedIn, and my website!

--

--

Jacob Neterer
Jacob Neterer

Written by Jacob Neterer

Lead software engineer specializing in web and mobile development. Always learning new things. “There is no growth in the comfort zone…”