How to configure Tailwindcss for Svelte and Storybook (2020 Update)
Tags: tutorial, javascript, css
Published: 2020-10-26 15:32:55

Last week I was assigned the task of configuring a project that uses Svelte, Tailwindcss, and Storybook. I had never worked with any of the tech, so I spent a good amount of time researching. What I've come to realize is that there's not a lot of articles that break down how to work with them, and the ones that are available don't use the latest Tailwind or Storybook. I decided to write this article to show how you can use Svelte with the recently updated Storybook and Tailwindcss. I will break it down step by step to make sure it's easy to follow, especially for someone who's new to these frameworks like I was a few weeks ago.

To better explain how the dependencies work together, I'm going to divide the article into 2 main parts. We'll set up Svelte first, then move on to Storybook. Let's get started!
    
## Part 1: Svelte
 
(If you don't have a Svelte app yet, follow 
[this tutorial](https://svelte.dev/tutorial/making-an-app).) 

**Step 1: Install Tailwind and dependencies**
        
For the main app, we need to install 3 main dependencies.
`npm i tailwindcss postcss-import svelte-preprocess`

 - tailwindcss: this is the official Tailwindcss plugin
 - svelte-preprocess: we need this for Svelte components' styles
 - postcss-import: to import css files that use Tailwindcss syntax into our svelte components

To use these dependencies, we need to update their configuration files: postcss, rollup, and tailwind.

**Step 2: Configuration**
It's time for the fun part! There are 3 main configuration files that we need to edit: `postcss.config.js`, `rollup.config.js`, and `tailwind.config.js`

Let's start by creating the file `postcss.config.js` at our root directory. To use Tailwindcss, we need to add the `tailwindcss` plugin to our postcss configuration. We also need to add `postcss-import`, so that any Tailwindcss syntax can be directly imported to svelte components.

```javascript
// postcss.config.js
module.exports = {
  plugins: [require("postcss-import"), require("tailwindcss")],
};
```
                
The next step is to tackle the rollup config. In our `rollup.config.js`, we need to set up `svelte-preprocess` to process our component styles with the above postcss configuration.
		
```javascript
// rollup.config.js
export default {
  ...
  plugins: [
    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
      preprocess: sveltePreprocess({ postcss: true }),
      css: (css) => {
        css.write("bundle.css");
      },
    }),
    ...
```
                
Finally, we need to set up our tailwind config by creating a `tailwind.config.js` at the root directory. You can do this quickly by using the command: `npx tailwind init`.

3 main things we need to configure:

- `purge`: This will ensure that all the unused CSS rules that Tailwind creates will be purged at build.
- `defaultextractor`: a more customized extractor to make sure that we don't lose tailwind styles used in class directive.
- `whitelist`: to indicate which selectors are safe to leave in the final CSS.

Your config should now look like this:

```javascript
// tailwind.config.js
const production = !process.env.ROLLUP_WATCH;

module.exports = {
  future: {},
  purge: {
    content: ["./src/**/*.svelte", "./src/**/*.html"],
    enabled: production, // disable purge in dev
    options: {
      whitelist: [/svelte-/],
      /* eslint-disable no-unused-vars */
      defaultExtractor: (content) =>
        [...content.matchAll(/(?:class:)*([\w\d-/:%.]+)/gm)].map(
          ([_match, group, ..._rest]) => group
        ),
    },
  },
  theme: {
    extend: {},
  },
  variants: {},
  plugins: [],
};
```

**Step 3: Add global Tailwindcss to your app**
        
Now let's add some Tailwind styling to your app. Before you start adding any custom styles, let's add the global utilities packages first. Create a css file with the below content.
```css
/* globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
```

if you want to use these global styles in a svelte component for hot reloading, you can import the css file like this.

    // Tailwindcss.svelte
    <style global>
	@import "globals.css";
	</style>
            
The reason why we want to keep our global styles in a css file is because we need it for storybook later.
    
## Part 2: Storybook: 
    
**Step 1: Install Storybook**. 
Follow this guide for the complete installation: [https://storybook.js.org/docs/svelte/get-started/install](https://storybook.js.org/docs/svelte/get-started/install)

**Step 2: Add `svelte-preprocess`**
Now we need to add a preprocessor to Storybook so that our stories will render Svelte properly. We do this by adding webpack configuration to `.storybook/main.js`

```javascript
const sveltePreprocess = require("svelte-preprocess");

module.exports = {
  stories: ["../stories/**/*.stories.js"],
  addons: ["@storybook/addon-knobs"],

  webpackFinal: async (config) => {
    const svelteLoader = config.module.rules.find(
      (r) => r.loader && r.loader.includes("svelte-loader")
    );
    svelteLoader.options = {
      ...svelteLoader.options,
      preprocess: sveltePreprocess({ postcss: true }),
    };

    return config;
  },
};
```

**Step 3: Import global styles to storybook**
Lastly, It's time to import your global styles to storybook, and we can do it easily by importing the global.css file we created earlier. Now you see why we want our global styles to be in a css file, rather than Svelte. 

```css
@import "globals.css";
```


**Aaaaand that's it!** You should be able to use Tailwindcss with Svelte and Storybook effortlessly now. I hope this was helpful, feel free to comment below if you spot any errors. Happy coding!