Skip to content

docs: update nextjs documentation #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 172 additions & 8 deletions apps/docs/content/en/docs/01-app/01-getting-started/06-css.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ Next.js provides several ways to use CSS in your application, including:

CSS Modules locally scope CSS by generating unique class names. This allows you to use the same class in different files without worrying about naming collisions.

<AppOnly>

To start using CSS Modules, create a new file with the extension `.module.css` and import it into any component inside the `app` directory:

```css filename="app/blog/styles.module.css"
Expand All @@ -33,26 +35,58 @@ To start using CSS Modules, create a new file with the extension `.module.css` a
```

```tsx filename="app/blog/page.tsx" switcher
import styles from './styles.module.css'
import styles from './blog.module.css'

export default function Page({ children }: { children: React.ReactNode }) {
return <main className={styles.blog}>{children}</main>
export default function Page() {
return <main className={styles.blog}></main>
}
```

```jsx filename="app/blog/page.js" switcher
import styles from './styles.module.css'
import styles from './blog.module.css'

export default function Layout() {
return <main className={styles.blog}></main>
}
```

</AppOnly>

export default function Page({ children }) {
return <main className={styles.blog}>{children}</main>
<PagesOnly>

To start using CSS Modules, create a new file with the extension `.module.css` and import it into any component inside the `pages` directory:

```css filename="/styles/blog.module.css"
.blog {
padding: 24px;
}
```

```tsx filename="pages/blog/index.tsx" switcher
import styles from './blog.module.css'

export default function Page() {
return <main className={styles.blog}></main>
}
```

```jsx filename="pages/blog/index.js" switcher
import styles from './blog.module.css'

export default function Page() {
return <main className={styles.blog}></main>
}
```

</PagesOnly>

## Global CSS

You can use global CSS to apply styles across your application.

To use global styles, create a `app/global.css` file and import it in the root layout to apply the styles to **every route** in your application:
<AppOnly>

Create a `app/global.css` file and import it in the root layout to apply the styles to **every route** in your application:

```css filename="app/global.css"
body {
Expand Down Expand Up @@ -94,8 +128,28 @@ export default function RootLayout({ children }) {

> **Good to know:** Global styles can be imported into any layout, page, or component inside the `app` directory. However, since Next.js uses React's built-in support for stylesheets to integrate with Suspense, this currently does not remove stylesheets as you navigate between routes which can lead to conflicts. We recommend using global styles for _truly_ global CSS, and [CSS Modules](#css-modules) for scoped CSS.

</AppOnly>

<PagesOnly>

Import the stylesheet in the `pages/_app.js` file to apply the styles to **every route** in your application:

```tsx filename="pages/_app.js"
import '@/styles/global.css'

export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
```

Due to the global nature of stylesheets, and to avoid conflicts, you should import them inside [`pages/_app.js`](/docs/pages/building-your-application/routing/custom-app).

</PagesOnly>

## External stylesheets

<AppOnly>

Stylesheets published by external packages can be imported anywhere in the `app` directory, including colocated components:

```tsx filename="app/layout.tsx" switcher
Expand Down Expand Up @@ -126,4 +180,114 @@ export default function RootLayout({ children }) {
}
```

External stylesheets must be directly imported from an npm package or downloaded and colocated with your codebase. You cannot use `<link rel="stylesheet" />`.
> **Good to know:** In React 19, `<link rel="stylesheet" href="..." />` can also be used. See the [React `link` documentation](https://react.dev/reference/react-dom/components/link) for more information.

</AppOnly>

<PagesOnly>

Next.js allows you to import CSS files from a JavaScript file.
This is possible because Next.js extends the concept of [`import`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/import) beyond JavaScript.

### Import styles from `node_modules`

Since Next.js **9.5.4**, importing a CSS file from `node_modules` is permitted anywhere in your application.

For global stylesheets, like `bootstrap` or `nprogress`, you should import the file inside `pages/_app.js`. For example:

```jsx filename="pages/_app.js"
import 'bootstrap/dist/css/bootstrap.css'

export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
```

To import CSS required by a third-party component, you can do so in your component. For example:

```jsx filename="components/example-dialog.js"
import { useState } from 'react'
import { Dialog } from '@reach/dialog'
import VisuallyHidden from '@reach/visually-hidden'
import '@reach/dialog/styles.css'

function ExampleDialog(props) {
const [showDialog, setShowDialog] = useState(false)
const open = () => setShowDialog(true)
const close = () => setShowDialog(false)

return (
<div>
<button onClick={open}>Open Dialog</button>
<Dialog isOpen={showDialog} onDismiss={close}>
<button className="close-button" onClick={close}>
<VisuallyHidden>Close</VisuallyHidden>
<span aria-hidden>×</span>
</button>
<p>Hello there. I am a dialog</p>
</Dialog>
</div>
)
}
```

</PagesOnly>

## Ordering and Merging

Next.js optimizes CSS during production builds by automatically chunking (merging) stylesheets. The **order of your CSS** depends on the **order you import styles in your code**.

For example, `base-button.module.css` will be ordered before `page.module.css` since `<BaseButton>` is imported before `page.module.css`:

```tsx filename="page.ts" switcher
import { BaseButton } from './base-button'
import styles from './page.module.css'

export default function Page() {
return <BaseButton className={styles.primary} />
}
```

```jsx filename="page.js" switcher
import { BaseButton } from './base-button'
import styles from './page.module.css'

export default function Page() {
return <BaseButton className={styles.primary} />
}
```

```tsx filename="base-button.tsx" switcher
import styles from './base-button.module.css'

export function BaseButton() {
return <button className={styles.primary} />
}
```

```jsx filename="base-button.js" switcher
import styles from './base-button.module.css'

export function BaseButton() {
return <button className={styles.primary} />
}
```

### Recommendations

To keep CSS ordering predictable:

- Try to contain CSS imports to a single JavaScript or TypeScript entry file
- Import global styles and Tailwind stylesheets in the root of your application.
- Use CSS Modules instead of global styles for nested components.
- Use a consistent naming convention for your CSS modules. For example, using `<name>.module.css` over `<name>.tsx`.
- Extract shared styles into shared components to avoid duplicate imports.
- Turn off linters or formatters that auto-sort imports like ESLint’s [`sort-imports`](https://eslint.org/docs/latest/rules/sort-imports).
- You can use the [`cssChunking`](/docs/app/api-reference/config/next-config-js/cssChunking) option in `next.config.js` to control how CSS is chunked.

## Development vs Production

- In development (`next dev`), CSS updates apply instantly with [Fast Refresh](/docs/architecture/fast-refresh).
- In production (`next build`), all CSS files are automatically concatenated into **many minified and code-split** `.css` files, ensuring the minimal amount of CSS is loaded for a route.
- CSS still loads with JavaScript disabled in production, but JavaScript is required in development for Fast Refresh.
- CSS ordering can behave differently in development, always ensure to check the build (`next build`) to verify the final CSS order.
Loading