Using TailwindCSS with SvelteJS

muhajirdev profile image Muhammad Muhajir ・2 min read

If you haven't check TailwindCSS, you might want to. I don't want to repeat the awesomeness here 🤪

TL;DR. Full implementation can be found on my Github muhajirdev/svelte-tailwind-template

Get Svelte default template

npx degit sveltejs/template my-svelte-project
cd my-svelte-project

Install dependencies

npm install --save-dev tailwindcss postcss-import @fullhuman/postcss-purgecss postcss rollup-plugin-postcss autoprefixer

Setup rollup-plugin-postcss

// rollup.config.js

import postcss from 'rollup-plugin-postcss'

export default {
    plugins: [
         postcss({extract: true}),

Here's the end result


import svelte from 'rollup-plugin-svelte';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
import postcss from 'rollup-plugin-postcss'

const production = !process.env.ROLLUP_WATCH;

export default {
    input: 'src/main.js',
    output: {
        sourcemap: true,
        format: 'iife',
        name: 'app',
        file: 'public/bundle.js'
    plugins: [
            extract: true
            // enable run-time checks when not in production
            dev: !production,
            // we'll extract any component CSS out into
            // a separate file — better for performance
            css: css => {

        // If you have external dependencies installed from
        // npm, you'll most likely need these plugins. In
        // some cases you'll need additional configuration —
        // consult the documentation for details:
        // https://github.com/rollup/rollup-plugin-commonjs
        resolve({ browser: true }),

        // Watch the `public` directory and refresh the
        // browser on changes when not in production
        !production && livereload('public'),

        // If we're building for production (npm run build
        // instead of npm run dev), minify
        production && terser()
    watch: {
        clearScreen: false

Create postcss.config.js

const production = !process.env.ROLLUP_WATCH;
const purgecss = require("@fullhuman/postcss-purgecss");

module.exports = {
  plugins: [
    // Only purge css on production
    production &&
        content: ["./**/*.html", "./**/*.svelte"],
        defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || []

Create src/main.css

@import "tailwindcss/base";

@import "tailwindcss/components";

@import "tailwindcss/utilities";

Import src/main.css in src/main.js

// src/main.js
import App from "./App.svelte";
import "./main.css";

const app = new App({
  target: document.body,
  props: {
    name: "world"

export default app;


Remove public/global.css
And also remove

 <link rel="stylesheet" href="global.css" />

from index.html as we already have normalize.css from tailwind

And finally, now you can just write tailwind class

Try it <div class="bg-black">test</div> should give you a div with black background.

Any feedback would be very appreciated :)

Originally published at https://muhajir.dev/writing/using-tailwincss-with-svelte/

Posted on by:

muhajirdev profile

Muhammad Muhajir


Javascript Wizard Riding ReactJS for web development, Driving Flutter for Mobile Development #Fullstack #Typescript #NodeJS #ReactJS #Graphql #Flutter


Editor guide

Hey thanks for this - super helpful! I'm running into an issue though when I use the svelte class shorthand:

class:active="{ current == me }"

Purgecss ins't detected that I'm using the class active :(


This extractor is working for me, but I've not tested it thoroughly:

function extractor(content) {
  const matches = content.match(/[A-Za-z0-9-_:/]+/g) || [];
  const res = matches.map(match => {
    if (match.startsWith("class:")) {
      return match.split(":")[1];
    return match;
  return res;

Hey Tom,
I haven't tried it yet. It's probably related to the purgecss regex.

See more here: tailwindcss.com/docs/controlling-f.... When the class name is not found anywhere in the source code. It will try to remove that code. Hence the class active is removed.

You can find the regex implementation in github.com/muhajirdev/svelte-tailw... . in defaultExtractor part.

A quick solution for this it to put class "active" into whitelist.

Here's an example I whitelist "html", and "body" in nextjs-tailwind template github.com/muhajirdev/nextjs-tailw...



Yeah you're right it's an issue with the regex. It matches the whole string class:active. I tried to come up with a regex that could handle that but failed miserably! My current solution was to drop that svelte feature and use the classnames package to simplify optional classes.

I think whitelisting would work too, but I'm using tailwindcss so I was adding lots of classes like that. I didn't want have to keep addind lots of little utility classes to a whitelist.



I've noticed as soon as I import main.css, I lose the styles defined in my svelte components (using the style tag as normal). I don't mind so much as I prefer to do all my styling with Tailwind and using apply, but is that to be expected? Just want to make sure I'm not doing something wrong.


I've actually solved this, so the Svelte styles work as normal alongside Tailwind:

  • in rollup.config.js give a name to the extracted CSS so it doesn't clash with the CSS generated by Svelte, for example:
postcss({ extract: "public/tailwind.css" })
  • link that CSS from public/index.html
<link rel="stylesheet" href="/tailwind.css" />

  • add public/tailwind.css to .gitignore

Thanks a bunch for writing this! It was super easy to follow :)

One note: I ran into an issue with PostCSS and autoprefixer. I had to downgrade autoprefixer from v10 to v9.8.6.



Thank you for this tutorial. I have a problem.
I'm trying to create my own classes in tailwind so I can apply them. I created the file 'tailwind.config.js', and imported it into 'postcss.config.js' as follows:


I try to apply the added class in the tailwind.config.js file in HTML and it doesn't apply. Could you tell me how to make it work?

Thank you so much.


This was really helpful, thanks so much!!


You're welcome


found it

templates now use public/build/bundle.js


Is is the same setup for sapper more or less?


i haven't tried yet with sapper unfortunately :).

Probably similar, just take a look at config file , postcss and rollup


Here's an implementation of TailwindCss and Svelte...nicely name Smelte!



sadly this does not seem to work at time of writing this comment any longer due to github.com/rollup/rollup/issues/3443 - apparent issues with rollup


thanks so much, I struggled to get this working on my own... all the info from the libraries/frameworks seems 90% complete


Glad to hear it helps you :)


This post made it easy to update a Svelte app for experimenting withTailwind CSS, thanks 👍🏾


you're welcome