Search code examples
typescriptnext.jstailwind-css

How do I get tailwind CSS to load before rendering components in NextJS?


I have a webapp I'm currently building that uses tailwind CSS for styling. The styles load properly but it seems that they don't load instantly. What this means is that the users will see the unstyled website for a split second before the tailwind CSS classes kicks in and styles everything.

Not really sure why this happens, the configurations for the project are just the default ones that are set when using create-next-app (except for the tsx settings, had to change moduleResolution to "node" instead of "bundler").

I've tried changing moduleResolution in the tsconfig back to "bundler" but it didn't work.

tailwind.config.js

import type { Config } from 'tailwindcss'

const config: Config = {
  content: [
    './pages/**/*.{js,ts,jsx,tsx,mdx}',
    './components/**/*.{js,ts,jsx,tsx,mdx}',
    './app/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  theme: {
    extend: {
      backgroundImage: {
        'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
        'gradient-conic':
          'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
      },
    },
  },
  plugins: [],
}
export default config

tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "plugins": [
      {
        "name": "next"
      }
    ],
    "paths": {
      "@/*": ["./*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  "exclude": ["node_modules"]
}

layout.tsx

import { Inter } from 'next/font/google'
import Navbar from './components/Navbar' 
import type { Metadata } from "next"
import './globals.css'

const inter = Inter({ subsets: ['latin'] })

export const metadata: Metadata = {
  title: 'test project',
  description: 'Generated by create next app',
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <Navbar />
        {children}
      </body>
    </html>
  )
}

Navbar.tsx

import { Fragment } from "react"
import { AppBar, Button } from "@mui/material/index";

export function Navbar() {

  const headers = ['Find me my coffee!', 'About', 'Donate']

  return (
    <Fragment>
      <AppBar
        className="bg-amber-950 p-4 flex justify-between flex-col md:flex-row sticky top-0 drop-shadow-xl"
      >
        <Button
          className="rounded-xl bg-black text-white lowercase"
        >
          test button
        </Button>
          hello
      </AppBar>
    </Fragment>
  )

}

export default Navbar;

globals.css

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

The only thing I found about this is this thread Issue with tailwind styles not applying immediately in a nextJs 13 project However, I tried the proposed solution in the only answer and it doesn't work.

Any help greatly appreciated, thank you!


Solution

  • Putting this up in case anyone else is having problem with this.

    If you are experiencing the same problem I had and are using MUI, that is the source of the problem.

    The problem is not tailwind itself. I figured out that the problem was that I was using MUI together with tailwind. Since MUI has its own styling engine, it was creating styling conflicts with the tailwind classes I was using.

    MUI has documentation on how to fix this, but I was unsuccessful in fixing the problem. I am unsure why, but will edit this answer if I figure out why.

    My recommendation is to first follow MUI's documentation for styling interoperability.

    If that does not work, I would recommend to just remove MUI components and use html + tailwind instead.