How to Set Up Svelte with Tailwind CSS

A quick reference for myself on how to set up Svelte with Tailwind CSS #svelte #tailwindcss #tech

Read time: 6 minutes
Last update:

Jan 2021 update: minor update of config for Tailwind 2.0. I've also added alternative approaches at the bottom, scroll down

Sep 2020 update: Chris has shown a much easier way to do this than I originally outlined, so I have replaced my original notes with notes from his sample repo. There's a build speed tradeoff, I discuss alternatives at bottom.

On the latest Toolsday, Chris Dhanaraj said he had trouble finding documentation for adding Tailwind to Svelte.

Today I also needed to add Tailwind to a Svelte project, so I am writing this as a reference for myself. Setting up PostCSS with Svelte is something I have documented on the new Svelte Society site, but of course it could be better and more specifically tailored to Tailwind (which after all is "just" a PostCSS plugin).

So I am writing this for him and for me.

A quick aside on WHY Use Tailwind with Svelte, since Svelte offers scoped CSS by default: Tailwind offers a nicely constrained "design system" so you don't overuse Magic Numbers and it's easy to add responsive styling with Tailwind breakpoints. Because Tailwind has the developer experience of "inline styles", I also find it easier to delete and move HTML around without having to go back for the styling. I also like not having to name classes. I discuss more on Why Tailwind in general in a separate post.

3 Steps

I will assume you have a standard existing Svelte or Sapper project with no PostCSS/Tailwind set up. I'll also add in autoprefixer and postcss-nesting since I like to work with those, but of course feel free to remove as needed.

Step 1: Install deps

npm install -D svelte-preprocess tailwindcss autoprefixer postcss-nesting

# optional tailwind ui plugin
npm install @tailwindcss/ui

Step 2: Setup Config Files

Add a tailwind.config.js file at the project root:

// tailwind.config.js
const production = !process.env.ROLLUP_WATCH; // or some other env var like NODE_ENV
module.exports = {
  future: { // for tailwind 2.0 compat
    purgeLayersByDefault: true, 
    removeDeprecatedGapUtilities: true,
  },
  plugins: [
    // for tailwind UI users only
    require('@tailwindcss/ui'),
    // other plugins here
  ],
  purge: {
    content: [
      "./src/**/*.svelte",
      // may also want to include base index.html
    ], 
    enabled: production // disable purge in dev
  },
};

And now set it up inside of your Svelte bundler config as well:

import sveltePreprocess from "svelte-preprocess";

const production = !process.env.ROLLUP_WATCH;

export default {
  plugins: [
    svelte({
      // etc...
      preprocess: sveltePreprocess({
        // https://github.com/kaisermann/svelte-preprocess/#user-content-options
        sourceMap: !production,
        postcss: {
          plugins: [
             require("tailwindcss"), 
             require("autoprefixer"),
             require("postcss-nesting")
          ],
        },
      }),
    }),
  ]
}

Here is the equivalent for Svelte with Webpack:

// webpack.config.js
const sveltePreprocess = require('svelte-preprocess');
module.exports = {
  // ...
	module: {
		rules: [
			{
				test: /\.svelte$/,
				use: {
					loader: 'svelte-loader',
					options: {
						emitCss: true,
						hotReload: true,
						preprocess: sveltePreprocess({
							// https://github.com/kaisermann/svelte-preprocess/#user-content-options
							sourceMap: !prod,
							postcss: {
								plugins: [
									require("tailwindcss"), 
									// require("autoprefixer"),
									require("postcss-nesting")
								],
							},
						}),
					}
				}
			},
}

Step 3: Add the Tailwind includes to your Svelte App

Typically a Svelte app will have a way to inject css already, so all we do is piggyback onto that. You'll want to put these includes at a reasonably high level, say App.svelte or Layout.svelte component that will be included in every page of your site.

<style global lang="postcss">

  /* only apply purgecss on utilities, per Tailwind docs */
  /* purgecss start ignore */
  @tailwind base;
  @tailwind components;
  /* purgecss end ignore */
 
  @tailwind utilities;

</style>

And that's it!

Note: this section used to involve messing with package.json scripts to run postcss-cli, but Chris realized that you didn't need to do any of this since Svelte already has a way to inject CSS and svelte-preprocess already runs on every Svelte file.

Please see:

To see this working in action.

Unresolved

Svelte has a class: binding syntax that isnt' supported by Tailwind out of the box. There is an open discussion for this.

Alternative Approaches

This method outlined above is simple to get running, but does end up running thousands of lines of Tailwind's CSS through the Svelte compiler. This may cause performance issues (primarily, every time you change the entry point file). Alternative approaches may be more appropriate depending on your preferences:


Join 2,000+ developers getting updates ✉️

Too soon! Show me what I'm signing up for!


Webmentions

Tweet about this post and it will show up here, or you could leave a comment on Dev.to
Loading...