Skip to content

Commit f3ad435

Browse files
docs: Merge CSS pages (vercel#78996)
Closes: https://linear.app/vercel/issue/DOC-4648/css Redirects: vercel/front#45417 - Improves the CSS content for clarity and brevity. - Adds Pages Router examples. --------- Co-authored-by: Lee Robinson <lee@leerob.com>
1 parent 556e0c6 commit f3ad435

File tree

21 files changed

+195
-431
lines changed

21 files changed

+195
-431
lines changed

docs/01-app/01-getting-started/06-css.mdx

Lines changed: 171 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ Next.js provides several ways to use CSS in your application, including:
2424

2525
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.
2626

27+
<AppOnly>
28+
2729
To start using CSS Modules, create a new file with the extension `.module.css` and import it into any component inside the `app` directory:
2830

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

3537
```tsx filename="app/blog/page.tsx" switcher
36-
import styles from './styles.module.css'
38+
import styles from './blog.module.css'
3739

38-
export default function Page({ children }: { children: React.ReactNode }) {
39-
return <main className={styles.blog}>{children}</main>
40+
export default function Page() {
41+
return <main className={styles.blog}></main>
4042
}
4143
```
4244

4345
```jsx filename="app/blog/page.js" switcher
44-
import styles from './styles.module.css'
46+
import styles from './blog.module.css'
47+
48+
export default function Layout() {
49+
return <main className={styles.blog}></main>
50+
}
51+
```
52+
53+
</AppOnly>
54+
55+
<PagesOnly>
56+
57+
To start using CSS Modules, create a new file with the extension `.module.css` and import it into any component inside the `pages` directory:
58+
59+
```css filename="/styles/blog.module.css"
60+
.blog {
61+
padding: 24px;
62+
}
63+
```
4564

46-
export default function Page({ children }) {
47-
return <main className={styles.blog}>{children}</main>
65+
```tsx filename="pages/blog/index.tsx" switcher
66+
import styles from './blog.module.css'
67+
68+
export default function Page() {
69+
return <main className={styles.blog}></main>
4870
}
4971
```
5072

73+
```jsx filename="pages/blog/index.js" switcher
74+
import styles from './blog.module.css'
75+
76+
export default function Page() {
77+
return <main className={styles.blog}></main>
78+
}
79+
```
80+
81+
</PagesOnly>
82+
5183
## Global CSS
5284

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

55-
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:
87+
<AppOnly>
88+
89+
Create a `app/global.css` file and import it in the root layout to apply the styles to **every route** in your application:
5690

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

95129
> **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.
96130
131+
</AppOnly>
132+
133+
<PagesOnly>
134+
135+
Import the stylesheet in the `pages/_app.js` file to apply the styles to **every route** in your application:
136+
137+
```tsx filename="pages/_app.js"
138+
import '@/styles/global.css'
139+
140+
export default function MyApp({ Component, pageProps }) {
141+
return <Component {...pageProps} />
142+
}
143+
```
144+
145+
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).
146+
147+
</PagesOnly>
148+
97149
## External stylesheets
98150

151+
<AppOnly>
152+
99153
Stylesheets published by external packages can be imported anywhere in the `app` directory, including colocated components:
100154

101155
```tsx filename="app/layout.tsx" switcher
@@ -126,4 +180,113 @@ export default function RootLayout({ children }) {
126180
}
127181
```
128182

129-
External stylesheets must be directly imported from an npm package or downloaded and colocated with your codebase. You cannot use `<link rel="stylesheet" />`.
183+
> **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.
184+
185+
</AppOnly>
186+
187+
<PagesOnly>
188+
189+
Next.js allows you to import CSS files from a JavaScript file.
190+
This is possible because Next.js extends the concept of [`import`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/import) beyond JavaScript.
191+
192+
### Import styles from `node_modules`
193+
194+
Since Next.js **9.5.4**, importing a CSS file from `node_modules` is permitted anywhere in your application.
195+
196+
For global stylesheets, like `bootstrap` or `nprogress`, you should import the file inside `pages/_app.js`. For example:
197+
198+
```jsx filename="pages/_app.js"
199+
import 'bootstrap/dist/css/bootstrap.css'
200+
201+
export default function MyApp({ Component, pageProps }) {
202+
return <Component {...pageProps} />
203+
}
204+
```
205+
206+
To import CSS required by a third-party component, you can do so in your component. For example:
207+
208+
```jsx filename="components/example-dialog.js"
209+
import { useState } from 'react'
210+
import { Dialog } from '@reach/dialog'
211+
import VisuallyHidden from '@reach/visually-hidden'
212+
import '@reach/dialog/styles.css'
213+
214+
function ExampleDialog(props) {
215+
const [showDialog, setShowDialog] = useState(false)
216+
const open = () => setShowDialog(true)
217+
const close = () => setShowDialog(false)
218+
219+
return (
220+
<div>
221+
<button onClick={open}>Open Dialog</button>
222+
<Dialog isOpen={showDialog} onDismiss={close}>
223+
<button className="close-button" onClick={close}>
224+
<VisuallyHidden>Close</VisuallyHidden>
225+
<span aria-hidden>×</span>
226+
</button>
227+
<p>Hello there. I am a dialog</p>
228+
</Dialog>
229+
</div>
230+
)
231+
}
232+
```
233+
234+
</PagesOnly>
235+
## Ordering and Merging
236+
237+
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**.
238+
239+
For example, `base-button.module.css` will be ordered before `page.module.css` since `<BaseButton>` is imported before `page.module.css`:
240+
241+
```tsx filename="page.ts" switcher
242+
import { BaseButton } from './base-button'
243+
import styles from './page.module.css'
244+
245+
export default function Page() {
246+
return <BaseButton className={styles.primary} />
247+
}
248+
```
249+
250+
```jsx filename="page.js" switcher
251+
import { BaseButton } from './base-button'
252+
import styles from './page.module.css'
253+
254+
export default function Page() {
255+
return <BaseButton className={styles.primary} />
256+
}
257+
```
258+
259+
```tsx filename="base-button.tsx" switcher
260+
import styles from './base-button.module.css'
261+
262+
export function BaseButton() {
263+
return <button className={styles.primary} />
264+
}
265+
```
266+
267+
```jsx filename="base-button.js" switcher
268+
import styles from './base-button.module.css'
269+
270+
export function BaseButton() {
271+
return <button className={styles.primary} />
272+
}
273+
```
274+
275+
### Recommendations
276+
277+
To keep CSS ordering predictable:
278+
279+
- Try to contain CSS imports to a single JavaScript or TypeScript entry file
280+
- Import global styles and Tailwind stylesheets in the root of your application.
281+
- Use CSS Modules instead of global styles for nested components.
282+
- Use a consistent naming convention for your CSS modules. For example, using `<name>.module.css` over `<name>.tsx`.
283+
- Extract shared styles into shared components to avoid duplicate imports.
284+
- Turn off linters or formatters that auto-sort imports like ESLint’s [`sort-imports`](https://eslint.org/docs/latest/rules/sort-imports).
285+
- 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.
286+
287+
## Development vs Production
288+
289+
- In development (`next dev`), CSS updates apply instantly with [Fast Refresh](/docs/architecture/fast-refresh).
290+
- 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.
291+
- CSS still loads with JavaScript disabled in production, but JavaScript is required in development for Fast Refresh.
292+
- CSS ordering can behave differently in development, always ensure to check the build (`next build`) to verify the final CSS order.

docs/01-app/02-guides/css-in-js.mdx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ The following are currently working on support:
3232

3333
> **Good to know**: We're testing out different CSS-in-JS libraries and we'll be adding more examples for libraries that support React 18 features and/or the `app` directory.
3434
35-
If you want to style Server Components, we recommend using [CSS Modules](/docs/app/building-your-application/styling/css) or other solutions that output CSS files, like PostCSS or [Tailwind CSS](/docs/app/guides/tailwind-css).
36-
3735
## Configuring CSS-in-JS in `app`
3836

3937
Configuring CSS-in-JS is a three-step opt-in process that involves:

docs/01-app/02-guides/migrating/app-router-migration.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -886,11 +886,11 @@ If you are also migrating to Next.js from a Single-Page Application (SPA) at the
886886

887887
In the `pages` directory, global stylesheets are restricted to only `pages/_app.js`. With the `app` directory, this restriction has been lifted. Global styles can be added to any layout, page, or component.
888888

889-
- [CSS Modules](/docs/app/building-your-application/styling/css#css-modules)
889+
- [CSS Modules](/docs/app/getting-started/css#css-modules)
890890
- [Tailwind CSS](/docs/app/guides/tailwind-css)
891-
- [Global Styles](/docs/app/building-your-application/styling/css#global-styles)
891+
- [Global Styles](/docs/app/getting-started/css#global-css)
892892
- [CSS-in-JS](/docs/app/guides/css-in-js)
893-
- [External Stylesheets](/docs/app/building-your-application/styling/css#external-stylesheets)
893+
- [External Stylesheets](/docs/app/getting-started/css#external-stylesheets)
894894
- [Sass](/docs/app/guides/sass)
895895

896896
#### Tailwind CSS

docs/01-app/02-guides/migrating/from-create-react-app.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ With the above changes, you shifted from declaring everything in your `index.htm
273273

274274
### Step 5: Styles
275275

276-
Like CRA, Next.js supports [CSS Modules](/docs/app/building-your-application/styling/css#css-modules) out of the box. It also supports [global CSS imports](/docs/app/building-your-application/styling/css#global-styles).
276+
Like CRA, Next.js supports [CSS Modules](/docs/app/getting-started/css#css-modules) out of the box. It also supports [global CSS imports](/docs/app/getting-started/css#global-css).
277277

278278
If you have a global CSS file, import it into your `app/layout.tsx`:
279279

docs/01-app/02-guides/tailwind-css.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ There is also an [upgrade CLI](https://tailwindcss.com/docs/upgrade-guide) and [
3939

4040
## Importing Styles
4141

42-
Add the [Tailwind CSS directives](https://tailwindcss.com/docs/functions-and-directives#directives) that Tailwind will use to inject its generated styles to a [Global Stylesheet](/docs/app/building-your-application/styling/css#global-styles) in your application, for example:
42+
Add the [Tailwind CSS directives](https://tailwindcss.com/docs/functions-and-directives#directives) that Tailwind will use to inject its generated styles to a [Global Stylesheet](/docs/app/getting-started/css#global-css) in your application, for example:
4343

4444
```css filename="app/globals.css"
4545
@import 'tailwindcss';
@@ -111,7 +111,7 @@ export default function Page() {
111111

112112
## Importing Styles
113113

114-
Add the [Tailwind CSS directives](https://tailwindcss.com/docs/functions-and-directives#directives) that Tailwind will use to inject its generated styles to a [Global Stylesheet](/docs/pages/building-your-application/styling/css#global-styles) in your application, for example:
114+
Add the [Tailwind CSS directives](https://tailwindcss.com/docs/functions-and-directives#directives) that Tailwind will use to inject its generated styles to a [Global Stylesheet](/docs/app/getting-started/css#global-css) in your application, for example:
115115

116116
```css filename="styles/globals.css"
117117
@import 'tailwindcss';

0 commit comments

Comments
 (0)