Tailwind css classes not showing in Storybook build
Asked Answered
C

13

19

I am trying to build my storybook with tailwind css. When running build-storybook the components are rendered with the tailwind classes. Unfortunately, when I build storybook and run the create build storybook-static with npx http-server storybook-static the classes are not loaded into the stories and the components are displayed not styled.

This is a repro repo of my project: https://gitlab.com/ens.evelyn.development/storybook-issue

This is my main.js :

    const path = require('path')

module.exports = {
  "stories": [
    "../src/components/**/**/*.stories.mdx",
    "../src/components/**/**/*.stories.@(js|jsx|ts|tsx)"
  ],
  "addons": [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    {
     name: '@storybook/addon-postcss',
     options: {
       postcssLoaderOptions: {
         implementation: require('postcss'),
       },
     },
   },        
   "@storybook/addon-actions",
    "storybook-tailwind-dark-mode"
  ]}

My Projectstructure looks like this:

.storybook 
src
  components 
     subdir
       Button
         index.tsx
         button.stories.js 
  styles
    index.css (<-- tailwindcss file)

Any hints or advice is very appreciated.

Crawler answered 17/6, 2021 at 13:48 Comment(2)
How are you including your other styles?Groves
@Groves I am only using tailwindcss for the moment so my only styles are located in src/styles/index.cssCrawler
A
16

UPDATE: My original answer could be useful to others, so I'll leave it for reference. However, in this case, the problem was in tailwind.config.js.

Change

purge: {
    mode: 'all',
    content: [
      './src/components/**/**/*.{ts, tsx}'
    ],
  },

to

purge: ['./src/**/*.{js,jsx,ts,tsx}'],

ORIGINAL:

Just tested it out and storybook builds as expected for me. I think the key difference in our configurations is that I am not making changes to Storybook's webpack config in main.js. Rather, I am using @storybook/addon-postcss for postcss@^8 (required for tailwind@^2):

// main.js
module.exports = {
  ...
  addons: [
    ...
    {
      name: '@storybook/addon-postcss',
      options: {
        postcssLoaderOptions: {
          implementation: require('postcss'),
        },
      },
    },
  ],
};

I specify the necessary plugins in a postcss.config.js (in my project root):

// postcss.config.js
module.exports = {
    plugins: {
      tailwindcss: {},
      autoprefixer: {},
    },
  }

It's also worth noting that I import Tailwind directly in Storybook's preview.js instead via my own css file:

// preview.js
import 'tailwindcss/tailwind.css';
export const parameters = {...}

Hopefully, making those changes will get Tailwind working for you.

For comparison (see comments below), here are the contents of my build storybook-static directory:

contents of storybook-static directory

Almshouse answered 17/6, 2021 at 15:20 Comment(8)
Thank you for your effort. Unfortunately this aproach did not work for me either. Does it make any difference where my tailwindcss.css file is located or named?Crawler
I think we would need to look into Storybook's default Webpack config. I am surprised that your index.css is getting copied to the build directory. I'll attach the contents of my built storybook-static to my answer for comparison.Almshouse
If you post a repro repo, I can take a look.Almshouse
thank you that is very nice of you. I just removed the line that my index.css is part of the storybook-static. I added it will try/error via -s flag when building storybook. When I look at my storybook-static then it looks the same as yours. I will try and setup repro repo. Thanks a lot. i really appreciate it!Crawler
I posted a repro repo in my questionCrawler
Got it: I'll add to my answer above.Almshouse
Glad I could help :) Btw, I've pushed a repo to Github with a few more potentially helpful changes: 1) I recommend using Tailwind's new JIT mode; 2) your tsconfig includes were a little broken; 3) I included a pattern for writing stories in Typescript: github.com/jcamden/SO-68020712-revised/commit/…Almshouse
import 'tailwindcss/tailwind.css'; worked for meSalpingitis
I
17

The above solutions will not work for Tailwind version > 3.0 because of JIT compiler.

Solution 1: Easy solution

in .storybook/preview.js file add this line to compile tailwind generated css files like this -

import '!style-loader!css-loader!postcss-loader!tailwindcss/tailwind.css';

Here tailwindcss/tailwind.css is the tailwind css file. Look, important is I've to add !postcss-loader! to compile tailwind generated css.

You can add also your custom scss file like this if any -

import '!style-loader!css-loader!sass-loader!../src/scss/style.scss';

Here ../src/scss/style.scss is custom scss file.

For most of the people this will work in Tailwind version > 3.0 without any issue.

Solution 2: Kinda Hack solution

Create a custom styled element in preview page

import tailwindCss from '!style-loader!css-loader!postcss-loader!sass-loader!tailwindcss/tailwind.css';
const storybookStyles = document.createElement('style');
storybookStyles.innerHTML = tailwindCss;
document.body.appendChild(storybookStyles);

Hope, this will help for new Tailwind users who are working in Tailwind greater than v3.0.

Isogloss answered 21/1, 2022 at 18:11 Comment(4)
added this but the disabled:opacity-25 class still doesn't work, any ideas?Thrill
Can you try extending tailwind.config.js by adding this - variants: { extend: { opacity: ['disabled'], }, },Isogloss
My custom styles in index.css alson still doesn't work in storybook, but works in normal react app. Open to your thoughts too...Outstay
Your first solution worked perfectly for me with Gatsby 4.2.0, TailwindCSS 3.1.7, PostCSS 8.4.14, @storybook/react 6.5.10.Pirtle
A
16

UPDATE: My original answer could be useful to others, so I'll leave it for reference. However, in this case, the problem was in tailwind.config.js.

Change

purge: {
    mode: 'all',
    content: [
      './src/components/**/**/*.{ts, tsx}'
    ],
  },

to

purge: ['./src/**/*.{js,jsx,ts,tsx}'],

ORIGINAL:

Just tested it out and storybook builds as expected for me. I think the key difference in our configurations is that I am not making changes to Storybook's webpack config in main.js. Rather, I am using @storybook/addon-postcss for postcss@^8 (required for tailwind@^2):

// main.js
module.exports = {
  ...
  addons: [
    ...
    {
      name: '@storybook/addon-postcss',
      options: {
        postcssLoaderOptions: {
          implementation: require('postcss'),
        },
      },
    },
  ],
};

I specify the necessary plugins in a postcss.config.js (in my project root):

// postcss.config.js
module.exports = {
    plugins: {
      tailwindcss: {},
      autoprefixer: {},
    },
  }

It's also worth noting that I import Tailwind directly in Storybook's preview.js instead via my own css file:

// preview.js
import 'tailwindcss/tailwind.css';
export const parameters = {...}

Hopefully, making those changes will get Tailwind working for you.

For comparison (see comments below), here are the contents of my build storybook-static directory:

contents of storybook-static directory

Almshouse answered 17/6, 2021 at 15:20 Comment(8)
Thank you for your effort. Unfortunately this aproach did not work for me either. Does it make any difference where my tailwindcss.css file is located or named?Crawler
I think we would need to look into Storybook's default Webpack config. I am surprised that your index.css is getting copied to the build directory. I'll attach the contents of my built storybook-static to my answer for comparison.Almshouse
If you post a repro repo, I can take a look.Almshouse
thank you that is very nice of you. I just removed the line that my index.css is part of the storybook-static. I added it will try/error via -s flag when building storybook. When I look at my storybook-static then it looks the same as yours. I will try and setup repro repo. Thanks a lot. i really appreciate it!Crawler
I posted a repro repo in my questionCrawler
Got it: I'll add to my answer above.Almshouse
Glad I could help :) Btw, I've pushed a repo to Github with a few more potentially helpful changes: 1) I recommend using Tailwind's new JIT mode; 2) your tsconfig includes were a little broken; 3) I included a pattern for writing stories in Typescript: github.com/jcamden/SO-68020712-revised/commit/…Almshouse
import 'tailwindcss/tailwind.css'; worked for meSalpingitis
Y
13

I had a similar problem. My problem was solved by adding: import "../src/index.css"; to .storybook/preview.js

Yung answered 4/8, 2022 at 9:11 Comment(3)
Thanks, this worked for me as well in a Vite + Vue 3 project.Pander
What a life-saver of an answer!Cown
thanks also work for my react 18.2.0Haycock
D
4

The following configuration will enable so Tailwind generate CSS as new tailwind classes are added to the markup in dev mode (hot reload).

In summary, I don't think @storybook/addon-postcss works with Tailwind JIT and Storybook hot reload, and the workaround is to use the postcss-loader webpack loader.

Install these deps:

@storybook/builder-webpack5 @storybook/manager-webpack5 postcss-loader webpack (must be version 5)

// .storybook/main.js
const path = require("path");

module.exports = {
  stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/addon-interactions",
    // {
    //   name: "@storybook/addon-postcss",
    //   options: {
    //     postcssLoaderOptions: {
    //       implementation: require("postcss"),
    //     },
    //   },
    // },
  ],
  framework: "@storybook/react",
  core: {
    builder: "webpack5",
  },
  webpackFinal: (config) => {
    config.module.rules.push({
      test: /\.css$/,
      use: [
        {
          loader: "postcss-loader",
          options: {
            postcssOptions: {
              plugins: [require("tailwindcss"), require("autoprefixer")],
            },
          },
        },
      ],
      include: path.resolve(__dirname, "../"),
    });
    return config;
  },
};
// .storybook/preview.js
import "../styles/globals.css";

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
  },
};
// postcss.config.js
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};
Ding answered 14/4, 2022 at 21:31 Comment(1)
This worked for me after upgrading to webpack 5Poling
D
2

For those who are still having this problem and is using postcss >= 8, I suggest you to do as following. Add this to tailwind.config.js

// eslint-disable-next-line @typescript-eslint/no-var-requires
const path = require("path")

module.exports = {
  content: [path.join(__dirname, "./src/**/*.(js|jsx|ts|tsx)")],
  theme: {
    extend: {},
  },
  variants: {}
  plugins: [],
}

Add this to preview.js

import "!style-loader!css-loader!postcss-loader!tailwindcss/tailwind.css"

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
  },
}

This has helped me fix the problem and I hope it can help you too

Disturbing answered 10/11, 2022 at 19:5 Comment(0)
W
2

When you try to create a storybook while using Tailwind CSS, you will notice that the CSS is not being applied. There is a simple solution that has helped me.

Your preview.js should be like.

  export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
  },
};

And you will need to add the following line in the preview.js to fix it.

// Add the below import line

  import "!style-loader!css-loader!postcss-loader!tailwindcss/tailwind.css";

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
  },
};

However this will be a temporary fix. To get this resolved completely, you will need to add the below mentioned package.

yarn add -D @storybook/addon-postcss

For reference, click here How to add postcss

Winnow answered 7/12, 2022 at 14:51 Comment(2)
This is working for me partially. When I try to use @apply on a css module and import it into the component, it doesn't work. Any ideas?Rebatement
Yes @apply its not working for me etherMarra
I
2

The solutions mentioned above worked but only partially. I was facing 2 issues:

  1. If I added new classes to stories then tailwind was not adding corresponding styles associated with the classes.
  2. Hot reloading wasn't working.

Solution: Add the path to the stories folder in the tailwind.config.js file.

module.exports = {
  content: [
    "./pages/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
    "./stories/**/*.{js,ts,jsx,tsx}", //needed to make hot reload work with stories
  ],
  theme: {},
  plugins: [],
}
Iminourea answered 10/2, 2023 at 11:24 Comment(0)
N
2

For anyone using Next.js: Try these

  1. Storybook Next.js Recipe
  2. Storybook TailwindCSS Recipe

NOTE : In step 2 of the tailwindcss storybook recipe, where you need to Provide Tailwind to stories, the guide suggests importing tailwind.css file in .storybook/preview.js as mentioned here.

But for my setup, there was no separate tailwind.css file, what worked for me instead was that I imported globals.css file from default Next.js file structure setup as:

In .storybook/preview.ts:

import '../styles/globals.css';

Provided that tailwind directives are added to globals.css: This is how my globals.css starts like -

@tailwind base;
@tailwind components;
@tailwind utilities;
...

So, in conclusion, I believe any css file containing base directive imports of tailwindmight just work (I might be wrong) when imported in preview.ts... what I showed above might just work for most Next.js users.

Please leave a comment if it doesn't work.

Nicotiana answered 12/2 at 1:33 Comment(1)
Snapshot of webpages as of when this answer was posted, as there are possibilities that links might have been updated/moved or content has been updated. 1. Next.js Recipe on 12th Feb 2024 2. Tailwind Recipe on 12th Feb 2024Nicotiana
L
1

if you using storybook with TSdx and tailwind css you should be able to import a CSS into components

  1. To be able to import your CSS into components, you will need to tell TSDX how to include it with your code. For that, you will need to install rollup-plugin-postcss (as TSDX uses rollup).
  2. Create a CSS file in your src directory which we will use in any component in which we want to use Tailwind.

Alright, so now let's add rollup-plugin-postcss:

yarn add -D rollup-plugin-postcss

TSDX is fully customizable and you can add any rollup plugin, but be aware that it overrides the default behavior

Now you'll create a

tsdx.config.js

// tsdx.config.js

const postcss = require('rollup-plugin-postcss');

module.exports = {
  rollup(config, options) {
    config.plugins.push(
      postcss({
        config: {
          path: './postcss.config.js',
        },
        extensions: ['.css'],
        minimize: true,
        inject: {
          insertAt: 'top',
        },
      })
    );
    return config;
  },
};

This is giving a postCSS path, which tells it what files you want it to run on. The minimize key is to allow you to minimize the output. The most important key here is the "inject". you set it to "top" to tell postCSS where inside the of our page the CSS will be inserted. It's paramount for Tailwind as it needs to have the utmost priority of any other stylesheet.

Next, for part 2, you will create a tailwind.css (can be named anything else) file under the src directory and paste this in:

// src/tailwind.css
@tailwind base;
@tailwind components;
@tailwind utilities;

Add the CSS import statement to your component

// src/Thing.tsx

import React, { FC, HTMLAttributes, ReactChild } from 'react';

// ! Add the CSS import statement !
import './tailwind.css`;

// ...

// we'll add some Tailwind classes on our components to test

export const Thing: FC<Props> = ({ children }) => {
  return (
    <div className="flex items-center justify-center w-5/6 m-auto text-2xl text-center text-pink-700 uppercase bg-blue-300 shadow-xl rounded-3xl">
      {children || `the snozzberries taste like snozzberries`}
    </div>
  );
};
Loferski answered 14/4, 2022 at 2:47 Comment(0)
N
0

I couldn't work this out and the above answered didn't work for me, so I eventually just set my build-storybook script to run tailwind itself after the build. package.json scripts looked like this in the end:

"build-storybook": "build-storybook -s public && $(npm bin -g)/tailwindcss -i storybook-static/static/css/main.*.chunk.css -o storybook-static/static/css/main.*.chunk.css -m",

Bit of a mess, but $(npm bin -g)/ here uses my globally installed (npm i -g tailwindcss) version of tailwindcss as the version installed to the project wasn't working in builds for me.

-i and -o specifies the input and output files, and -m minifies the output.

I can foresee this causing problems if more than one CSS file gets built (maybe using storybook-static/static/css/**/*.css would work instead?), but this might help someone just get something working.

Neanderthal answered 7/9, 2021 at 14:40 Comment(0)
S
0

For tailwind version > 3.0.0 add this import this line in file --> .storybook/preview.ts | js

import '!style-loader!css-loader!postcss-loader!tailwindcss/tailwind.css';

Now your tailwind CSS classes will work with storybook build.

Selfdeception answered 1/5 at 18:38 Comment(0)
D
0

Other Solutions

I've reviewed all the posts and discovered that the root issue lies in the Tailwind configuration, specifically in the tailwind.config.ts file.

Many solutions here are project-specific and don't fully explain the underlying issue. I hope to provide a more generic solution that can be applied universally to various projects.

Root Cause

The issue is that Tailwind doesn't know to JIT compile or hot reload for Storybook files by default. This results in missing styles when using Storybook. When you run Storybook alongside your dev server, it may work because the styles are being compiled and referenced from the dev server, but this is not a reliable setup.

Solution

To fix this, you need to tell Tailwind where to find all your project content files using the content property in your tailwind.config.ts. This way, Tailwind can properly include your Storybook files in its compilation process.

Here's an example of how to configure this:

const config: Config = {
  content: [
    "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
    /**
      *  Add the below line:
      *  Customise the match pattern to target the Storybook story
      *  files in your project per your projects directory structure
      */
    "./src/stories/**/*.{js,ts,jsx,tsx,mdx}"
  ],
  // ...the rest of the configuration
}
export default config;

Explanation

In the above configuration:

  • "./src/pages/**/*.{js,ts,jsx,tsx,mdx}" specifies to look for all files in the ./src/pages directory and its subdirectories with extensions js, ts, jsx, tsx, and mdx.
  • The additional line "./src/stories/**/*.{js,ts,jsx,tsx,mdx}" ensures that Tailwind includes Storybook story files in its compilation process.

By including the ./src/stories directory (you should change this to match where your Storybook files are located), Tailwind can now watch and compile styles for those files correctly.

This approach resolved the issue for me and aims to provide context so that that the solutions should be easily adaptable to other projects.

Declass answered 24/6 at 14:32 Comment(0)
G
-1

in taiwind config content: ["./src/**/*.{js,jsx,ts,tsx}","./nodemodules/ @yourstorybooklib/**/*.{js,jsx,ts,tsx}"]

Genous answered 8/5 at 12:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.