Skip to content

Commit

Permalink
Overhaul image component documentation (vercel#29186)
Browse files Browse the repository at this point in the history
This PR contains an overhaul of the image component documentation for next (both the [primary usage doc](https://nextjs.org/docs/basic-features/image-optimization) and the [API reference](https://nextjs.org/docs/api-reference/next/image)). This PR does not change the filepath/URL for either of those documents, but that may still be warranted as right now Google searches for "next.js image component" and the like return the API document as the first result, which is not optimal.

The changes to the docs are based on feedback from the community and with input from @leerob. I'm marking this PR a draft because we will likely want to have a round of revisions before merging, but in general I consider this PR "read to go," contingent on buy-in from other stakeholders.

The basic goal of the changes are as follows:
1. Simplify the getting started page by moving extraneous detail to the API documentation.
2. Refocus the getting started page on practical usage information
3. Add additional content to address issues that have come up as common pain-points around the image component, such as image sizing and styling.

Fixes vercel#21786 

CC: @styfle @timneutkens @kara @spanicker
  • Loading branch information
atcastle authored Oct 5, 2021
1 parent 8eec492 commit 5d7b68f
Show file tree
Hide file tree
Showing 2 changed files with 237 additions and 176 deletions.
215 changes: 149 additions & 66 deletions docs/api-reference/next/image.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,52 +24,22 @@ description: Enable Image Optimization with the built-in Image component.

</details>

> Before moving forward, we recommend you to read
> [Image Optimization](/docs/basic-features/image-optimization.md) first.
Image Optimization can be enabled via the `<Image />` component exported by
`next/image`.

## Usage

For an example, consider a project with the following files:

- `pages/index.js`
- `public/me.png`

We can serve an optimized image like so:

```jsx
import Image from 'next/image'
import profilePic from '../public/me.png'

function Home() {
return (
<>
<h1>My Homepage</h1>
<Image src={profilePic} alt="Picture of the author" />
<p>Welcome to my homepage!</p>
</>
)
}

export default Home
```
> **Note: This is API documentation for the Image Component and Image Optimization. For a feature overview and usage information for images in Next.js, please see [Images](/docs/basic-features/image-optimization.md).**
## Required Props

The `<Image />` component requires the following properties.

### src

Required and must be one of the following:
Must be one of the following:

1. A statically imported image file, as in the example code above, or
1. A [statically imported](/docs/basic-features/image-optimization.md#local-images) image file, or
2. A path string. This can be either an absolute external URL,
or an internal path depending on the [loader](#loader).

When using an external URL, you must add it to
[domains](/docs/basic-features/image-optimization.md#domains) in
[domains](#domains) in
`next.config.js`.

### width
Expand All @@ -86,18 +56,18 @@ Required, except for statically imported images, or those with [`layout="fill"`]

## Optional Props

The `<Image />` component optionally accepts the following properties.
The `<Image />` component accepts a number of additional properties beyond those which are required. This section describes the most commonly-used properties of the Image component. Find details about more rarely-used properties in the [Advanced Props](#advanced-props) section.

### layout

The layout behavior of the image as the viewport changes size.

| `layout` | Behavior | `srcSet` | `sizes` |
| --------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| `intrinsic` (default) | Scale *down* to fit width of container, up to image size | `1x``2x` (based on [imageSizes](/docs/basic-features/image-optimization.md#image-sizes)) | N/A |
| `fixed` | Sized to `width` and `height` exactly | `1x``2x` (based on [imageSizes](/docs/basic-features/image-optimization.md#image-sizes)) | N/A |
| `responsive` | Scale to fit width of container | `640w``750w`, ... `2048w``3840w` (based on [imageSizes](/docs/basic-features/image-optimization.md#image-sizes) and [deviceSizes](/docs/basic-features/image-optimization.md#device-sizes)) | `100vw` |
| `fill` | Grow in X and Y axes to fill container | `640w``750w`, ... `2048w``3840w` (based on [imageSizes](/docs/basic-features/image-optimization.md#image-sizes) and [deviceSizes](/docs/basic-features/image-optimization.md#device-sizes)) | `100vw` |
| `layout` | Behavior | `srcSet` | `sizes` |
| --------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------- |
| `intrinsic` (default) | Scale *down* to fit width of container, up to image size | `1x``2x` (based on [imageSizes](#image-sizes)) | N/A |
| `fixed` | Sized to `width` and `height` exactly | `1x``2x` (based on [imageSizes](#image-sizes)) | N/A |
| `responsive` | Scale to fit width of container | `640w``750w`, ... `2048w``3840w` (based on [imageSizes](#image-sizes) and [deviceSizes](#device-sizes)) | `100vw` |
| `fill` | Grow in both X and Y axes to fill container | `640w``750w`, ... `2048w``3840w` (based on [imageSizes](#image-sizes) and [deviceSizes](#device-sizes)) | `100vw` |

- [Demo the `intrinsic` layout (default)](https://image-component.nextjs.gallery/layout-intrinsic)
- When `intrinsic`, the image will scale the dimensions down for smaller viewports, but maintain the original dimensions for larger viewports.
Expand All @@ -114,14 +84,16 @@ The layout behavior of the image as the viewport changes size.

### loader

A custom function used to resolve URLs. Defaults to [`images` object in `next.config.js`](/docs/basic-features/image-optimization.md#loader).
A custom function used to resolve URLs. Setting the loader as a prop on the Image component overrides the default loader defined in the [`images` section of `next.config.js`](#loader-configuration).

`loader` is a function returning a string, given the following parameters:
A `loader` is a function returning a URL string for the image, given the following parameters:

- [`src`](#src)
- [`width`](#width)
- [`quality`](#quality)

Here is an example of using a custom loader with `next/image`:

```js
import Image from 'next/image'

Expand All @@ -144,30 +116,32 @@ const MyImage = (props) => {

### sizes

A string mapping media queries to device sizes. Defaults to `100vw`.
A string that provides information about how wide the image will be at different breakpoints. Defaults to `100vw` (the full width of the screen) when using `layout="responsive"` or `layout="fill"`.

`sizes` is important for performance when using `layout="responsive"` or `layout="fill"` with images that take up less than the full viewport width.

We recommend setting `sizes` when using `layout="responsive"` or `layout="fill"` and your image will **not** be the same width as the viewport.
If you are using `layout="fill"` or `layout="responsive"` and the image will always be less than half the viewport width, include `sizes="50vw"`. Without `sizes`, the image will be sent at twice the necessary resolution, decreasing performance.

[Learn more](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-sizes).

### quality

The quality of the optimized image, an integer between `1` and `100` where `100`
is the best quality. Defaults to `75`.
The quality of the optimized image, an integer between `1` and `100` where `100` is the best quality. Defaults to `75`.

### priority

When true, the image will be considered high priority and
[preload](https://web.dev/preload-responsive-images/).
[preload](https://web.dev/preload-responsive-images/). Lazy loading is automatically disabled for images using `priority`.

Should only be used when the image is visible above the fold. Defaults to
`false`.
You should use the `priority` attribute on any image which you suspect will be the [Largest Contentful Paint (LCP) element](https://nextjs.org/learn/seo/web-performance/lcp). It may be appropriate to have multiple priority images, as different images may be the LCP element for different viewport sizes.

Should only be used when the image is visible above the fold. Defaults to `false`.

### placeholder

A placeholder to use while the image is loading, possible values are `blur` or `empty`. Defaults to `empty`.
A placeholder to use while the image is loading. Possible values are `blur` or `empty`. Defaults to `empty`.

When `blur`, the [`blurDataURL`](#blurdataurl) property will be used as the placeholder. If `src` is an object from a static import and the imported image is jpg, png, or webp, then `blurDataURL` will automatically be populated.
When `blur`, the [`blurDataURL`](#blurdataurl) property will be used as the placeholder. If `src` is an object from a [static import](#local-images) and the imported image is `.jpg`, `.png`, or `.webp`, then `blurDataURL` will be automatically populated.

For dynamic images, you must provide the [`blurDataURL`](#blurdataurl) property. Solutions such as [Plaiceholder](https://github.com/joe-bell/plaiceholder) can help with `base64` generation.

Expand All @@ -180,20 +154,19 @@ Try it out:

## Advanced Props

In some cases, you may need more advanced usage. The `<Image />` component
optionally accepts the following advanced properties.
In some cases, you may need more advanced usage. The `<Image />` component optionally accepts the following advanced properties.

### objectFit

The image fit when using `layout="fill"`.
Defines how the image will fit into its parent container when using `layout="fill"`.

[Learn more](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit)
This value is passed to the [object-fit CSS property](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) for the `src` image.

### objectPosition

The image position when using `layout="fill"`.
Defines how the image is positioned within its parent element when using `layout="fill"`.

[Learn more](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position)
This value is passed to the [object-position CSS property](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position) applied to the image.

### onLoadingComplete

Expand Down Expand Up @@ -255,26 +228,136 @@ Other properties on the `<Image />` component will be passed to the underlying

- `style`. Use `className` instead.
- `srcSet`. Use
[Device Sizes](/docs/basic-features/image-optimization.md#device-sizes)
[Device Sizes](#device-sizes)
instead.
- `ref`. Use [`onLoadingComplete`](#onloadingcomplete) instead.
- `decoding`. It is always `"async"`.

## Styling
## Configuration Options

### Domains

To protect your application from malicious users, you must define a list of image provider domains that you want to be served from the Next.js Image Optimization API. This is configured in with the `domains` property in your `next.config.js` file, as shown below:

```js
module.exports = {
images: {
domains: ['assets.acme.com'],
},
}
```

### Loader Configuration

If you want to use a cloud provider to optimize images instead of using the Next.js built-in Image Optimization API, you can configure the `loader` and `path` prefix in your `next.config.js` file. This allows you to use relative URLs for the Image `src` and automatically generate the correct absolute URL for your provider.

```js
module.exports = {
images: {
loader: 'imgix',
path: 'https://example.com/myaccount/',
},
}
```

### Built-in Loaders

The following Image Optimization cloud providers are included:

- Default: Works automatically with `next dev`, `next start`, or a custom server
- [Vercel](https://vercel.com): Works automatically when you deploy on Vercel, no configuration necessary. [Learn more](https://vercel.com/docs/next.js/image-optimization)
- [Imgix](https://www.imgix.com): `loader: 'imgix'`
- [Cloudinary](https://cloudinary.com): `loader: 'cloudinary'`
- [Akamai](https://www.akamai.com): `loader: 'akamai'`
- Custom: `loader: 'custom'` use a custom cloud provider by implementing the [`loader`](/docs/api-reference/next/image.md#loader) prop on the `next/image` component

If you need a different provider, you can use the [`loader`](#loader) prop with `next/image`.

> The `next/image` component's default loader is not supported when using [`next export`](/docs/advanced-features/static-html-export.md). However, other loader options will work.
> The `next/image` component's default loader uses [`squoosh`](https://www.npmjs.com/package/@squoosh/lib) because it is quick to install and suitable for a development environment. When using `next start` in your production environment, it is strongly recommended that you install [`sharp`](https://www.npmjs.com/package/sharp) by running `yarn add sharp` in your project directory. This is not necessary for Vercel deployments, as `sharp` is installed automatically.
`next/image` wraps the `img` element with a single `div` element to maintain the aspect ratio of the image and prevent [Cumulative Layout Shift](https://vercel.com/blog/core-web-vitals#cumulative-layout-shift).
## Advanced

To add styles to the underlying `img` element, pass the `className` prop to the `<Image />` component. Then, use Next.js' [built-in CSS support](/docs/basic-features/built-in-css-support.md) to add rules to that class.
The following configuration is for advanced use cases and is usually not necessary. If you choose to configure the properties below, you will override any changes to the Next.js defaults in future updates.

**Note:** If using [`layout="fill"`](/docs/api-reference/next/image.md#layout), ensure the parent element uses `position: relative`.
### Device Sizes

If you know the expected device widths of your users, you can specify a list of device width breakpoints using the `deviceSizes` property in `next.config.js`. These widths are used when the [`next/image`](/docs/api-reference/next/image.md) component uses `layout="responsive"` or `layout="fill"` to ensure the correct image is served for user's device.

If no configuration is provided, the default below is used.

```js
module.exports = {
images: {
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
},
}
```

### Image Sizes

You can specify a list of image widths using the `images.imageSizes` property in your `next.config.js` file. These widths are concatenated with the array of [device sizes](#device-sizes) to form the full array of sizes used to generate image [srcset](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/srcset)s.

The reason there are two seperate lists is that imageSizes is only used for images which provide a [`sizes`](#sizes) prop, which indicates that the image is less than the full width of the screen. **Therefore, the sizes in imageSizes should all be smaller than the smallest size in deviceSizes.**

If no configuration is provided, the default below is used.

```js
module.exports = {
images: {
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
},
}
```

## Caching Behavior

The following describes the caching algorithm for the default [loader](#loader). For all other loaders, please refer to your cloud provider's documentation.

Images are optimized dynamically upon request and stored in the `<distDir>/cache/images` directory. The optimized image file will be served for subsequent requests until the expiration is reached. When a request is made that matches a cached but expired file, the cached file is deleted before generating a new optimized image and caching the new file.

The expiration (or rather Max Age) is defined by the upstream server's `Cache-Control` header.

- If `s-maxage` is found in `Cache-Control`, it is used. If no `s-maxage` is found, then `max-age` is used. If no `max-age` is found, then [`minimumCacheTTL`](#minimum-cache-ttl) is used.
- You can configure [`minimumCacheTTL`](#minimum-cache-ttl) to increase the cache duration when the upstream image does not include `max-age`.
- You can also configure [`deviceSizes`](#device-sizes) and [`imageSizes`](#device-sizes) to reduce the total number of possible generated images.

You can configure the Time to Live (TTL) in seconds for cached optimized images. In many cases, it's better to use a [Static Image Import](/docs/basic-features/image-optimization.md#local-images) which will automatically hash the file contents and cache the image forever with a `Cache-Control` header of `immutable`.

```js
module.exports = {
images: {
minimumCacheTTL: 60,
},
}
```

If you need to add a `Cache-Control` header for the browser (not recommended), you can configure [`headers`](/docs/api-reference/next.config.js/headers) on the upstream image e.g. `/some-asset.jpg` not `/_next/image` itself.

### Disable Static Imports

The default behavior allows you to import static files such as `import icon from './icon.png` and then pass that to the `src` property.

In some cases, you may wish to disable this feature if it conflicts with other plugins that expect the import to behave differently.

You can disable static image imports inside your `next.config.js`:

```js
module.exports = {
images: {
disableStaticImages: true,
},
}
```

## Related

For more information on what to do next, we recommend the following sections:
For an overview of the Image component features and usage guidelines, see:

<div class="card">
<a href="/docs/basic-features/image-optimization.md">
<b>Image Optimization</b>
<small>See how to configure domains and loaders.</small>
<b>Images</b>
<small>Learn how to display and optimize images with the Image component.</small>
</a>
</div>
Loading

0 comments on commit 5d7b68f

Please sign in to comment.