However, there can be times when Tailwind doesn’t work as expected with Next. It could be a variety of reasons, so in this article, we’ll take a look and learn how to solve them so you can continue making performant applications.
Common issues with Tailwind CSS and Next.js
There are two categories of problems that we may face while setting up Tailwind with Next. The first problem is the incorrect usage of Tailwind features and functionalities. It includes any of the following:
- Not having the Tailwind directives in the main CSS file
- Using the incorrect class names in the template files
- Using extension utilities without installing the required plugin
The second category of issues stem from improper or incomplete configuration of Tailwind or Next. If you have used Tailwind before, you may already know about the configuration files created when we run the Tailwind
It could also be some options in the Next config file that may be causing the problem. These configuration issues can be any or all of the following:
- Usage of the old purge method to specify source paths in Tailwind 3.0, which is redundant now
- Lack of the correct content path. Next offers a slightly different project structure compared to a regular React project
- Not defining the dynamic paths when using a modern build system like Nx
- Using the Next experimental features
In this tutorial, we’ll learn the correct ways to fix all these problems.
Setting up a Next.js project with Tailwind CSS
Let’s keep it step-by-step and start with the standard way to install Next. After confirming you are in the right install location, run the below given standard command to install Next:
Note that if you use a modern packaging system like yarn or npm, there are separate sets of installation commands.
You’ll get asked to pick a name for the app, and a few more options like installing support for TypeScript. Make suitable choices and wait while things finish setting up. This process may take some time, depending on your internet connection.
After the installation finishes, let’s
cd into our project directory, run our app and see if it’s working as expected:
cd debug-twcss yarn dev
Installing Tailwind CSS with Next.js
Now, let’s pause to install Tailwind and its prerequisites in our existing Next app with the commands below:
npm i -D Tailwind [email protected] [email protected] [email protected]
Alternatively, you can use the
yarn add ... command to install all these packages. After the packages get installed, let’s generate Tailwind configuration files with the following command:
npx Tailwind CSS init -p
The above command will add the
postcss.config.js files to the root of our project. Tailwind uses PostCSS extensively to function and recommends not to use any preprocessor alongside.
We have completed the primary phase of installing Tailwind CSS. Let’s add some of its utility classes to our index page and run the app.
It doesn’t seem to work. There are some styles visible like box-shadow, but it’s not even close to what we expected. Here’s a bit more on why this happens.
The next few steps will cover how to get it working by fixing the usual problems and configuration issues, one at a time.
Check for the correct directives
The first step is to ensure the global CSS file in our styles directory contains all the Tailwind directives.
Without these directives, Tailwind doesn’t know what base, utility, and component classes it should provide to the finished CSS based on their use in the content-path files:
/* debug-twcss/styles/global.css */ @tailwind base; @tailwind utilities; @tailwind components;
Avoid incorrect class names
There may be incorrect class names that can cause problems and keep you wondering for hours. Always double check that Tailwind class names have no typographical errors.
Visual Studio Code users can easily avoid these errors with the official Tailwind CSS IntelliSense extension. Here is a glimpse of the extension in action.
This extension will not only show you a list of autocomplete suggestions as you type class names in your project files, but also provides linting and syntax highlighting support for Tailwind-specific things.
Let’s assume you use the typography utility extension provided by Tailwind, but you missed installing the required plugin:
// debug-twcss/pages/post.js export default function Post() return ( <article className="entry p-16 [ prose md:prose-md lg:-prose-lg ]"> <p>...</p> <p>...</p> <p>...</p> </article> )
You won’t be able to see any
prose class in action in the front end unless you install the required extension. Let’s install the typography plugin now:
npm i -D @Tailwind CSS/typography
It’s not over yet. Let’s also specify the freshly-installed typography plugin in the
plugins option of the configuration file:
// debug-twcss/tailwind.config.js module.exports = content: ['./pages/**/*.html'], theme: extend: , , plugins: [ require('@Tailwind CSS/typography'), ],
content instead of
If you are used to the
purge option from older versions of Tailwind and using the same with a recent version, it could be why your project isn’t working.
Tailwind from v.3 onwards provides the
content property to add file paths.
If you’re wondering why
content is required, it helps the Tailwind CSS engine decide which pages to process and export their CSS classes to the final CSS file.
Here’s how easy it is to switch from
content with the latest version of Tailwind:
// debug-twcss/tailwind.config.js module.exports = content: ['...'], theme: extend: ,
Use correct paths
If you configure the content paths with Next the way you did with a React app, it will still not work. This is because Next offers a slightly different project structure compared to a traditional react project.
Unlike a traditional React project, there is no default
src directory in a Next project. We have a default
pages directory instead, where the page templates of our app reside.
More such directories can help keep things well-organized in future development. The
component directory fits best as an example here.
Therefore, we need to provide the path to the templates stored in the
pages and the
component folders in the
content variable of the Tailwind configuration file:
// debug-twcss/tailwind.config.js module.exports = content: [ "./pages/**/*.js,ts,jsx,tsx", "./components/**/*.js,ts,jsx,tsx", ], theme: extend: ,
There is a reason why some of the Tailwind utilities will work even if you don’t set anything up in the content option. That is because the actual purging happens only during the production build. Best practice is to set things up correctly only during development.
If we run the app now, there are chances that it will run perfectly, as we have fixed the most common issues already.
Use dynamic paths with build systems.
If your Next app is a part of a monorepo, you will have to optimize the path definitions in the config files to get Tailwind working.
A monorepo is a repository of many independent projects that may also share global utilities like Tailwind CSS. Having Tailwind work on a monorepo is a bit complicated, though.
Let’s see how to install or debug Tailwind CSS on a modern build system like Nx.
The installation process is nearly the same as we discussed above; the only thing you should ensure is to install the packages in the workspace root and not in apps or libs.
Initializing Tailwind for configuration is also the same; all you need is just
cd into the directory in which you want to use Tailwind:
cd apps/debug-twcss npx Tailwind CSS init -p
Now, we have both the Tailwind CSS and PostCSS config files created in our project’s root. We need to tell these files what project from the apps folder should use the Tailwind features:
// apps/debug-twcss/postcss.config.js const join = require('path'); module.exports = plugins: Tailwind CSS: config: join(__dirname, 'tailwind.config.js'), , autoprefixer: , , ;
--dirname variable, in this case, specifies the absolute path to the current directory dynamically.
We can do something similar with the
tailwind.config.js, and it will work, but let’s consider the project dependencies before going further.
libs directory in our Nx workspace contains project dependencies (like shared components) that might also be using Tailwind utilities. There’s a way to specify all these dependencies automatically in the config’s content option using an inbuilt Nx function:
// apps/debug-twcss/Tailwind CSS.config.js const createGlobPatternsForDependencies = require('@nrwl/next/tailwind'); const join = require('path'); module.exports = content: [ join(__dirname, 'pages/**/*.js,ts,jsx,tsx,html'), ...createGlobPatternsForDependencies(__dirname), ], theme: extend: , , plugins: , ;
The Tailwind engine will automatically observe all the project dependencies with the above additions to the config file.
If you have many of your projects in a monorepo using the same Tailwind settings, you may create a preset file with those settings in the workspace root and access it with the
preset option of the Tailwind config in your projects.
Turning off Next.js experimental features
Finally, it could be some experimental features messing with Tailwind and other packages you have installed within your Next.js app.
If you are using any such features, try turning them off by setting the
concurrentFeatures option to false in the
// debug-twcss/next.config.js /** @type import('next').NextConfig */ const nextConfig = swcMinify: true, reactStrictMode: true, experimental: concurrentFeatures: false, // <- Turn this option to false serverComponents: true, , module.exports = nextConfig
You might need to restart and rebuild the project to observe changes.
In this article we learned about the different scenarios of debugging Tailwind CSS issues with Next. The problems we discussed were mostly the configuration and usage issues.
I’m sure the solutions we discussed above will fix most of your problems. If you think something is missing or you are still experiencing a problem setting up Tailwind CSS, let me know in the comments.
LogRocket: Full visibility into production Next.js apps
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens on your Next app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app’s performance, reporting with metrics like client CPU load, client memory usage, and more.
The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.
Modernize how you debug your Next.js apps — start monitoring for free.