What causes the absence of CSS classes in production while utilizing Tailwind and next.js?

Tailwind version: v9.3.5

PostCSS Configuration:

// postcss.config.js

module.exports = {
   plugins: {
      tailwindcss: {},
      autoprefixer: {},
      ...(process.env.NODE_ENV === 'production'
         ? {
              '@fullhuman/postcss-purgecss': {
                 content: ['./components/**/*.js', './pages/**/*.js'],
                 defaultExtractor: content =>
                    content.match(/[\w-/:]+(?<!:)/g) || [],
              },
           }
         : {}),
   },
}

Tailwind Style Configuration:

// tailwind.config.js

module.exports = {
   theme: {
      extend: {
         colors: {
            tint: 'rgba(0,0,0,0.3)',
         },
      },
   },
   variants: {},
   plugins: [],
}

The styles are functioning correctly during development, however, in production only some styles are being applied. After examining the CSS file in the build folder, it appears that certain CSS classes are not being extracted or possibly purged, resulting in incomplete styling of the application.

Answer №1

UPDATE: The latest PurgeCSS version 3.0 introduces a safelist option, replacing the previously used whitelist.

I encountered a similar issue when dynamically injecting class names into my HTML template.
As I am using nuxt.js/tailwindcss, it is important to refer to the documentation for solutions.

Issue

The following code generates missing classes in production:

 computed: {
    axeY() {
      return this.y < 0 ? `-translate-y${this.y}` + ' ' : `translate-y-1` + ' '
    },
    axeX() {
      return this.x < 0 ? `-translate-x${this.x}` : `translate-x-${this.x}`
    },

PostCSS analyzes all files within the content table (defined in the configuration file), however, my files do not contain classes with the translate prefix.
It is evident that the missing classes are: [translate-x-1,-translate-x-1, translate-y-1, -translate-y-1] ... where the number 1 represents a variable.

Resolution

  • To prevent deletion of these classes, add them to the whitelist in PurgeCSS configuration
  • Alternatively, include them in your files, such as by creating an unless file analyzed by PostCSS

Specify content to be analyzed by PurgeCSS with an array of filenames

  • Update your TailWindCSS config file by specifying all core plugins used
  • In complex scenarios, utilize regular expressions in the config file.
    In my case, I directly configure purge in the TailWindCSS config file, passing the whitelist in the options variable. Here is a snippet of my config file when implementing the first solution:
/*
 ** TailwindCSS Configuration File
 **
 ** Docs: https://tailwindcss.com/docs/configuration
 ** Default: https://github.com/tailwindcss/tailwindcss/blob/master/stubs/defaultConfig.stub.js
 */
const num = [1, 2, 3, 4, 5, 6, 8, 10, 12]
const whitelist = []
num.map((x) => {
  whitelist.push('translate-x-' + x)
  whitelist.push('-translate-x-' + x)
  whitelist.push('translate-y-' + x)
  whitelist.push('-translate-y-' + x)
})
module.exports = {
  future: {
    removeDeprecatedGapUtilities: true,
  },
  theme: {},
  variants: {
    backgroundColor: ['hover', 'focus', 'active'],
  },
  plugins: [],
  purge: {
    // Learn more on https://tailwindcss.com/docs/controlling-file-size/#removing-unused-css
    enabled: process.env.NODE_ENV === 'production',
    content: [
      'components/**/*.vue',
      'layouts/**/*.vue',
      'pages/**/*.vue',
      'plugins/**/*.js',
      'nuxt.config.js',
    ],
    options: {
      whitelist,
    },
  },
}

Answer №2

After some investigation, I discovered the root cause of the issue. The postcss config was missing the sections folder in the content array. Additionally, since my JavaScript files contained jsx, it was necessary to include that as well.

// postcss.config.js

module.exports = {
   plugins: {
      tailwindcss: {},
      autoprefixer: {},
      ...(process.env.NODE_ENV === 'production'
         ? {
              '@fullhuman/postcss-purgecss': {
                 // added sections folder and changed extension to jsx
                 content: ['./components/**/*.jsx', './pages/**/*.js', './sections/**/**/*.jsx'],
                 defaultExtractor: content =>
                    content.match(/[\w-/:]+(?<!:)/g) || [],
              },
           }
         : {}),
   },
}

Answer №3

This particular issue gave me quite a challenge. Tailwind has the ability to remove classes that are generated through string concatenation.

One workaround is to store class names as variables.

const className = 'row-start-2';

className={className}

In my situation, using variables was not an option. Therefore, I opted for the safelist greedy approach.

In the Tailwind config file:


module.exports = {
  purge: {
    content: ["./src/**/*.{js,jsx}", "./public/index.html"],
    options: {
      safelist: {
        greedy: ["/safe$/"],
      },
    },
  },

Afterwards, I included the "safe" class in all elements where I needed to generate classes through string concatenation.

className={`safe sm:grid-cols-${smCols} sm:grid-rows-${smRows} md:grid-cols-${mdCols} md:grid-rows-${mdRows}`}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Discover the art of incorporating transient properties into the styled() function with @mui/system

I have been implementing import { styled } from "@mui/system"; in the following way: const Column = styled("div")<ColumnProps>` background: ${(props) => props.backgroundColor ?? "blue"}; `; export default function ...

Updating TextField Values with React Material UI

At the beginning of each session, I initialize the state with these variables: state = { firm: null, office: null, salesCode: null, account: null } Each TextField in my application is rendered like this: <TableCell> <TextFie ...

What is the process for incorporating a node.js module into Next.js?

Can I integrate the pdf2json npm module into my next.js application without using express? I'm attempting to include this code snippet in my next.js app: const fs = require('fs'); const PDFParser = require("pdf2json"); const pdfParser = ne ...

Fixed position does not adjust based on the screen resolution

If I were to create a web page, I would include a main menu that always remains on the screen, similar to this design: There are no issues with screen resolution exceeding 1300px, as seen in the image above. However, when attempting to resize the browser ...

Struggling to choose an element within $(this) despite being able to view it in the $(this) outerHTML

I have a question regarding jQuery 1.12. I am attempting to target an element within $(this). $(".select").bind('keydown', function(event) { elt = $(this)[0]; console.log(elt.outerHTML); elt = $(this)[0].search("li") console.log ...

NextJS Input Field causing a strange "Hydration Error indicating server HTML should not contain a <div> within a <form>", perplexingly occurring only in Chrome and exclusively on my personal computer

Looking for some assistance with a website I'm working on using NextJS and TailwindCSS. There seems to be a pesky little issue in my code that's causing some trouble. Below is the code snippet for the MainContent section of the page: "use c ...

ReactJs: `npm run build` encountering failure with Exit status 1

I am encountering an issue with my Create React App, Single Page Application. Every time I run the npm run build command, I receive the following error message : npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! <a href="/cdn-cgi/l/email-protection" ...

The content within the iframe is not properly sized

I'm facing a challenge with an iframe that has a fixed height of 1000px which I am unable to adjust. I would like the content to fit within the iframe. As a CSS novice, I need some guidance on how to achieve this. Thank you! <iframe style="height: ...

What is the best way to implement KaTeX in a React application?

Can someone help explain how KaTex can be incorporated into a React application? Despite reviewing the documentation on NPM, I am still having trouble understanding. I am specifically confused on how katex.render and katex.renderToString functions can be ...

Place the Material-UI Drawer component beneath the Appbar in the layout

Currently, I am working on developing a single-page application using Material-UI. In this project, I have integrated the use of an AppBar along with a ToolBar and a Drawer. However, I have encountered an issue where the Drawer is overlapping the AppBar an ...

Updating the text inside a div element in React when the state changes

Is it possible to dynamically update the text in a div tag based on changes in startDate and endDate values? Despite attempting to do so, the div continues to display old values. How can I ensure that the text in the div is updated when the state changes ...

The Material-UI checkbox in combination with react-hook-form V7 may not send the correct value when the checked value is programmatically changed

I've recently upgraded to react-hook-form V7.14.2 and encountered an issue with a Material-UI checkbox in my form. The checkbox can be manually checked by the user or automatically checked based on certain input values. While this functionality works ...

Issue with vertical alignment within nested divs

I have been attempting to center a search bar inside a top banner vertically. My understanding was that the following code could achieve this: #banner { height: 35px; width: 100%; } #searchbar { height: 15px; position: relative; top: 50%; ...

Ensuring type safety in React using TypeScript

Within the code snippet below, I have specified that setLocale should be passed a value of type Locale through LocaleContextValue. However, why does the setLocale function not throw an error if no value is provided as a parameter? Even when I change it t ...

Running a Redux Thunk action from within a TypeScript environment, beyond the confines of a React component

Currently, I am in the process of converting a React Native app into TypeScript. Unfortunately, I have encountered an issue with dispatching thunk actions outside of the store. Below is how my store is configured: store/index.ts import { createStore, app ...

What are the steps to incorporate an iframe containing uniquely designed XML content?

I'm currently working on a website project for a client who specifically wants to include news from the BBC. Despite spending 3 hours searching online, I haven't been able to successfully insert an XML file into an iframe and style it to the clie ...

Expanding Page Width Using iPad CSS Styling

I am currently experiencing some difficulties with my webpage and its header layout when viewed on an iPad versus a desktop. Upon visiting on a computer, the images and header/footer are intended to extend 100% to the edges of the screen. However, when ...

Sibling selector beside not functional

Trying to create a sliding sidebar without using JavaScript has presented me with a challenge involving an adjacent sibling selector that just won't function as expected. Here is the code snippet causing the issue: .sidebar { position: fixed; ...

Issue with Material-kit-react on smaller screens when employing two GridItems within GridContainer

I am currently experimenting with the library material-kit-react. The issue I am facing is that when I have a <GridContainer> with just one <GridItem>, everything looks fine. But as soon as I add another <GridItem>, the first one moves u ...

Changing the color of the collapsed icon for accordion buttons in Bootstrap 5

I've been attempting to alter the color of Bootstrap 5's accordion's "accordion-button" when it's collapsed. I tested the following code, but it only changes the background and not the icon color of the button. .accordion-but ...