nx: TailwindCSS not working in NX NextJS project.

Current Behavior

Following the egghead tutorial for a NextJS project with a new nx-workspace, installing Tailwind is not working. Tailwind styles are not applied to the page.

Follow steps in this guide: https://egghead.io/lessons/tailwind-setup-next-js-with-tailwind-in-a-nx-workspace or in the steps to reproduce below.

Expected Behavior

Tailwind styles are applied to the page.

Steps to Reproduce

npx create-nx-workspace zip-finder --packageManager=yarn

What to create in the new workspace? next Application name? app Default stylesheet format css Use Nx cloud no

cd zip-finder (workspace name) yarn add -D tailwindcss@latest postcss@latest autoprefixer@latest

cd apps/app npx tailwindcss init -p

Replace pages/styles.css with

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

.test { 
  color: red;
}

Replace postcss.config.js with:

const { join } = require('path');

module.exports = {
  plugins: {
    tailwindcss: {
      config: join(__dirname, 'tailwind.config.js'),
    },
    autoprefixer: {},
  },
};

Replace pages/index.tsx with something simple like:

export function Index() {
  return (
    <div className="test bg-gray-500">
      <h1>Testing Tailwind!</h1>
    </div>
  );
}

export default Index;

You should see the test class applying the color red to the text, but no Tailwind classes are applied. If you search tailwind in the Dev Tools Elements panel, you’ll see Tailwind is loaded in the DOM.

Adding this to tailwind.config.js doesn’t help either:

content: [
    "./pages/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
  ],

Best way to repro is from @juristr 's egghead tutorial (which is the same as the steps listed above).

Failure Logs

Environment

Nx Report:

Node : 12.18.3
  OS   : darwin x64
  yarn : 1.22.10
  
  nx : 13.4.2
  @nrwl/angular : undefined
  @nrwl/cli : 13.4.2
  @nrwl/cypress : 13.4.2
  @nrwl/devkit : 13.4.2
  @nrwl/eslint-plugin-nx : 13.4.2
  @nrwl/express : undefined
  @nrwl/jest : 13.4.2
  @nrwl/linter : 13.4.2
  @nrwl/nest : undefined
  @nrwl/next : 13.4.2
  @nrwl/node : undefined
  @nrwl/nx-cloud : undefined
  @nrwl/react : 13.4.2
  @nrwl/react-native : undefined
  @nrwl/schematics : undefined
  @nrwl/tao : 13.4.2
  @nrwl/web : 13.4.2
  @nrwl/workspace : 13.4.2
  @nrwl/storybook : 13.4.2
  @nrwl/gatsby : undefined
  typescript : 4.4.4
  rxjs : 6.6.7
  ---------------------------------------
  Community plugins:

Tailwind 3.x.x is used, but I couldn’t find any different install instructions vs. the 2.x.x version used in the egghead tutorial.

Thanks for having a look!

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 6
  • Comments: 32 (2 by maintainers)

Commits related to this issue

Most upvoted comments

So, I just got it working. In tailwind.config.js, I had to set content path from root explicitly. Maybe something has changed from Tailwind 2.x.x --> 3.x.x?

// my-monorepo/apps/site/tailwind.config.js

module.exports = {
  // content: [], <-- not working
  // content: ['./pages/**/*.{js,ts,jsx,tsx}'], <-- not working
  content: ['apps/site/pages/**/*.{js,ts,jsx,tsx}'],
  theme: {
    extend: {}
  },
  plugins: []
};

just use this in styles/globals.css

@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';

I got it working with the following config (react app not nextjs but I think it should work)

postcss.config.js

module.exports = {
  plugins: {
    tailwindcss: { config: './tailwind.config.js' },
    autoprefixer: {},
  },
};

tailwind.config.js

module.exports = {
  mode: 'jit',
  content: ['./src/**/*.{js,ts,jsx,tsx,html,css}'],
  theme: {
    extend: {},
  },
  plugins: [],
};
const { join } = require('path');

module.exports = {
  content: [
    join(__dirname, "pages/**/*.{js,ts,jsx,tsx}"),
    join(__dirname, "components/**/*.{js,ts,jsx,tsx)"),
  ],
  theme: {
    extend: {},
  },
  plugins: [
    require('@tailwindcss/forms'),
  ],
}

This fixed the problem for me

I also encountered this error with my Next.js project (unrelated to the Egghead course mentioned by others). What fixed it for me was creating a src folder and moving my pages, component etc folders. So my setup is exactly the same as outlined in the installation guide , except I’m using a src folder and my tailwind.config.js looks:

module.exports = {
  content: ['./src/pages/**/*.{js,jsx,ts,tsx}', './src/components/**/*.{js,jsx,ts,tsx}'],
  theme: {
    extend: {},
  },
  plugins: [],
}

I’m having issues getting the components that are library generated to render the styles with the rest of the application.

I’ve been following this article and with help from the comments above I got my main application to render styles.

Here’s the kicker, the library styles only work if they are first added as a class to an element in the app. If that same class appears on an element in the library the style will work. If the class in the library does not appear in the application than the style does not appear.

Any Idea how to fix this?

Ref

/apps/cms/postcss.config.js

const {join, dirname} = require('path');
// Following this guide
// https://blog.nrwl.io/setup-next-js-to-use-tailwind-with-nx-849b7e21d8d0

module.exports = {
  plugins: {
    tailwindcss: {
      config: join(__dirname, 'tailwind.config.js'),
    },
    autoprefixer: {},
  },
};

/app/cms/tailwind.config.js

const { join } = require('path');
const { createGlobPatternsForDependencies } = require('@nrwl/next/tailwind');

// apps/site/tailwind.config.js

module.exports = {
  presets: [require('../../tailwind-workspace-preset.js')],
  mode: 'jit',
  content: [
    join(__dirname, '**/*.{js,ts,jsx,tsx}'),
    ...createGlobPatternsForDependencies(__dirname),
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};

/tailwind.workspace.config

module.exports = {
  // since we already have our own resets for both app and view, we don't use the tailwind preflight reset
  corePlugins: {
    preflight: false,
  },

  // we also enable !important, because we often need to override materials base css, and without it, we will have to add ! to every statement anyways
  important: true,
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
}

/tsconfig.base.json

{
  "compileOnSave": false,
  "compilerOptions": {
    "rootDir": ".",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "importHelpers": true,
    "target": "es2015",
    "module": "esnext",
    "lib": ["es2017", "dom"],
    "skipLibCheck": true,
    "skipDefaultLibCheck": true,
    "baseUrl": ".",
    "paths": {
      "@evolvingsoftware/tailwind-ui": ["./libs/tailwind-ui/src/index.ts"]
    }
  },
  "exclude": ["node_modules", "tmp"]
}

/apps/cms/tsconfig.json

{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "jsx": "react-jsx",
    "allowJs": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true
  },
  "files": [],
  "include": [],
  "references": [
    {
      "path": "./tsconfig.lib.json"
    },
    {
      "path": "./tsconfig.spec.json"
    }
  ]
}

just use this in styles/globals.css

@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';

I switched from @tailwind ... to @import ... syntax and it works. But the weird thing is after that I switched back to @tailwind ... and it still works. Maybe it related to the caching of next.

The guide here is up to date to provide correct config, with purging as well.

https://nx.dev/guides/using-tailwind-css-in-react

The main thing is the utility we provide for including dependencies in content.

// apps/app1/tailwind.config.js
const { createGlobPatternsForDependencies } = require('@nrwl/react/tailwind');
const { join } = require('path');

module.exports = {
  content: [
    join(
      __dirname,
      '{src,pages,components}/**/*!(*.stories|*.spec).{ts,tsx,html}'
    ),
    ...createGlobPatternsForDependencies(__dirname),
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};

If you are having more issues after following the guide, please re-open a new issue with more details on what is wrong.

Hello Community,

I faced the same issue and found a solution.

Some background: let’s keep in mind that we have to different tailwind.config.js configuration files. One for the web app package and the other one for the component library.

The solution was to include the path to my component’s library in the tailwind.config.js content section of my web application package. When I was running into this issue, the path to my component library was not present in the config file for the web app.

To summarize, you must include the path to your component library folder in the tailwind configuration file for your web project (even if it is outside the app/package folder) as well as the configuration file for your component library.

You will end up with a tailwind.config.js in ./packages/webapp/ that looks something like this (note that I am pointing to a folder outside this package):

module.exports = {
  content: [
    "./packages/comodin-web-app/pages/**/*.{js,ts,jsx,tsx}",
    "./packages/comodin-web-app/components/**/*.{js,ts,jsx,tsx}",
    "./packages/shared/ui/src/lib/**/*.{js,ts,jsx,tsx}", //this was missing
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

and a tailwind.config.js in ./packages**/shared/**ui that looks something like this:

module.exports = {
  content: [
    "./packages/shared/ui/src/lib/**/*.{js,ts,jsx,tsx}", //this path must also be include in the web app configuration
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

I hope this helps.

Note: this configuration does not consider css purging. I will update my answer once I have that feature configured.

Note 2: there is a concept of tailwind presets see here and here that may result in a more elegant approach to import the content for your component library styles.

I have the same problem, someone found the solution?

Guys, mb it will help someone. I had same problem and it was because I forgot to put import '../styles/globals.css'; into my _app.tsx file in pages.

I’m having issues getting the components that are library generated to render the styles with the rest of the application.

I’ve been following this article and with help from the comments above I got my main application to render styles.

Here’s the kicker, the library styles only work if they are first added as a class to an element in the app. If that same class appears on an element in the library the style will work. If the class in the library does not appear in the application than the style does not appear.

Any Idea how to fix this?

Ref

/apps/cms/postcss.config.js

const {join, dirname} = require('path');
// Following this guide
// https://blog.nrwl.io/setup-next-js-to-use-tailwind-with-nx-849b7e21d8d0

module.exports = {
  plugins: {
    tailwindcss: {
      config: join(__dirname, 'tailwind.config.js'),
    },
    autoprefixer: {},
  },
};

/app/cms/tailwind.config.js

const { join } = require('path');
const { createGlobPatternsForDependencies } = require('@nrwl/next/tailwind');

// apps/site/tailwind.config.js

module.exports = {
  presets: [require('../../tailwind-workspace-preset.js')],
  mode: 'jit',
  content: [
    join(__dirname, '**/*.{js,ts,jsx,tsx}'),
    ...createGlobPatternsForDependencies(__dirname),
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};

/tailwind.workspace.config

module.exports = {
  // since we already have our own resets for both app and view, we don't use the tailwind preflight reset
  corePlugins: {
    preflight: false,
  },

  // we also enable !important, because we often need to override materials base css, and without it, we will have to add ! to every statement anyways
  important: true,
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
}

/tsconfig.base.json

{
  "compileOnSave": false,
  "compilerOptions": {
    "rootDir": ".",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "importHelpers": true,
    "target": "es2015",
    "module": "esnext",
    "lib": ["es2017", "dom"],
    "skipLibCheck": true,
    "skipDefaultLibCheck": true,
    "baseUrl": ".",
    "paths": {
      "@evolvingsoftware/tailwind-ui": ["./libs/tailwind-ui/src/index.ts"]
    }
  },
  "exclude": ["node_modules", "tmp"]
}

/apps/cms/tsconfig.json

{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "jsx": "react-jsx",
    "allowJs": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true
  },
  "files": [],
  "include": [],
  "references": [
    {
      "path": "./tsconfig.lib.json"
    },
    {
      "path": "./tsconfig.spec.json"
    }
  ]
}

I am not completely sure that I understood the problem you’re facing fully, however I might have encountered the similar issue that I’ll try to explain briefly, as well as the approach that solved the issue for me. My setup was using Angular application and several different Angular (SCAM - Single component Angular module) libraries that were independent of the application - they are standalone libraries (however, not buildable and do not have their separate TailwindCSS configuration files) that had UI components defined inside of them.

So, to put into perspective and give a little context, I had the following setup in my NX workspace:

/apps
  /platform
/libs
  /shell
    // ...as per Angular SCAM approach, this module imports all other feature modules and sets up the routing for an application
  /layout
    // ...some module and container component in here, that are using TailwindCSS and Angular (custom theming) styles
  /card
    // ...some UI components that also have been using the TailwindCSS and Angular (custom theming) styles
  /feature-1
    // ...some ui and page (routable components) that were also using the TailwindCSS and Angular (custom theming) styles

As if you were to image, my application is just importing shell module and has no features / content defined at all from within the application directory - it is pretty slim, with just a single component. Hence, the only thing present in my app.component template is the <router-outlet></router-outlet> and everything else comes from feature libraries imported into the shell module.

Now that we got that out of the way (disclaimer: it is not of a great importance to completely understand the architecture of the application, but rather that I had the library approach for different UI elements) let me clarify the issue that I have encountered and how I managed to solve it.

Once the application is started I see that no TailwindCSS styles are applied to my application elements. If you were to remember as explained previously, I had no UI elements defined in the application itself, but rather there were coming from my feature modules (NX Angular libraries).

On the other hand, if I was to define an element in my app.component.html file and apply TailwindCSS classes on that element, they were applied properly, but only to that element. The rest of application is still not styled properly and pretty ugly. So I figured, it has something to do with the feature (SCAM) library approach I was using, with UI components / pages coming from within NX (Angular) defined libraries. And since they were never strictly referenced in the application component template, the styles never got resolved properly and never got applied to any UI element coming from the library.

How I managed to fix it, is basically create the right glob pattern, as you already explained. However, I needed to change a configuration just a little, to point Tailwind to the right path.

The configuration in my tailwind.config.js file that was defined by default when the application was generated using NX schematics had the following line of code:

...
content: [
  ...createGlobPatternsForDependencies(__dirname),
],
...

And for some reason was not able to pickup any styles defined in the UI components. In other words, no styles got applied to any of the UI elements defined in my feature libraries (as they were not referenced / used from within the application template).

After a few tweaks, I was able to fix this issue by constructing the right path to source files using the following fix in my tailwind.config.js file:

...
content: [
  ...createGlobPatternsForDependencies(path.join(__dirname, 'src/**/*.{html,ts}')),
],
...

After this change, all the styles were applied properly to all the UI elements, no matter if they were defined in the feature libraries or directly in my app.component template.

Note: I am currently having a single (Angular) application, but am still using project based tailwind.config.js files (TailwindCSS config file per application). I am not using a single global tailwind.config.js file in the root of my workspace. This is as to how the application was structured for me using the NX schematics and is a best practice from my understanding (as I found out the reason why, reading the following issue: https://github.com/nrwl/nx/issues/8072).

I hope this might be useful to others that encountered the same / similar issue like me, of not having styles properly applied to elements / pages defined in the libraries (that were not referenced directly in the application component templates) and being properly defined in the elements / classes used from within the application that has TailwindCSS configured using tailwind.config.js file.

Disclaimer: I do not think that this is framework specific approach, although I might be wrong, and should work as long as the styles are not properly applied to library defined UI elements that are not used from within the application templates.

Hello. I posted a working (for me) example here: https://github.com/nrwl/nx/issues/8072#issuecomment-1018089879