[Update] Using Svelte with Tailwindcss - A better approach

I've been using Tailwind since its early days and it is a complete life changer for me. That's why I tried to use it on a project written using Svelte. Existing methods to combine these two weren't sufficient in terms of developer experience that they have provided. So, I've tried to come up with a better approach. Wish you enjoy reading!

TL;DR

I've combined Svelte's preprocessing feature and PostCSS using svelte-preprocess to handle Tailwind. You can skip the tutorial and use the template that I've published on GitHub:

They create another pipeline alongside Svelte to process external css. Tailwind will be processed by PostCSS while component styles are being processed by Svelte. That's why developers need to reconsider everything from transpiling to minimization.

They make it impossible to use directives of Tailwind (like @apply or @screen) in component styles.

They create an auto-generated css file within the codebase.

That's why I've come up with a new approach to make this integration smoother. So let's start with it:

1-Create a Svelte app

First, we need to initialize a Svelte app using the following commands. If you already have an existing one, you can skip this section.

This will create a file named tailwind.config.js in your codebase. You can edit or replace this file to extend your Tailwind config.

3-Make the integration

In order to make the integration we'll need following two files. We'll use postcss.config.js to configure PostCSS to process styles with Tailwind. Note that PostCSS uses Purgecss to get rid of unused styles in production mode. We'll also need to whitelist css classes generated by Svelte itself since Svelte itself takes are of these.

Tailwindcss.svelte file includes a Svelte component which only has a style definition. We'll use it to inject our utility classes into the app. global directive here means that styles of this component will be available globally.

rollup.config.js

Results

Using this new approach will enable us to benefit from every feature of Tailwind by combining Svelte's preprocessing ability and PostCSS. You can use utility classes, or call directives to combine them into component styles. All those styles will be processed by Svelte without creating additional pipeline.

To demonstrate the outcome let's run the app using npm run dev command and change some styles in App.svelte:

<style>h1{@applybg-blacktext-white;}</style>

You will see that styles provided by Tailwind are perfectly applied to our mighty Hello world! message. So you can start using them for a better cause!

What about Sapper?

Not a problem! You can apply the same steps to integrate Tailwind into your Sapper app. Just be sure that you've changed both client and server configs.

I've published the Sapper template to GitHub. Since it is based on the official template, you can use either of rollup and webpack setups. Here is the link:

src

Other benefits

Using svelte-preprocess to let PostCSS to handle component styles provides various other side benefits. You can use postcss.config.js to import some other PostCSS plugins like autoprefixer, etc. Those plugins will immediately take care of your component styles.

Great solution! One thing that i'm still struggling with, i can't seem to use regular classes in my svelte files like <div class="bg-red-200">...</div>. It works if i rerun sapper dev. If i use @apply inside tag it works fine. Btw i added inside _layout.svelte. Any idea how to get this working without having to rerun npm run dev every time?

Thanks for the information! In fact, using process.env.NODE_ENV in both setups would be better. However since process.env.ROLLUP_WATCH is used to determine mode in rollup.config.js, I wanted to be consistent with it. I've changed it to process.env.NODE_ENV in Sapper template.

Thanks for sharing that. I'm having issues with responsive classes such as sm:block. Using it throws an error saying that class doesn't exist. Are others able to use responsive classes with the approach explained in this article?

Thanks for your response. I cloned your repo and changed App.svelte's style to the following:

h1{@applybg-blacktext-whitemd:text-red-200;}

This throws the same error I see in my project:

[!] (plugin svelte) CssSyntaxError: /home/mikenikles/dev/github/sarioglu/svelte-tailwindcss-template/src/App.svelte:3:3: `@apply` cannot be used with `.md\:text-red-200` because `.md\:text-red-200` either cannot be found, or its actual definition includes a pseudo-selector like :hover, :active, etc. If you're sure that `.md\:text-red-200` exists, make sure that any `@import` statements are being properly processed *before* Tailwind CSS sees your CSS, as `@apply` can only be used for classes in the same CSS tree.
src/App.svelte

Thanks for sharing. I ran into a small issue where the production flag in the postcss config is always false and therefore purgecss is not invoked. The NODE_ENV is "development" even when running npm run build in my case. I am on windows and I am resolving this by changing the build script to set NODE_ENV=production && sapper build --legacy. With that purgecss is invoked and everything is fabulous, thanks again.

I think it worths to disable Purgecss in development. I frequently use DevTools to add/remove some styles to get an instant preview. Therefore, I can sacrifice some seconds for better development experience 🙂

Thank you! I've updated the template according to your comments. Issue with html and body was happening because index.html is in public folder. Purgecss config now checks every folder under project directory.

I included it in Sapper by following exactly your description and then, instead of importing and including it in src/App.svelte, I just included it in src/routes/_layout.svelte. This way it should be included in all pages rendered by Sapper.

Works like a charm and, as you mentioned, no additional workflow side-by-side with Sapper/Svelte.

i think this is great! i made a recipe blog based on the sapper at master-tailwind method you mentioned above. i would like to try this method instead. do you have any plans on coming out with sapper-tailwind template on github? i can't figure out which goes into the server and which into client configs as you said. i'm a noob with those sort of things and more of a UI/UX guy. thank you for this! i'll try it out on a svelte project. cheers!