DEV Community

Muhammad Muhajir
Muhammad Muhajir

Posted on

Using TailwindCSS with SvelteJS

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
Enter fullscreen mode Exit fullscreen mode

Install dependencies

npm install --save-dev tailwindcss postcss-import @fullhuman/postcss-purgecss postcss rollup-plugin-postcss autoprefixer
Enter fullscreen mode Exit fullscreen mode

Setup rollup-plugin-postcss

// rollup.config.js

...
import postcss from 'rollup-plugin-postcss'
...

export default {
    plugins: [
         postcss({extract: true}),
         svelte(...),
         ...
    ]
}
Enter fullscreen mode Exit fullscreen mode

Here's the end result

//rollup.config.js

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: [
        postcss({
            extract: true
        }),
        svelte({
            // 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 => {
                css.write('public/bundle.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 }),
        commonjs(),

        // 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
    }
};
Enter fullscreen mode Exit fullscreen mode

Create postcss.config.js

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

module.exports = {
  plugins: [
    require("postcss-import")(),
    require("tailwindcss"),
    require("autoprefixer"),
    // Only purge css on production
    production &&
      purgecss({
        content: ["./**/*.html", "./**/*.svelte"],
        defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || []
      })
  ]
};
Enter fullscreen mode Exit fullscreen mode

Create src/main.css

@import "tailwindcss/base";

@import "tailwindcss/components";

@import "tailwindcss/utilities";
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

Optional

Remove public/global.css
And also remove

 <link rel="stylesheet" href="global.css" />
Enter fullscreen mode Exit fullscreen mode

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/

Top comments (19)

Collapse
 
tompretty profile image
Tom Pretty

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

class:active="{ current == me }"
Enter fullscreen mode Exit fullscreen mode

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

Collapse
 
collardeau profile image
Thomas Collardeau

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;
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
muhajirdev profile image
Muhammad Muhajir

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...

Collapse
 
tompretty profile image
Tom Pretty

Hey,

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.

Cheers!

Collapse
 
collardeau profile image
Thomas Collardeau

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.

Collapse
 
collardeau profile image
Thomas Collardeau

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
Collapse
 
aresinodev profile image
Aarón Resino Jiménez

Hi!!
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:
thepracticaldev.s3.amazonaws.com/i...

tailwind.config.js:
thepracticaldev.s3.amazonaws.com/i...

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.

Collapse
 
jsjoeio profile image
Joe Previte (he/him)

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.

Source

Collapse
 
quantuminformation profile image
Nikos

found it

templates now use public/build/bundle.js

Collapse
 
_darrenburns profile image
Darren Burns

This was really helpful, thanks so much!!

Collapse
 
muhajirdev profile image
Muhammad Muhajir

You're welcome

Collapse
 
quantuminformation profile image
Nikos

Is is the same setup for sapper more or less?

Collapse
 
muhajirdev profile image
Muhammad Muhajir

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

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

Collapse
 
alexanderalemayhu profile image
Alexander Alemayhu

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

Collapse
 
muhajirdev profile image
Muhammad Muhajir

you're welcome

Collapse
 
marshyon profile image
jon brookes

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

Collapse
 
simeydotme profile image
Simon Goellner

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

Collapse
 
muhajirdev profile image
Muhammad Muhajir

Glad to hear it helps you :)