DEV Community

Linh Nguyen
Linh Nguyen

Posted on • Updated on

How to configure Tailwindcss for Svelte and Storybook (2020 Update)

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

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.

// postcss.config.js
module.exports = {
  plugins: [require("postcss-import"), require("tailwindcss")],
};
Enter fullscreen mode Exit fullscreen mode

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.

// 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");
      },
    }),
    ...
Enter fullscreen mode Exit fullscreen mode

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:

// 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: [],
};
Enter fullscreen mode Exit fullscreen mode

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.

/* globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
Enter fullscreen mode Exit fullscreen mode

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

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

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

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

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.

@import "globals.css";
Enter fullscreen mode Exit fullscreen mode

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!

Oldest comments (5)

Collapse
 
sagato profile image
Sagato

Hi Linh thx for the article. I don't get where u import the globals.css to storybook. Would u mind explain? Greets!

Collapse
 
gyurielf profile image
gyurielf

You should put into preview .cjs/js, right below the other imports.
I hope it helps.

// .storybook/preview.cjs

import '../static/base-style.css';

export const parameters ={
..
}

Collapse
 
jayliu50 profile image
Jay Liu • Edited

Awesome article! Other guides were out of date and didn't get things working, but I was able to get up and running mainly because of your writeup.

In addition to the instructions above, this is what I had to do to get things running:

PostCSS 8 issues (At the time of writing 9 Jan 2021)

  • I had to use the compatibilty build for Tailwind:

    • yarn remove tailwindcss postcss autoprefixer
    • yarn add -D tailwindcss@npm:@tailwindcss/postcss7-compat @tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9
  • In package.json, I also had to change from "postcss-import": "^14" to "postcss-import": "^12" for the same reason.

Other notes

  • I had to yarn add autoprefixer for npx tailwind init to work
  • To install storybook, I ran npx -p @storybook/cli sb init --type svelte
  • I believe the dependency is svelte-preprocess rather than svelte-preprocessor
Collapse
 
arperyan profile image
Ryan Arpe • Edited

Hi @JayLiu,

Thanks for your info. I struggled to get it to work and your comment, helped alot.

Thanks again!.

Ryan

Collapse
 
catalactics profile image
Joshua Pelealu • Edited

Hello there, Great article!

Anyways, for anyone that is having an issue with your postcss-import issue or any PostCSS 8 compatibility issue that would look like this on the error:

Error: PostCSS plugin postcss-import requires PostCSS 8
Enter fullscreen mode Exit fullscreen mode

At the time of writing this (Which is March 14, 2021), Here's what you need to do:

  • npx sb@next init --type svelte instead of npx sb init --svelte This is because the StoryBook developer has updated the dependency issue in their pre-release branch.
  • It's going to ask you to install sb@next, press [ Enter ]

Here's a GitHub issue for this problem:
github.com/storybookjs/storybook/i...

To future proof this for StoryBook 7:

  • run npm i -D @storybook/addon-postcss or yarn install -D @storybook/addon-postcss
  • Include @storybook/addon-postcss inside the main.js.
//.storybook/main.js

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

module.exports = {
  stories: ["../stories/**/*.stories.js"],
  addons: ["@storybook/addon-knobs', '@storybook/addon-postcss"], // <- Add it here

  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;
  },
};

Enter fullscreen mode Exit fullscreen mode