Skip to content
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

Getting Started docs: Images and Fonts #73340

Merged
merged 20 commits into from
Dec 3, 2024
Merged
Changes from 18 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
90625f6
Create 04-images-and-fonts.mdx
delbaoliveira Nov 29, 2024
3fd7b76
Add 'handling static assets' section
delbaoliveira Nov 29, 2024
a020083
Add "optimizing images" section
delbaoliveira Nov 29, 2024
f832bff
Add "local images" section
delbaoliveira Nov 29, 2024
d87b474
Clean up
delbaoliveira Nov 29, 2024
94953ef
Add "remote images" section
delbaoliveira Nov 29, 2024
af93482
Add optimizing fonts section
delbaoliveira Nov 29, 2024
21ea925
Clean up
delbaoliveira Nov 29, 2024
e418d8a
Add "local fonts" section
delbaoliveira Nov 29, 2024
bed3130
Add "google fonts" section
delbaoliveira Nov 29, 2024
4a8fdad
Delete new link for now
delbaoliveira Nov 29, 2024
5a63fa6
Merge branch 'canary' into docs-getting-started-images-and-fonts
delbaoliveira Nov 29, 2024
8463a72
Apply suggestions from code review
delbaoliveira Dec 2, 2024
83b10b7
Merge branch 'canary' into docs-getting-started-images-and-fonts
delbaoliveira Dec 2, 2024
732e29b
Update docs/01-app/01-getting-started/04-images-and-fonts.mdx
delbaoliveira Dec 2, 2024
28fe2bf
Merge branch 'canary' into docs-getting-started-images-and-fonts
delbaoliveira Dec 2, 2024
fc6761f
Update docs/01-app/01-getting-started/04-images-and-fonts.mdx
delbaoliveira Dec 2, 2024
ec9dc4e
Update docs/01-app/01-getting-started/04-images-and-fonts.mdx
delbaoliveira Dec 2, 2024
1257ae4
Update docs/01-app/01-getting-started/04-images-and-fonts.mdx
delbaoliveira Dec 3, 2024
b89e907
Merge branch 'canary' into docs-getting-started-images-and-fonts
delbaoliveira Dec 3, 2024
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
371 changes: 371 additions & 0 deletions docs/01-app/01-getting-started/04-images-and-fonts.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,371 @@
---
title: How to optimize images and fonts
nav_title: Images and Fonts
description: Learn how to optimize images and fonts with Next.js
related:
links:
- app/api-reference/components/font
- app/api-reference/components/image
---

Next.js comes with automatic image and font optimizations for better performance and user experience. This page will guide you through how to start using them.

## Handling static assets

You can store static files, like images and fonts, under a folder called `public` in the root directory. Files inside `public` can then be referenced by your code starting from the base URL (`/`).

<Image
alt="Folder structure showing app and public folders"
srcLight="/docs/light/public-folder.png"
srcDark="/docs/dark/public-folder.png"
width="1600"
height="282"
/>

## Optmizing images

The Next.js [`<Image>`](/docs/app/building-your-application/optimizing/images) component extends the HTML `<img>` element to provide:

- **Size optimization:** Automatically serving correctly sized images for each device, using modern image formats like WebP and AVIF.
- **Visual stability:** Preventing [layout shift](/learn/seo/web-performance/cls) automatically when images are loading.
- **Faster page loads:** Only loading images when they enter the viewport using native browser lazy loading, with optional blur-up placeholders.
- **Asset flexibility:** Resizing images on-demand, even images stored on remote servers.

To start using `<Image>`, first import it from `next/image` and render it within your component.

```tsx filename="app/page.tsx" switcher
import Image from 'next/image'

export default function Page() {
return <Image src="" alt="" />
}
```

```jsx filename="app/page.js" switcher
import Image from 'next/image'

export default function Page() {
return <Image src="" alt="" />
}
```

The `src` property can be a [local](#local-images) or [remote](#remote-images) image.

### Local images

To use a local image, `import` your `.jpg`, `.png`, or `.webp` image files from your [`public` folder](#handling-static-assets).

```tsx filename="app/page.ts" switcher
import Image from 'next/image'
import profilePic from './me.png'

export default function Page() {
return (
<Image
src={profilePic}
alt="Picture of the author"
// width={500} automatically provided
// height={500} automatically provided
// blurDataURL="data:..." automatically provided
// placeholder="blur" // Optional blur-up while loading
/>
)
}
```

```jsx filename="app/page.js" switcher
import Image from 'next/image'
import profilePic from './me.png'

export default function Page() {
return (
<Image
src={profilePic}
alt="Picture of the author"
// width={500} automatically provided
// height={500} automatically provided
// blurDataURL="data:..." automatically provided
// placeholder="blur" // Optional blur-up while loading
/>
)
}
```

Next.js will automatically determine the intrinsic [`width`](/docs/app/api-reference/components/image#width) and [`height`](/docs/app/api-reference/components/image#height) of your image based on the imported file. These values are used to determine the image ratio and prevent [Cumulative Layout Shift](https://nextjs.org/learn/seo/web-performance/cls) while your image is loading.

### Remote images

To use a remote image, you can provide an URL string for the `src` property.

```tsx filename="app/page.ts" switcher
import Image from 'next/image'

export default function Page() {
return (
<Image
src="https://s3.amazonaws.com/my-bucket/profile.png"
alt="Picture of the author"
width={500}
height={500}
/>
)
}
```

```jsx filename="app/page.js" switcher
import Image from 'next/image'

export default function Page() {
return (
<Image
src="https://s3.amazonaws.com/my-bucket/profile.png"
alt="Picture of the author"
width={500}
height={500}
/>
)
}
```

Since Next.js does not have access to remote files during the build process, you'll need to provide the [`width`](/docs/app/api-reference/components/image#width), [`height`](/docs/app/api-reference/components/image#height) and optional [`blurDataURL`](/docs/app/api-reference/components/image#blurdataurl) props manually.

> **Good to know:** The `width` and `height` attributes are used to infer the correct aspect ratio of image and avoid layout shift from the image loading in. The `width` and `height` do _not_ determine the rendered size of the image file.

Then, to safely allow images from remote servers, you need to define a list of supported URL patterns in `next.config.js`. Be as specific as possible to prevent malicious usage. For example, the following configuration will only allow images from a specific AWS S3 bucket:

```ts filename="next.config.js" switcher
import { NextConfig } from 'next'

const config: NextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 's3.amazonaws.com',
port: '',
pathname: '/my-bucket/**',
},
],
},
}

export default config
```

```js filename="next.config.js" switcher
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 's3.amazonaws.com',
port: '',
pathname: '/my-bucket/**',
},
],
},
}
```

Learn more about Image Optimization in the [API Reference](/docs/app/api-reference/components/image).

## Optimizing fonts

The [`next/font`](/docs/app/api-reference/components/font) module automatically optimizes your fonts and removes external network requests for improved privacy and performance.

It includes **built-in automatic self-hosting** for _any_ font file. This means you can optimally load web fonts with no layout shift.

To start using `next/font`, import it from `next/font/local` or `next/font/google` (depending on whether you're using a [local](#local-fonts) or [Google](#google-fonts) font), call it as a function with the appropriate options, and set the `className` of the element you want to apply the font to.

```tsx filename="app/layout.tsx" switcher
import { Geist } from 'next/font/google'

const geist = Geist({
subsets: ['latin'],
display: 'swap',
})

export default function Layout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" className={geist.className}>
<body>{children}</body>
</html>
)
}
```

```jsx filename="app/layout.js" switcher
import { Geist } from 'next/font/google'

const geist = Geist({
subsets: ['latin'],
display: 'swap',
})

export default function Layout({ children }) {
return (
<html className={geist.className}>
<body>{children}</body>
</html>
)
}
```

### Local fonts

To use a local font, import `next/font/local` and specify the `src` of your local font file in the [`public` folder](#handling-static-assets).

```tsx filename="app/layout.tsx" switcher
import localFont from 'next/font/local'

const myFont = localFont({
src: './my-font.woff2',
display: 'swap',
})

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

```jsx filename="app/layout.js" switcher
import localFont from 'next/font/local'

const myFont = localFont({
src: './my-font.woff2',
display: 'swap',
})

export default function RootLayout({ children }) {
return (
<html lang="en" className={myFont.className}>
<body>{children}</body>
</html>
)
}
```

If you want to use multiple files for a single font family, `src` can be an array:

```js
const roboto = localFont({
src: [
{
path: './Roboto-Regular.woff2',
weight: '400',
style: 'normal',
},
{
path: './Roboto-Italic.woff2',
weight: '400',
style: 'italic',
},
{
path: './Roboto-Bold.woff2',
weight: '700',
style: 'normal',
},
{
path: './Roboto-BoldItalic.woff2',
weight: '700',
style: 'italic',
},
],
})
```

### Google fonts

You can automatically self-host any Google Font. Fonts are included in the deployment and served from the same domain as your deployment. **No requests are sent to Google by the browser.**

To start using a Google Font, import it from `next/font/google` as a function.

```tsx filename="app/layout.tsx" switcher
import { Inter } from 'next/font/google'

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

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

```jsx filename="app/layout.js" switcher
import { Inter } from 'next/font/google'

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

export default function RootLayout({ children }) {
return (
<html lang="en" className={inter.className}>
<body>{children}</body>
</html>
)
}
```

We recommend using [variable fonts](https://fonts.google.com/variablefonts) for the best performance and flexibility. But if you can't use a variable font, you will **need to specify a weight**:

```tsx filename="app/layout.tsx" switcher
import { Roboto } from 'next/font/google'

const roboto = Roboto({
weight: '400',
subsets: ['latin'],
display: 'swap',
})

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

```jsx filename="app/layout.js" switcher
import { Roboto } from 'next/font/google'

const roboto = Roboto({
weight: '400',
subsets: ['latin'],
display: 'swap',
})

export default function RootLayout({ children }) {
return (
<html lang="en" className={roboto.className}>
<body>{children}</body>
</html>
)
}
```

Learn more about Font Optimization in the [API Reference](/docs/app/api-reference/components/font).
Loading