'Getting the error "Nested CSS was detected, but CSS nesting has not been configured correctly" in React app?

I've been upgrading my CRA project to TailwindCSS 3, but now CSS nesting no longer works. Upon starting the server, the console spits out:

(8:3) Nested CSS was detected, but CSS nesting has not been configured correctly.
Please enable a CSS nesting plugin *before* Tailwind in your configuration.
See how here: https://tailwindcss.com/docs/using-with-preprocessors#nesting

However, I don't see what must be done to correct this. I've tried setting up a plain CRA project with Tailwind (following this guide) just to make sure I have no conflicts, and still no success.

postcss.config.js:

module.exports = {
  plugins: {
    "tailwindcss/nesting": {},
    tailwindcss: {},
    autoprefixer: {},
  },
};

As you can see, I have added the nesting plugin before Tailwind. It appears to me as if the plugin isn't being detected whatsoever. I've also tried replacing it with postcss-nesting with same outcome.

Note: I've also tried using the array syntax with require('tailwind/nesting') like the guide suggests.

Interestingly, removing all plugins from postcss.config.js (or using a require that fails to resolve) still outputs the same error, implying that this file isn't needed to get Tailwind to load. Maybe I am missing something that causes the whole postcss.config.js file to not be loaded in the first place?


index.js:

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";

ReactDOM.render(
  <React.StrictMode>
    <div className="a">
      aaa
      <div className="b">bbb</div>
    </div>
  </React.StrictMode>,
  document.getElementById("root")
);

index.css:

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

.a {
  @apply text-blue-500;

  .b {
    @apply text-green-500;
  }
}

package.json: (omitted things for brevity)

{
  "name": "tailwindtest",
  "dependencies": {
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "5.0.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "devDependencies": {
    "autoprefixer": "^10.4.2",
    "postcss": "^8.4.5",
    "tailwindcss": "^3.0.12"
  }
}


Solution 1:[1]

This is mostly just bad news.

Create React App's Tailwind support means that they will detect tailwind.config.js in the project and add tailwindcss to their existing postcss configuration. Source in CRA

The guide that Tailwind offers on their site creates a dummy postcss.config.js - Making changes in this file does not change the actual postcss configuration. (misleading if anything)

This is a known issue currently - Github discussion on Tailwind support PR between Adam Wathan (Tailwind founder) and Ian Sutherland (CRA maintainer). But it does not seem like there is an intention to be fixed soon.

If you want to use nesting (or any PostCSS plugin really) is to eject from CRA using:

npm run eject

After ejecting you can find CRA's postcss configuration in config/webpack.config.js - look for postcss-loader. Editing the configuration there can enable any postcss features.

PS: Look out for postcss-preset-env in the default configuration while enabling nesting. Tailwind requires you to edit configuration if this is present.

Solution 2:[2]

I use CRA and to fix the issue I used postinstall to run a script after npm install or yarn. The script is changing the web pack config of CRA after all dependencies are installed(a temporary solution of cause). You can find the web pack config in node_modules/react-scripts/config/webpack.config.js. The script adds my postcss packages to the actual CRA web pack config.

WHY? CRA does not respect any postcss config in your repo

Have also a look at this comment to see how you should use postinstall https://github.com/facebook/create-react-app/issues/2133#issuecomment-347574268.

I also added tailwindcss/nesting before tailwindcss because tailwind is throwing a warning when it sees any nested css. The warning was blocking my CI since CI=true in CRA means all warnings are treated as errors.

Here is the script that is running in my repo.

FILE="node_modules/react-scripts/config/webpack.config.js"

function replace {
  TARGET_FILE=$1
  PATTERN_TO_FIND=$2
  VALUE_FOR_REPLACEMENT=$3

  OLD_FILE_CONTENT=$(cat "$TARGET_FILE")  # we need to collect the content of the file so we can overwrite it in the next command
  echo "$OLD_FILE_CONTENT" | sed -e "s/$PATTERN_TO_FIND/$VALUE_FOR_REPLACEMENT/g" > "$TARGET_FILE"
}

# add postcss-nesting
replace "$FILE" "'postcss-flexbugs-fixes'," "'postcss-flexbugs-fixes','postcss-nesting',"

# add tailwind/nesting
replace "$FILE" "'tailwindcss'," "'tailwindcss\/nesting', 'tailwindcss',"

Solution 3:[3]

acording to @aricma answer, is easier if you create a script.js file on parent directory (same as package.json) and add this on package.json

  "scripts": { 
    "postinstall": "node script.js",
    ...
  }

and this on script.js

const fs = require('fs');

fs.readFile('node_modules/react-scripts/config/webpack.config.js', 'utf8', (err, data) => {
  if (err) {
    return console.log(err);
  }
  const result = data.replace("'postcss-flexbugs-fixes',", "'postcss-flexbugs-fixes','postcss-nesting',").replace("'tailwindcss',", "'tailwindcss/nesting', 'tailwindcss',");

  fs.writeFile('node_modules/react-scripts/config/webpack.config.js', result, 'utf8', (err) => {
    if (err) {
      return console.log(err);
    }
    return console.log(true);
  });
  return console.log(true);
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Agney
Solution 2 aricma
Solution 3 Rey David C.V.