cf.completefrontend
Open lab My progress
THE NEXT.JS FIELD GUIDE

Tailwind CSS in Next.js

Set up Tailwind CSS 4 in Next.js as create-next-app does, add design tokens with @theme, dark mode and a font variable, and keep class lists readable.

By the end, you can
  • 01
    Set up Tailwind CSSRead the three files create-next-app writes for it, or set it up with its PostCSS plugin, and import it once in the root layout.
  • 02
    Make it the shop's ownAdd colors and sizes with @theme, turn on dark mode from the computer's setting or a class, and use a next/font variable.
  • 03
    Write classes Tailwind CSS can findTell why a class built from pieces gets no CSS, and keep long class lists short and clear.

The tea shop, styled with utility classes

CSS in Next.js styled the tea shop with a global stylesheet and CSS Modules. Here the shop gets Tailwind CSS instead, a CSS library made of utility classes: small classes that each do one thing, like px-6 (padding on the left and right) or bg-emerald-800 (a dark green background). You put them in className, and Tailwind CSS writes the CSS for them. A new Next.js app has it unless you say no: Creating a Next.js app shows the question. (Styling components compares it with the other ways to style React components.)

Here is the shop with Tailwind CSS, set up the way create-next-app 16.4.3 does it. It was built with real Next.js and Tailwind CSS 4.3.3, the latest on October 30, 2026, and each page was pictured in real Chrome, in a window 800 px wide. The Browser tab shows the pictures.

The tea shop, styled with Tailwind CSSNext.js
app/teas/
app/teas/page.tsx
const teas = [  { name: "Green tea", price: 4 },  { name: "Mint tea", price: 3 },]; export default function TeasPage() {  return (    <main className="px-6 py-4">      <h1 className="text-3xl font-bold">Our teas</h1>      <ul className="mt-4 grid grid-cols-1 gap-4 md:grid-cols-2">        {teas.map((tea) => (          <li key={tea.name} className="rounded-xl border-2 border-emerald-800 bg-white px-4 py-3">            <h2 className="text-xl font-semibold">{tea.name}</h2>            <p className="font-bold text-emerald-800">${tea.price} a box</p>          </li>        ))}      </ul>    </main>  );}
Recorded from Next.js 16.4.3
localhost:3000/teasTea shop
The page at /teas, as Chrome drew it with its styles. It says: Home Teas. Our teas. Green tea. $4 a box. Mint tea. $3 a box. Open every day, 9 to 5.

A picture of the page in real Chrome, in a window 800 px wide, taken once the page had loaded with its styles. Open it full size

Read the class lists in app/teas/page.tsx as a list of instructions. Line 10 makes the list a grid with grid, one column with grid-cols-1, and a gap of 1rem with gap-4. Then md:grid-cols-2 gives it two columns, but only on screens at least 48rem (768 px) wide: md: is a variant, a prefix that says when a utility applies. Line 12 gives each card round corners, a green border, a white background and padding, and line 14 makes the price bold and green. The picture is 800 px wide, so the cards sit side by side. Pick / above the picture: its link looks like a button, and hover:bg-emerald-800 on line 8 of app/page.tsx darkens it when the mouse is over it.

Now open the Network tab. Both pages link one stylesheet, 0pvj_uzeycuk5.css, of about 7 KB. It starts with a reset Tailwind CSS calls Preflight, which takes away the browser's own margins and heading sizes. Then the theme variables the classes need, like --color-emerald-800, and then one rule for each class in the files: .px-6 sets padding-inline:calc(var(--spacing) * 6). Variants become conditions: md:grid-cols-2 sits inside @media (min-width:48rem), and hover:bg-emerald-800 inside @media (hover:hover). Each color is there twice: as a hex color like #005f46, and again as lab(), another way CSS can write a color, inside @supports, a check that applies its rules only in browsers that support that feature.

An editor window for the app folder lists layout.tsx, page.tsx and teas/page.tsx. An arrow goes to a shaded card, Tailwind CSS, which reads them as text. Another arrow goes to a window of built CSS with three rules: .px-6, .bg-emerald-800 and .md:grid-cols-2, the classes it found.applayout.tsxpage.tsxteas/page.tsxTailwind CSSreads them as textCSS.px-6.bg-emerald-800.md:grid-cols-2only the classes it found
While Next.js builds the CSS, Tailwind CSS reads the project's files as text, finds class names like px-6 and md:grid-cols-2, and writes a rule for each one it knows. A utility that no file uses gets no rule.
Real-life analogyA sign maker who cuts only the letters you order

A sign maker reads your order form and cuts the letters for exactly the words written on it. He doesn't cut every letter he could, and he can't cut a word the form only describes, like "whatever the customer says later". He needs to read it.

In real life: The order form, with every word spelled out
In Next.js: Your files, with every class name written whole
In real life: The sign maker reads the form and cuts those letters
In Next.js: Tailwind CSS reads the files and writes those rules
In real life: A letter nobody ordered is never cut
In Next.js: A utility no file uses gets no rule
In real life: An order that says "the word the customer tells you later"
In Next.js: A class built from pieces when the code runs
The main idea

Tailwind CSS turns the class names written in your files into one stylesheet, which the root layout imports. create-next-app runs it as a Turbopack loader. Your colors, sizes and fonts go in @theme, where they make classes of their own, and dark: classes apply in dark mode. Write every class name whole, so Tailwind CSS can find it.

Setting up Tailwind CSS as create-next-app does

Click through the example's files: four of them set up Tailwind CSS. They're exactly what create-next-app writes with its default answers, without the linter.

  1. package.json, lines 16 and 20: two packages, @tailwindcss/turbopack and tailwindcss, both ^4, any version 4.
  2. next.config.ts, lines 7 to 14: a turbopack rule. Turbopack is the bundler next build uses. The rule says: for every file whose name matches *.css, run the loader @tailwindcss/turbopack, and treat what it gives back as CSS. A loader is a function the bundler runs on a file's text before it bundles it.
  3. app/globals.css, line 1: @import "tailwindcss";. The loader replaces it with Preflight, the theme and the utilities.
  4. app/layout.tsx, line 2: the root layout imports globals.css, as in the last lesson, so every page gets the stylesheet.

There's no tailwind.config.js. Tailwind CSS 4 keeps its settings in the CSS itself, in @theme, and finds your files on its own, with automatic source detection: starting from the folder the build runs in (the project's folder, here), it reads every file except node_modules, the files .gitignore lists, CSS files, images and lockfiles. In a repository that holds several projects, that starting folder matters: @import "tailwindcss" source("../src") changes it. @source "../ui" adds a folder it would skip, like a component library's, and @source inline("bg-teal-700") makes a utility that no file contains.

Next.js's CSS docs set it up another way, with Tailwind CSS's PostCSS plugin. PostCSS is a tool that runs plugins over CSS, and Next.js runs it on every CSS file when the project has a postcss.config.mjs. Each row compares the two setups:

Two ways to set up Tailwind CSS
Whatcreate-next-app with TurbopackThe docs' PostCSS setup
package.jsontailwindcss and @tailwindcss/turbopack, in devDependencies.tailwindcss and @tailwindcss/postcss, in devDependencies.
How Tailwind CSS runsA rule in next.config.ts sends every .css file through the @tailwindcss/turbopack loader.postcss.config.mjs adds the @tailwindcss/postcss plugin, which Next.js runs on every CSS file.
app/globals.css@import "tailwindcss";@import "tailwindcss";
Who writes it this waycreate-next-app, with Turbopack, the default bundler.The docs' CSS page, and create-next-app --rspack, which uses the Rspack bundler.

Try both. Before you switch, guess: does the page, or its CSS, change?

Playground: two ways to run Tailwind CSS
The tea shop, with this Tailwind CSS setupNext.js
app/teas/
next.config.ts
import type { NextConfig } from "next"; const nextConfig: NextConfig = {  /* config options here */  cacheComponents: true,  partialPrefetching: true,  turbopack: {    rules: {      "*.css": {        loaders: ["@tailwindcss/turbopack"],        as: "*.css",      },    },  },}; export default nextConfig;
Recorded from Next.js 16.4.3
localhost:3000/teasTea shop
The page at /teas, as Chrome drew it with its styles. It says: Home Teas. Our teas. Green tea. $4 a box. Mint tea. $3 a box. Open every day, 9 to 5.

A picture of the page in real Chrome, in a window 800 px wide, taken once the page had loaded with its styles. Open it full size

Try it yourself
Turbopack loader

What create-next-app writes: lines 7 to 14 of next.config.ts send every .css file through @tailwindcss/turbopack, and package.json lists it. The tea page gets two cards side by side.

Both versions were built with next build from Next.js 16.4.3 and Tailwind CSS 4.3.3, and pictured in real Chrome. Open the Network tab in each to compare the stylesheet's address and its CSS. Reset goes back to the first version.

Nothing changes. The PostCSS version builds the very same stylesheet, 0pvj_uzeycuk5.css, with the same CSS in it, and the pictures are the same. Keep the setup create-next-app wrote; switching changes nothing in the CSS.

Design tokens with @theme

The colors, sizes and fonts a design is made of are its design tokens. Tailwind CSS keeps them as theme variables: CSS variables written inside @theme, where each one also makes utility classes. The tea shop has its own green and cream, and a corner size for its cards:

The tea shop's own design tokensNext.js
app/teas/
app/globals.css
@import "tailwindcss"; @theme {  --color-leaf: #2f6b4f;  --color-cream: #f6f3ea;  --radius-card: 12px;}
Recorded from Next.js 16.4.3
localhost:3000/teasTea shop
The page at /teas, as Chrome drew it with its styles. It says: Home Teas. Our teas. Green tea. $4 a box. Mint tea. $3 a box. Open every day, 9 to 5.

A picture of the page in real Chrome, in a window 800 px wide, taken once the page had loaded with its styles. Open it full size

Lines 4 to 6 of app/globals.css add three theme variables. A theme variable's name starts with its namespace, which says which utilities it makes: --color-leaf is in --color-*, so text-leaf, bg-leaf and border-leaf exist now, and --radius-card makes rounded-card. Open app/teas/page.tsx: line 8 uses bg-cream, line 9 text-leaf, and line 12 rounded-card and border-leaf. The Browser tab shows the cream page and the green headings.

In the Network tab, the CSS has the three variables, --color-leaf:#2f6b4f, --color-cream:#f6f3ea and --radius-card:12px, and utilities that use them, like .text-leaf{color:var(--color-leaf)}. It only has what the files use: no .bg-leaf, and none of Tailwind's colors the shop doesn't use, like --color-red-500. (@theme static writes every variable, used or not.) Each row is one namespace:

What a theme variable makes
Theme variableNamespaceWhat it makes
--color-leaf--color-*bg-leaf, text-leaf, border-leaf and every other color utility.
--radius-card--radius-*rounded-card, and the corner utilities like rounded-t-card.
--font-display--font-*font-display, a font-family utility.
--breakpoint-tablet--breakpoint-*tablet:, a variant for screens at least that wide.
On the left, the theme variable --color-leaf: #2f6b4f, with arrows to three utilities: text-leaf and border-leaf, which the tea page uses, and bg-leaf, dashed and crossed out because no file uses it. Below, --radius-card: 12px, with an arrow to rounded-card, which the tea page uses.--color-leaf: #2f6b4ftext-leafborder-leafbg-leafusedusednot used--radius-card: 12pxrounded-cardused
In @theme, --color-leaf makes every color utility for leaf, and --radius-card makes rounded-card. The built CSS only has the ones the tea page uses: text-leaf, border-leaf and rounded-card, but no bg-leaf.

A plain CSS variable in :root still works, but makes no utility. Tailwind's docs suggest @theme for a token that should have classes, and :root for a variable that shouldn't.

Dark mode, two ways

The dark: variant applies a utility only in dark mode: dark:bg-stone-900 is a dark background, in dark mode. By default, dark mode means the computer's setting. This home page has a light and a dark version, and real Chrome took two steps: open the page, then switch the computer to dark mode.

A home page with dark: classesNext.js
app/teas/
app/page.tsx
export default function HomePage() {  return (    <main className="min-h-screen bg-white px-6 py-4 text-stone-900 dark:bg-stone-900 dark:text-stone-100">      <h1 className="text-3xl font-bold">Tea shop</h1>      <p className="mt-2 text-lg text-stone-600 dark:text-stone-300">Fresh tea, sent to your door.</p>    </main>  );}
Recorded from Next.js 16.4.3

Each step was taken in real Chrome against next start. Pick one to see the page after it.

localhost:3000/Tea shop
The page at / after step 2, as Chrome drew it with its styles. It says: Tea shop. Fresh tea, sent to your door.

A picture of the window in real Chrome after this step. Open it full size

Focus
nothing: the page itself
Scrolled
0 px down
Stylesheets on the page
0hge9d7pfco-n.css

No requests during this step: the page already had what it needed

Line 3 gives the page a white background and dark text, and in dark mode a stone background and light text. Line 5 does the same for the paragraph. The Steps tab opens on step 2: the page turned dark, with no click and no request. Open the Network tab to see why: the CSS has the dark rules inside @media (prefers-color-scheme:dark), a condition the browser checks against the computer's setting, and checks again when the setting changes.

Some sites let the visitor choose, with a button. Then dark: should follow a class instead. One line in globals.css says so, and a small Client Component (a component whose code also runs in the browser, so it can handle a click; its file starts with "use client", as Client Components shows) puts the class on <html>. Switch between the two versions:

Playground: who turns on dark mode?
The tea shop's home page, with this way of doing dark modeNext.js
app/teas/
app/page.tsx
export default function HomePage() {  return (    <main className="min-h-screen bg-white px-6 py-4 text-stone-900 dark:bg-stone-900 dark:text-stone-100">      <h1 className="text-3xl font-bold">Tea shop</h1>      <p className="mt-2 text-lg text-stone-600 dark:text-stone-300">Fresh tea, sent to your door.</p>    </main>  );}
Recorded from Next.js 16.4.3

Each step was taken in real Chrome against next start. Pick one to see the page after it.

localhost:3000/Tea shop
The page at / after step 2, as Chrome drew it with its styles. It says: Tea shop. Fresh tea, sent to your door.

A picture of the window in real Chrome after this step. Open it full size

Focus
nothing: the page itself
Scrolled
0 px down
Stylesheets on the page
0hge9d7pfco-n.css

No requests during this step: the page already had what it needed

Try it yourself
Follows the computer

Lines 3 and 5 have dark: classes. In step 2, Chrome switches the computer to dark mode, and the page turns dark at once, with no click and no request.

Each version was built with next build from Next.js 16.4.3, and its steps taken in real Chrome. Pick a step to see the page after it. Reset goes back to the first version.

In the second version, line 3 of globals.css, @custom-variant dark (&:where(.dark, .dark *));, makes dark: mean "inside an element with the class dark". Step 2 changes nothing: the computer is dark, but nobody set the class. In step 3, line 7 of app/theme-button.tsx toggles dark on <html>, and the page turns dark. The class is on the current document's <html>, so it stays there through client-side navigations: in step 4, the link to /teas swaps in the tea page, and the page is still dark (the tea page has dark: classes too). Step 5 loads / again as a new document, and it's light: a full page load makes a new <html> from the server's HTML, without the class. Keeping the choice across full loads takes more code, which saves it and sets the class again each time a page loads.

Two halves. Left, by default: dark:bg-stone-900 becomes a rule inside the media query prefers-color-scheme: dark, which follows the computer's dark mode. Right, after @custom-variant dark: the same class becomes a rule for :where(.dark, .dark *), which follows a dark class on an element around it, like html.By defaultdark:bg-stone-900prefers-color-scheme: darkthe computer's dark modeWith @custom-variantdark:bg-stone-900:where(.dark, .dark *)a dark class around it
By default, dark: writes its rule inside @media (prefers-color-scheme: dark), so it follows the computer. After @custom-variant dark (&:where(.dark, .dark *));, the same class follows a dark class on <html> or any element around it.

A font as a CSS variable

create-next-app's starter page uses the Geist font, through a CSS variable that Tailwind CSS's font-sans class reads. Here is the same idea in the tea shop:

Geist from next/font, as Tailwind CSS's sans-serif fontNext.js
app/teas/
app/layout.tsx
import { Geist } from "next/font/google";import "./globals.css"; const geist = Geist({  variable: "--font-geist-sans",  subsets: ["latin"],}); export const metadata = { title: "Tea shop" }; export default function RootLayout({ children }: LayoutProps<"/">) {  return (    <html lang="en" className={geist.variable}>      <body className="bg-stone-100 font-sans text-stone-800">{children}</body>    </html>  );}
Recorded from Next.js 16.4.3
localhost:3000/Tea shop
The page at /, as Chrome drew it with its styles. It says: Tea shop. Fresh tea, sent to your door. See our teas.

A picture of the page in real Chrome, in a window 800 px wide, taken once the page had loaded with its styles. Open it full size

Line 1 of app/layout.tsx imports Geist from next/font/google, Next.js's way to load a font: it downloads the font when you build, and serves it from your own site. Lines 4 to 7 ask for it with variable: "--font-geist-sans", so geist.variable is a class that defines that CSS variable. Line 13 puts the class on <html>, and line 14 gives the body font-sans. In app/globals.css, lines 3 to 5 point Tailwind CSS's --font-sans at the variable.

Open the Network tab. In this recorded build, the HTML says <html lang="en" class="PZ6jEG_variable"> (a generated name, like a CSS Module's, whose form can change), and the CSS has .PZ6jEG_variable{--font-geist-sans:"Geist", "Geist Fallback"}, the @font-face rules next/font made, and .font-sans{font-family:var(--font-geist-sans)}. That last rule is what inline on line 3 does: the utility uses the value, var(--font-geist-sans), itself. Tailwind's docs use inline for a theme variable that points at another variable, so it works wherever the class is. The picture shows the shop in Geist. Optimizing fonts, later in this stage, teaches next/font, and what "Geist Fallback" is for.

Keeping class lists readable

Class lists grow long: the tea card on line 12 of the first example has six classes. They stay readable, and correct, with a few habits. The first one matters most, because without it a class gets no CSS at all: write every class name whole. Here the tea page picks each tea's color from its data:

Playground: does Tailwind CSS find these classes?
The tea page, with this way of choosing each tea's colorNext.js
app/teas/
app/teas/page.tsx
const teas = [  { name: "Green tea", color: "green" },  { name: "Mint tea", color: "teal" },]; export default function TeasPage() {  return (    <main className="px-6 py-4">      <h1 className="text-3xl font-bold">Our teas</h1>      <ul className="mt-4 flex gap-4">        {teas.map((tea) => (          <li key={tea.name} className={`rounded-xl px-4 py-3 text-white bg-${tea.color}-700`}>            {tea.name}          </li>        ))}      </ul>    </main>  );}
Recorded from Next.js 16.4.3
localhost:3000/teasTea shop
The page at /teas, as Chrome drew it with its styles. It says: Home Teas. Our teas. Green tea. Mint tea. Open every day, 9 to 5.

A picture of the page in real Chrome, in a window 800 px wide, taken once the page had loaded with its styles. Open it full size

Try it yourself
Built from pieces

Line 12 builds bg-green-700 and bg-teal-700 when the code runs. No file holds either name whole, so the built CSS has no rule for them, and the white names sit on no background.

Both versions were built with next build from Next.js 16.4.3, and pictured in real Chrome. Open the Network tab and look for .bg-green-700 in the CSS. Reset goes back to the first version.

In the first version, line 12 builds the class from pieces: bg-, then tea.color, then -700. Tailwind CSS reads the file as text when Next.js builds the CSS, long before the code runs, so it never sees bg-green-700, and the built CSS has no rule for it. In the second version, lines 2 and 3 hold the whole names, and the cards are green and teal.

Two halves. Left: the file holds bg-dollar-brace-tea.color-brace-700, built from pieces, and the CSS has no .bg-green-700: that card is dashed and crossed out. Right: the file holds the whole name bg-green-700 in quotes, and the CSS has a .bg-green-700 rule.Built from pieces`bg-${tea.color}-700`.bg-green-700no rule in the CSSWritten whole"bg-green-700".bg-green-700a rule in the CSS
Tailwind CSS reads files as text, and doesn't run your code. A name built from pieces when the code runs is never in a file whole, so the built CSS has no rule for it. Written whole, in quotes, it does.

The other habits:

  • Make a component for markup you repeat. If the shop shows tea cards on two pages, move the <li> and its six classes into a TeaCard component. The classes are then written once, in the file they belong to, the way the last lesson's CSS Module was.
  • Choose between whole names. For a class that depends on data or state, keep the whole names in an object, like { green: "bg-green-700" }, or write both sides of a condition in full: isOn ? "bg-emerald-700" : "bg-stone-200".
  • Keep the same order everywhere. Tailwind CSS's official Prettier plugin, prettier-plugin-tailwindcss, sorts each class list for you, so every list reads the same way.
  • Put a value with a name in @theme. bg-cream says more than bg-[#f6f3ea], a class with a value used only here, in square brackets.

Will Tailwind CSS make this class?

Every class in the shop has to be found to be styled. Sort these snippets: does the built CSS get a rule for the class they use?

Does the built CSS get a rule?
  • className="bg-teal-700"
  • className={"bg-" + tea.color + "-700"}
  • const colors = { mint: "bg-teal-700" };
  • className={"text-" + size}
  • isOn ? "bg-emerald-700" : "bg-stone-200"
  • className="md:grid-cols-2"
  • className={"bg-teal-" + shade}
Try it yourself
0 of 7 correct

Sort each snippet: Tailwind CSS makes the class, or there's no CSS for it.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Common mix-ups

  • "Tailwind CSS needs a tailwind.config.js." No. Tailwind CSS 4 keeps its settings in your CSS, in @theme, and finds your files on its own.
  • "Every utility is in the CSS, so any class works." No. The CSS only has rules for classes written whole in your files: about 7 KB in the recorded build of the shop.
  • "A class built from a variable works if the result is a real class." No. Tailwind CSS reads files as text and doesn't run them, so it never sees the result.
  • "Tailwind CSS runs in the browser." No. It runs when Next.js builds the CSS. The browser only gets the stylesheet.
  • "dark: follows a dark class." Only after @custom-variant dark. By default, it follows the computer's setting.
  • "@theme and :root do the same thing." Both make CSS variables, but only @theme makes utility classes from them.
  • "Next.js runs Tailwind CSS through PostCSS." It can, as the docs show, but create-next-app runs it as a Turbopack loader. Both build the same CSS.

Practice exercises

These exercises are about Next.js projects, which can't run inside this page. Answer first, then use the hints.

Exercise 1 · Warm-upRead a utility's rule

These two rules are from the shop's built CSS. How much padding does px-6 put on the left and on the right, in rem?

Starter codeCSS
/* From the shop's built CSS */
:root, :host {
  --spacing: .25rem;
}

.px-6 {
  padding-inline: calc(var(--spacing) * 6);
}

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · Warm-upName a utility from the theme

    The shop adds a mint color to its theme. Which class gives an element a mint background?

    Starter codeCSS
    @import "tailwindcss";
    
    @theme {
      --color-mint: #5fb49c;
    }

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeRead where dark: goes

      The tea card gets a dark version. In a project with create-next-app's globals.css, inside which CSS rule does Tailwind CSS write dark:bg-stone-800?

      Starter codeTSX
      <li className="rounded-card bg-white px-4 py-3 dark:bg-stone-800">
        Green tea
      </li>

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticePredict a reload

        In the "A button decides" version, the visitor clicks Dark mode, and the page turns dark. Then they load / again. Is the page dark?

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeFind the missing colors

          On this tea page, the names show in white, on no background. Which rules are missing from the built CSS? Then fix the page.

          Starter codeTSX
          const teas = [
            { name: "Green tea", color: "green" },
            { name: "Mint tea", color: "teal" },
          ];
          
          export default function TeasPage() {
            return (
              <main className="px-6 py-4">
                <h1 className="text-3xl font-bold">Our teas</h1>
                <ul className="mt-4 flex gap-4">
                  {teas.map((tea) => (
                    <li key={tea.name} className={`rounded-xl px-4 py-3 text-white bg-${tea.color}-700`}>
                      {tea.name}
                    </li>
                  ))}
                </ul>
              </main>
            );
          }
          

          Answer, then press Check. Spacing and letter case don’t matter.

            Exercise 6 · ChallengeSet up Tailwind CSS the docs' way

            You're following Next.js's CSS docs in a project without Tailwind CSS. You ran this command. Which file do you add next, so that Next.js runs the plugin?

            Starter codeShell
            npm install -D tailwindcss @tailwindcss/postcss

            Answer, then press Check. Spacing and letter case don’t matter.

              Check your understanding

              For each question, ask what Tailwind CSS can read in your files, and when each rule applies.

              The Tailwind CSS in Next.js quiz · 7 questionsScore: first tries count
              1. Question 1 of 7With its default answers, what does create-next-app 16.4.3 add to a new project for Tailwind CSS?

                Choose an answer to see the explanation.

              2. Question 2 of 7With automatic source detection, in the tea shop's project, which utility classes end up in the stylesheet Next.js builds?

                Choose an answer to see the explanation.

              3. Question 3 of 7This globals.css adds --color-leaf. Which class can a page use now?

                Read the code, then predictCSS
                @import "tailwindcss";
                
                @theme {
                  --color-leaf: #2f6b4f;
                  --color-cream: #f6f3ea;
                  --radius-card: 12px;
                }
                

                Choose an answer to see the explanation.

              4. Question 4 of 7In a new Tailwind CSS project, when does dark:bg-stone-900 apply?

                Choose an answer to see the explanation.

              5. Question 5 of 7With this globals.css, the visitor switches the computer to dark mode. What does the page do?

                Read the code, then predictCSS
                @import "tailwindcss";
                
                @custom-variant dark (&:where(.dark, .dark *));
                

                Choose an answer to see the explanation.

              6. Question 6 of 7Why do these tea cards get no background color?

                Read the code, then predictTSX
                const teas = [
                  { name: "Green tea", color: "green" },
                  { name: "Mint tea", color: "teal" },
                ];
                
                export default function TeasPage() {
                  return (
                    <main className="px-6 py-4">
                      <h1 className="text-3xl font-bold">Our teas</h1>
                      <ul className="mt-4 flex gap-4">
                        {teas.map((tea) => (
                          <li key={tea.name} className={`rounded-xl px-4 py-3 text-white bg-${tea.color}-700`}>
                            {tea.name}
                          </li>
                        ))}
                      </ul>
                    </main>
                  );
                }
                

                Choose an answer to see the explanation.

              7. Question 7 of 7Why does this globals.css use @theme inline?

                Read the code, then predictCSS
                @import "tailwindcss";
                
                @theme inline {
                  --font-sans: var(--font-geist-sans);
                }
                

                Choose an answer to see the explanation.

              Key takeaways

              • Tailwind CSS writes one rule for each utility class written whole in your files, into the stylesheet built from globals.css, which the root layout imports.
              • create-next-app runs it as a Turbopack loader: @tailwindcss/turbopack and a turbopack rule in next.config.ts. The docs' PostCSS plugin builds the same CSS.
              • Theme variables in @theme make utilities by namespace: --color-leaf makes bg-leaf and text-leaf. Only the ones you use end up in the CSS.
              • dark: follows the computer's setting, or, after @custom-variant dark, a dark class.
              • A next/font variable becomes Tailwind CSS's font with @theme inline { --font-sans: var(--font-geist-sans); }.
              • Never build a class name from pieces; choose between whole names, and repeat markup through a component.

              Remember the one-liner.
              Tailwind CSS styles what it can read: write each class whole, keep your tokens in @theme, and import it once in the root layout.

              Coming next: CSS-in-JS and Server Components. It shows why libraries that write CSS while the page runs need a Client Component, and which ones don't.

              CompleteFrontend Clear concepts. Working examples.