What is causing the compatibility issue between Ant Design V5 styles and NextJS?

Description

In my NextJS project, I am using the Ant Design V5 framework with multiple pages. However, I am facing an issue where the styles are only working correctly on one page and not being applied properly on other pages. Despite referring to the official documentation and examples from Ant's GitHub repository, I couldn't resolve this styling inconsistency.

Questions

These are the questions puzzling me:

  1. What makes that particular page behave differently with the styles?
  2. Why are the styles failing to work as expected on other pages?

Links

  1. Link to my repository (branch: isolated-ant-bug)
  2. Working page - http://localhost:3000/en/m/main
  3. Broken page - http://localhost:3000/en/m/home
  4. Page with broken styles - http://localhost:3000/en
  5. Official Ant Design document - https://ant.design/docs/react/use-with-next
  6. Ant Design examples on GitHub - https://github.com/ant-design/ant-design-examples/tree/main/examples

Isolated Codes:

pages/_app.tsx

import { FC } from 'react'
import { AppProps } from 'next/app'
import { ConfigProvider } from 'antd'
import '../styles/globals.css'
import 'typeface-rubik/index.css'


const MyApp: FC<AppProps> = ({ Component, pageProps }) => (
       <ConfigProvider
          theme={{
            token: {
              fontFamily: '"Rubik", sans-serif',
            }
          }}
      >
        {/* eslint-disable-next-line react/jsx-props-no-spreading */}
        <Component {...pageProps} />
      </ConfigProvider>
)
...

Dependencies

{
  // JSON dependency list
}

Next.js Config

 
// JavaScript configuration for Next.js

Screenshots

Screenshot of /home page: (link)

Answer №1

When faced with this issue, I found a solution by utilizing the _document.tsx script

import Document, { Html, Head, Main, NextScript } from 'next/document'
    import { StyleProvider, createCache, extractStyle } from '@ant-design/cssinjs'
    
    type MyDocumentProps = {
      styles: React.ReactNode
    }
    
    export class MyDocument extends Document<MyDocumentProps> {
      render() {
        return (
          <Html lang="en">
            <Head>{this.props.styles}</Head>
            <body>
              <Main />
              <NextScript />
            </body>
          </Html>
        )
      }
    }
    
    MyDocument.getInitialProps = async (ctx) => {
      const originalRenderPage = ctx.renderPage
      const cache = createCache()
    
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) =>
            function EnhanceApp(props) {
              return (
                <StyleProvider cache={cache}>
                  <App {...props} />
                </StyleProvider>
              )
            },
        })
    
      const initialProps = await Document.getInitialProps(ctx)
    
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            <style dangerouslySetInnerHTML={{ __html: extractStyle(cache) }} />
          </>
        ),
      }
    }
    
    export default MyDocument

Answer №2

I also utilize antd and nextjs in my projects. Instead of using .css files for styles, I prefer to handle them with .ts files. You can check out a simple example that I created here.

While the example may not directly involve nextjs, you can easily incorporate it into your _app file by following these steps:

// Import default antd CSS styles
import 'antd/dist/reset.css'

function _app( {
  Component,
  pageProps
}: AppProps ): ReactNode {

  ....

  return (
    <ConfigProvider
      theme={{
        components: {
          Button: {
            colorPrimary: "#f00"
          }
        }
      }}
    >
      <Component { ...pageProps } />
    </ThemeProvider>
  )
}

Answer №3

After numerous attempts, I finally identified the issue. In development mode, the css classnames perfectly align with the styles, having a prefix of css-dev-only-do-not-override. However, when switching to production mode, the classnames in the style files receive just the css prefix while the elements still retain the css-dev-only-do-not-override. While a standard CLI handles the transition between prefixes automatically, using a custom build and run script requires setting the node environment explicitly. Below are examples for building and running:

const cli = require('next/dist/cli/next-build')
process.env.NODE_ENV = 'production'
cli.nextBuild()
const cli = require('next/dist/cli/next-start')
process.env.NODE_ENV = 'production'
cli.nextStart(
  [
    '--port', process.env.PORT,
    '--hostname', process.env.HOSTNAME,
  ],
)

Answer №4

One straightforward solution is to extract the Ant Design CSS and import it into the root layout as shown below:

import '@/app/styles/antd.min.css';
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) 
{
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

Steps to extract the CSS:

1) Install in your project

npm i @ant-design/static-style-extract

2) Create a script file

// scripts/genAntdCss.mjs
import fs from 'fs';
import { extractStyle } from '@ant-design/static-style-extract';

const outputPath = './app/styles/antd.min.css';

const css = extractStyle();
fs.writeFileSync(outputPath, css);

3) Add run command to package.json

  "scripts": {
    ...
    "antcss": "node ./scripts/genAntdCss.mjs"
  }

4) Create a directory path in your project

my-app/app/styles

5) Run the script

npm run antcss

Voila! Your Ant Design styles should now function correctly

Credits: https://github.com/ant-design/ant-design/issues/38555#issuecomment-1471908738

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

React component fails to re-render after state change

For the past two days, I've been struggling with this error and can't seem to fix it! I'm currently working on creating a weather app in React which utilizes the API. The app features a Bootstrap Navbar with a search option that allows user ...

Completion status of circle loader: 100%

I am currently facing some challenges getting the circle loader to work correctly. Although I can handle basic animations, the code I found on CodePen is a bit more advanced than what I am used to. I am using it as a learning experience to understand how i ...

Utilizing React JS and lodash's get method within a single function

Is it possible to display two string objects in the same line using Lodash get? Can I achieve this by chaining (_.chain(vehicle).get('test').get('test2))? Below is a snippet of the JSON file: { "results": [ { " ...

Adjusting height in Google Maps to fill the remaining space

Currently, I am developing a map application where I want the Google Maps DIV to occupy the remaining height under the header. Here is the code snippet: <!DOCTYPE html> <head> <title>Map Application</title> <style type ...

Unlocking the Mysterious Realm of HTML

I recently stumbled upon a mysterious combination of HTML attributes: <div vanisheffect="true" blinkcolor="red" fadeopacity="0.8"> Have you ever encountered something like this? And more importantly, does it have any impact on specific browsers? Is ...

Multer ensures that all fields are validated before proceeding with the upload process

I have been trying to implement field validation before uploading in NodeJS using Multer, but it doesn't seem to be working. I spent days on this issue and still couldn't get it to work. Is it possible that Multer doesn't support this featur ...

I'm curious, which ref tag should I utilize for draft.js?

I'm currently working on a form using Draft.js with Next.js and TS, but I've encountered some errors in my code. Here is what I have so far: import {Editor, EditorState} from 'draft-js'; const [editorState, setEditorState] = useState( ...

What is the best approach to developing a reusable function for managing the active className in React code?

I am struggling to come up with a universal method for applying an active class, can someone please help me figure it out? Any assistance would be greatly appreciated! Approach const engLangActive: string = router.locale === "en" ? ...

Having trouble changing the chosen selection in the material UI dropdown menu

I've encountered an issue with my material ui code for a select dropdown. It seems that the selected option is not updating properly within the dropdown. <FormControl variant="outlined" className={classes.formControl}> <InputLabel ref={ ...

Is there a way to transmit React code using Express?

Currently, I'm in the process of creating a coloring demonstration. Initially, I had an SVG file at hand, but I made the decision to utilize svgr for its conversion into a React component. This strategy will offer me the flexibility to easily modify i ...

When applying multiple classes with NgClass, use the property name instead of the class content

I am facing a challenge trying to add multiple classes (in this case 2) to a custom component that includes a list item component from MDBootstrap: App.module.ts <custom-list-component size="w-50"> <custom-list-item-component href="#">lis ...

Utilizing ReactStrap: a guide to retrieving the id of the chosen dropDownItem

In my code, I have a dropdownList component with various DropdownItems: <Dropdown isOpen={this.state.dropdownOpen[3]} toggle={() => { this.toggle(3); }} > <DropdownToggle className="my-dropdown" car ...

Securing your folders with Next Auth middleware

I am currently developing a NextJS application and have implemented routers at pages/dashboard/* that I need to secure. My goal is to restrict access to these routes only to authenticated users. I am utilizing Prisma for data management, with Google as the ...

Span tag not respecting CSS width property

One of my spans is causing an issue. Here are the styles in question: .form_container .col1che { float: left; width: 4%; text-align: left; } .form_container .col2che { float: left; width: 80%; text-align:left; } .form_container .col3che { float: ...

Using ReactJS with Material UI and applying styles with withStyles including themes in TypeScript

I've been working on converting the Material UI Dashboard into TypeScript. You can find the original code here: Material UI Dashboard One issue I'm encountering is that I am unable to define CSS styles within the withStyles function while export ...

Tips for maintaining the default arrow icon for HTML select elements

While styling a drop down in Firefox on Mac OS X, I noticed that the arrow changes from the standard look to an unattractive downward arrow. How can I maintain the standard form element with the appealing up and down arrows, instead of the unsightly downwa ...

How come my container-fluid div isn't encompassing the box divs too?

I am currently in the process of creating a dice using the bootstrap grid system. Although I have not completed it yet, here is a small snippet of the code that showcases my progress. However, when I inspect my webpage using developer tools (see attached i ...

Getting started with editing and selecting a row using an onClick event in DataGrid

Currently working with MUI's DataGrid, I am looking to enable edit mode on a specific row and set focus to it. I am using the community edition of DataGrid, would this feature only be available in data-grid-x version? ...

Why isn't the content of the initial tab in a <section> shown when clicking a link in the side-drawer?

View the JSFiddle here. Within this MCVC, a side drawer is implemented (opened by clicking the top left button) that contains three labeled links: Link One, Link Two, and Link Three. Each link has an href attribute value that starts with "#" concatenated ...

Encounter an incorrect route in react-router

My current setup involves a router similar to the following: const Routes = (props) => { const { store } = props; const { loggedIn } = props; const checkAuth = (nextState, replace) => { auth.checkAuth(nextState, replace, loggedIn); }; ...