Update next/image docs and examples (#41434)

This PR updates the docs for the following code change:

- #41399

There are a few updates here:

- [x] Update docs
- [x] Update links to docs inside component
- [x] Update examples
- [x] Fix corner cases in codemod
This commit is contained in:
Steven 2022-10-17 10:41:35 -04:00 committed by GitHub
parent e61820e04d
commit e2f16f96c2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
44 changed files with 1078 additions and 463 deletions

View file

@ -64,7 +64,97 @@ Dangerously migrates from `next/legacy/image` to the new `next/image` by adding
- Removes `objectPosition` prop and adds `style` - Removes `objectPosition` prop and adds `style`
- Removes `lazyBoundary` prop - Removes `lazyBoundary` prop
- Removes `lazyRoot` prop - Removes `lazyRoot` prop
- TODO: handle `loader` - TODO: does not migrate the `loader` config. If you need it, you must manually add a `loader` prop.
#### Before: intrinsic
```jsx
import Image from 'next/image'
import img from '../img.png'
function Page() {
return <Image src={img} />
}
```
#### After: intrinsic
```jsx
import Image from 'next/image'
import img from '../img.png'
const css = { maxWidth: '100%', height: 'auto' }
function Page() {
return <Image src={img} style={css} />
}
```
#### Before: responsive
```jsx
import Image from 'next/image'
import img from '../img.png'
function Page() {
return <Image src={img} layout="responsive" />
}
```
#### After: responsive
```jsx
import Image from 'next/image'
import img from '../img.png'
const css = { width: '100%', height: 'auto' }
function Page() {
return <Image src={img} sizes="100vw" style={css} />
}
```
#### Before: fill
```jsx
import Image from 'next/image'
import img from '../img.png'
function Page() {
return <Image src={img} layout="fill" />
}
```
#### After: fill
```jsx
import Image from 'next/image'
import img from '../img.png'
function Page() {
return <Image src={img} sizes="100vw" fill />
}
```
#### Before: fixed
```jsx
import Image from 'next/image'
import img from '../img.png'
function Page() {
return <Image src={img} layout="fixed" />
}
```
#### After: fixed
```jsx
import Image from 'next/image'
import img from '../img.png'
function Page() {
return <Image src={img} />
}
```
## Next.js 11 ## Next.js 11

View file

@ -4,33 +4,40 @@ description: Enable Image Optimization with the built-in Image component.
# next/image # next/image
<details>
<summary><b>Examples</b></summary>
<ul>
<li><a href="https://github.com/vercel/next.js/tree/canary/examples/image-component">Image Component</a></li>
</ul>
</details>
<details> <details>
<summary><b>Version History</b></summary> <summary><b>Version History</b></summary>
| Version | Changes | | Version | Changes |
| --------- | --------------------------------------------------------------------------------------------------------- | | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `v12.3.0` | `remotePatterns` and `unoptimized` configuration is stable. | | `v13.0.0` | `<span>` wrapper removed. `layout`, `objectFit`, `objectPosition`, `lazyBoundary`, `lazyRoot` props removed. `alt` is required. `onLoadingComplete` receives reference to `img` element. Built-in loader config removed. |
| `v12.2.0` | Experimental `remotePatterns` and experimental `unoptimized` configuration added. `layout="raw"` removed. | | `v12.3.0` | `remotePatterns` and `unoptimized` configuration is stable. |
| `v12.1.1` | `style` prop added. Experimental[\*](#experimental-raw-layout-mode) support for `layout="raw"` added. | | `v12.2.0` | Experimental `remotePatterns` and experimental `unoptimized` configuration added. `layout="raw"` removed. |
| `v12.1.0` | `dangerouslyAllowSVG` and `contentSecurityPolicy` configuration added. | | `v12.1.1` | `style` prop added. Experimental[\*](#experimental-raw-layout-mode) support for `layout="raw"` added. |
| `v12.0.9` | `lazyRoot` prop added. | | `v12.1.0` | `dangerouslyAllowSVG` and `contentSecurityPolicy` configuration added. |
| `v12.0.0` | `formats` configuration added.<br/>AVIF support added.<br/>Wrapper `<div>` changed to `<span>`. | | `v12.0.9` | `lazyRoot` prop added. |
| `v11.1.0` | `onLoadingComplete` and `lazyBoundary` props added. | | `v12.0.0` | `formats` configuration added.<br/>AVIF support added.<br/>Wrapper `<div>` changed to `<span>`. |
| `v11.0.0` | `src` prop support for static import.<br/>`placeholder` prop added.<br/>`blurDataURL` prop added. | | `v11.1.0` | `onLoadingComplete` and `lazyBoundary` props added. |
| `v10.0.5` | `loader` prop added. | | `v11.0.0` | `src` prop support for static import.<br/>`placeholder` prop added.<br/>`blurDataURL` prop added. |
| `v10.0.1` | `layout` prop added. | | `v10.0.5` | `loader` prop added. |
| `v10.0.0` | `next/image` introduced. | | `v10.0.1` | `layout` prop added. |
| `v10.0.0` | `next/image` introduced. |
</details> </details>
> **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).** > **Note**: This page is the API reference for the `next/image` component. For a feature overview and usage information, please see the [Image Component and Image Optimization](/docs/basic-features/image-optimization.md) documentation.
> **Note**: If you are using a version of Next.js prior to 13, you'll want to use the [next/legacy/image](/docs/api-reference/next/legacy/image.md) documentation since the component was renamed.
This `next/image` component uses browser native [lazy loading](https://caniuse.com/loading-lazy-attr), which may fallback to eager loading for older browsers before Safari 15.4. When using the blur-up placeholder, older browsers before Safari 12 will fallback to empty placeholder. When using styles with `width`/`height` of `auto`, it is possible to cause [Layout Shift](https://web.dev/cls/) on older browsers before Safari 15 that don't [preserve the aspect ratio](https://caniuse.com/mdn-html_elements_img_aspect_ratio_computed_from_attributes). For more details, see [this MDN video](https://www.youtube.com/watch?v=4-d_SoCHeWE).
## Known Browser Bugs
- [Safari 15](https://bugs.webkit.org/show_bug.cgi?id=243601) displays a gray border while loading. Possible solutions:
- Use CSS `@media not all and (min-resolution:.001dpcm) { img[loading="lazy"] { clip-path: inset(0.5px) } }`
- Use [`priority`](#priority) if the image is above the fold
- [Firefox 67+](https://bugzilla.mozilla.org/show_bug.cgi?id=1556156) displays a white background while loading. Possible solutions:
- Enable [AVIF `formats`](#acceptable-formats)
- Use [`placeholder="blur"`](#placeholder)
## Required Props ## Required Props
@ -42,63 +49,39 @@ Must be one of the following:
1. A [statically imported](/docs/basic-features/image-optimization.md#local-images) image file, 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, 2. A path string. This can be either an absolute external URL,
or an internal path depending on the [loader](#loader) prop or [loader configuration](#loader-configuration). or an internal path depending on the [loader](#loader) prop.
When using an external URL, you must add it to When using an external URL, you must add it to [remotePatterns](#remote-patterns) in `next.config.js`.
[remotePatterns](#remote-patterns) in
`next.config.js`.
### width ### width
The `width` property can represent either the _rendered_ width or _original_ width in pixels, depending on the [`layout`](#layout) and [`sizes`](#sizes) properties. The `width` property represents the _rendered_ width in pixels, so it will affect how large the image appears.
When using `layout="intrinsic"` or `layout="fixed"` the `width` property represents the _rendered_ width in pixels, so it will affect how large the image appears. Required, except for [statically imported images](/docs/basic-features/image-optimization.md#local-images) or images with the [`fill` property](#fill).
When using `layout="responsive"`, `layout="fill"`, the `width` property represents the _original_ width in pixels, so it will only affect the aspect ratio.
The `width` property is required, except for [statically imported images](/docs/basic-features/image-optimization.md#local-images), or those with `layout="fill"`.
### height ### height
The `height` property can represent either the _rendered_ height or _original_ height in pixels, depending on the [`layout`](#layout) and [`sizes`](#sizes) properties. The `height` property represents the _rendered_ height in pixels, so it will affect how large the image appears.
When using `layout="intrinsic"` or `layout="fixed"` the `height` property represents the _rendered_ height in pixels, so it will affect how large the image appears. Required, except for [statically imported images](/docs/basic-features/image-optimization.md#local-images) or images with the [`fill` property](#fill).
When using `layout="responsive"`, `layout="fill"`, the `height` property represents the _original_ height in pixels, so it will only affect the aspect ratio. ### alt
The `height` property is required, except for [statically imported images](/docs/basic-features/image-optimization.md#local-images), or those with `layout="fill"`. The `alt` property is used to describe the image for screen readers and search engines. It is also the fallback text if images have been disabled or an error occurs while loading the image.
It should contain text that could replace the image [without changing the meaning of the page](https://html.spec.whatwg.org/multipage/images.html#general-guidelines). It is not meant to supplement the image and should not repeat information that is already provided in the captions above or below the image.
If the image is [purely decorative](https://html.spec.whatwg.org/multipage/images.html#a-purely-decorative-image-that-doesn't-add-any-information) or [not intended for the user](https://html.spec.whatwg.org/multipage/images.html#an-image-not-intended-for-the-user), the `alt` property should be an empty string (`alt=""`).
[Learn more](https://html.spec.whatwg.org/multipage/images.html#alt)
## Optional Props ## Optional Props
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. 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` | Has wrapper and sizer |
| --------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------- | --------------------- |
| `intrinsic` (default) | Scale *down* to fit width of container, up to image size | `1x`, `2x` (based on [imageSizes](#image-sizes)) | N/A | yes |
| `fixed` | Sized to `width` and `height` exactly | `1x`, `2x` (based on [imageSizes](#image-sizes)) | N/A | yes |
| `responsive` | Scale to fit width of container | `640w`, `750w`, ... `2048w`, `3840w` (based on [imageSizes](#image-sizes) and [deviceSizes](#device-sizes)) | `100vw` | yes |
| `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` | yes |
- [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.
- [Demo the `fixed` layout](https://image-component.nextjs.gallery/layout-fixed)
- When `fixed`, the image dimensions will not change as the viewport changes (no responsiveness) similar to the native `img` element.
- [Demo the `responsive` layout](https://image-component.nextjs.gallery/layout-responsive)
- When `responsive`, the image will scale the dimensions down for smaller viewports and scale up for larger viewports.
- Ensure the parent element uses `display: block` in their stylesheet.
- [Demo the `fill` layout](https://image-component.nextjs.gallery/layout-fill)
- When `fill`, the image will stretch both width and height to the dimensions of the parent element, provided the parent element is relative.
- This is usually paired with the [`objectFit`](#objectFit) property.
- Ensure the parent element has `position: relative` in their stylesheet.
- [Demo background image](https://image-component.nextjs.gallery/background)
### loader ### 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). A custom function used to resolve image URLs.
A `loader` is a function returning a URL string for the image, given the following parameters: A `loader` is a function returning a URL string for the image, given the following parameters:
@ -106,7 +89,7 @@ A `loader` is a function returning a URL string for the image, given the followi
- [`width`](#width) - [`width`](#width)
- [`quality`](#quality) - [`quality`](#quality)
Here is an example of using a custom loader with `next/image`: Here is an example of using a custom loader:
```js ```js
import Image from 'next/image' import Image from 'next/image'
@ -128,15 +111,33 @@ const MyImage = (props) => {
} }
``` ```
### fill
A boolean that causes the image to fill the parent element instead of setting [`width`](#width) and [`height`](#height).
The parent element _must_ assign `position: "relative"`, `position: "fixed"`, or `position: "absolute"` style.
By default, the img element will automatically be assigned the `position: "absolute"` style.
The default image fit behavior will stretch the image to fit the container. You may prefer to set `object-fit: "contain"` for an image which is letterboxed to fit the container and preserve aspect ratio.
Alternatively, `object-fit: "cover"` will cause the image to fill the entire container and be cropped to preserve aspect ratio. For this to look correct, the `overflow: "hidden"` style should be assigned to the parent element.
See also:
- [position](https://developer.mozilla.org/en-US/docs/Web/CSS/position)
- [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit)
- [object-position](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position)
### sizes ### sizes
A string that provides information about how wide the image will be at different breakpoints. The value of `sizes` will greatly affect performance for images using `layout="responsive"` or `layout="fill"`. It will be ignored for images using `layout="intrinsic"` or `layout="fixed"`. A string that provides information about how wide the image will be at different breakpoints. The value of `sizes` will greatly affect performance for images using [`fill`](#fill) or which are styled to have a responsive size.
The `sizes` property serves two important purposes related to image performance: The `sizes` property serves two important purposes related to image performance:
First, the value of `sizes` is used by the browser to determine which size of the image to download, from `next/image`'s automatically-generated source set. When the browser chooses, it does not yet know the size of the image on the page, so it selects an image that is the same size or larger than the viewport. The `sizes` property allows you to tell the browser that the image will actually be smaller than full screen. If you don't specify a `sizes` value, a default value of `100vw` (full screen width) is used. First, the value of `sizes` is used by the browser to determine which size of the image to download, from `next/image`'s automatically-generated source set. When the browser chooses, it does not yet know the size of the image on the page, so it selects an image that is the same size or larger than the viewport. The `sizes` property allows you to tell the browser that the image will actually be smaller than full screen. If you don't specify a `sizes` value in an image with the `fill` property, a default value of `100vw` (full screen width) is used.
Second, the `sizes` value is parsed and used to trim the values in the automatically-created source set. If the `sizes` property includes sizes such as `50vw`, which represent a percentage of the viewport width, then the source set is trimmed to not include any values which are too small to ever be necessary. Second, the `sizes` property configures how `next/image` automatically generates an image source set. If no `sizes` value is present, a small source set is generated, suitable for a fixed-size image. If `sizes` is defined, a large source set is generated, suitable for a responsive image. If the `sizes` property includes sizes such as `50vw`, which represent a percentage of the viewport width, then the source set is trimmed to not include any values which are too small to ever be necessary.
For example, if you know your styling will cause an image to be full-width on mobile devices, in a 2-column layout on tablets, and a 3-column layout on desktop displays, you should include a sizes property such as the following: For example, if you know your styling will cause an image to be full-width on mobile devices, in a 2-column layout on tablets, and a 3-column layout on desktop displays, you should include a sizes property such as the following:
@ -164,7 +165,7 @@ Learn more about `srcset` and `sizes`:
### quality ### 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 and therefore largest file size. Defaults to `75`.
### priority ### priority
@ -199,30 +200,25 @@ In some cases, you may need more advanced usage. The `<Image />` component optio
Allows [passing CSS styles](https://reactjs.org/docs/dom-elements.html#style) to the underlying image element. Allows [passing CSS styles](https://reactjs.org/docs/dom-elements.html#style) to the underlying image element.
Note that all `layout` modes apply their own styles to the image element, and these automatic styles take precedence over the `style` prop.
Also keep in mind that the required `width` and `height` props can interact with your styling. If you use styling to modify an image's `width`, you must set the `height="auto"` style as well, or your image will be distorted. Also keep in mind that the required `width` and `height` props can interact with your styling. If you use styling to modify an image's `width`, you must set the `height="auto"` style as well, or your image will be distorted.
### objectFit
Defines how the image will fit into its parent container when using `layout="fill"`.
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
Defines how the image is positioned within its parent element when using `layout="fill"`.
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 ### onLoadingComplete
A callback function that is invoked once the image is completely loaded and the [placeholder](#placeholder) has been removed. A callback function that is invoked once the image is completely loaded and the [placeholder](#placeholder) has been removed.
The `onLoadingComplete` function accepts one parameter, an object with the following properties: The callback function will be called with one argument, a reference to the underlying `<img>` element.
- [`naturalWidth`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalWidth) ### onLoad
- [`naturalHeight`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalHeight)
A callback function that is invoked when the image is loaded.
Note that the load event might occur before the placeholder is removed and the image is fully decoded.
Instead, use [`onLoadingComplete`](#onloadingcomplete).
### onError
A callback function that is invoked if the image fails to load.
### loading ### loading
@ -258,66 +254,6 @@ Try it out:
You can also [generate a solid color Data URL](https://png-pixel.com) to match the image. You can also [generate a solid color Data URL](https://png-pixel.com) to match the image.
### lazyBoundary
A string (with similar syntax to the margin property) that acts as the bounding box used to detect the intersection of the viewport with the image and trigger lazy [loading](#loading). Defaults to `"200px"`.
If the image is nested in a scrollable parent element other than the root document, you will also need to assign the [lazyRoot](#lazyroot) prop.
[Learn more](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/rootMargin)
### lazyRoot
A React [Ref](https://reactjs.org/docs/refs-and-the-dom.html) pointing to the scrollable parent element. Defaults to `null` (the document viewport).
The Ref must point to a DOM element or a React component that [forwards the Ref](https://reactjs.org/docs/forwarding-refs.html) to the underlying DOM element.
**Example pointing to a DOM element**
```jsx
import Image from 'next/image'
import React from 'react'
const Example = () => {
const lazyRoot = React.useRef(null)
return (
<div ref={lazyRoot} style={{ overflowX: 'scroll', width: '500px' }}>
<Image lazyRoot={lazyRoot} src="/one.jpg" width="500" height="500" />
<Image lazyRoot={lazyRoot} src="/two.jpg" width="500" height="500" />
</div>
)
}
```
**Example pointing to a React component**
```jsx
import Image from 'next/image'
import React from 'react'
const Container = React.forwardRef((props, ref) => {
return (
<div ref={ref} style={{ overflowX: 'scroll', width: '500px' }}>
{props.children}
</div>
)
})
const Example = () => {
const lazyRoot = React.useRef(null)
return (
<Container ref={lazyRoot}>
<Image lazyRoot={lazyRoot} src="/one.jpg" width="500" height="500" />
<Image lazyRoot={lazyRoot} src="/two.jpg" width="500" height="500" />
</Container>
)
}
```
[Learn more](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/root)
### unoptimized ### unoptimized
When true, the source image will be served as-is instead of changing quality, When true, the source image will be served as-is instead of changing quality,
@ -338,9 +274,7 @@ module.exports = {
Other properties on the `<Image />` component will be passed to the underlying Other properties on the `<Image />` component will be passed to the underlying
`img` element with the exception of the following: `img` element with the exception of the following:
- `srcSet`. Use - `srcSet`. Use [Device Sizes](#device-sizes) instead.
[Device Sizes](#device-sizes)
instead.
- `ref`. Use [`onLoadingComplete`](#onloadingcomplete) instead. - `ref`. Use [`onLoadingComplete`](#onloadingcomplete) instead.
- `decoding`. It is always `"async"`. - `decoding`. It is always `"async"`.
@ -409,43 +343,13 @@ module.exports = {
} }
``` ```
### 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`](#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/concepts/image-optimization?utm_source=next-site&utm_medium=docs&utm_campaign=next-website)
- [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`.
> Images can not be optimized at build time using [`next export`](/docs/advanced-features/static-html-export.md), only on-demand. To use `next/image` with `next export`, you will need to use a different loader than the default. [Read more in the discussion.](https://github.com/vercel/next.js/discussions/19065)
> 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.
## Advanced ## Advanced
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. 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.
### Device Sizes ### 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 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` component uses [`sizes`](#sizes) prop to ensure the correct image is served for user's device.
If no configuration is provided, the default below is used. If no configuration is provided, the default below is used.
@ -475,7 +379,7 @@ module.exports = {
### Acceptable Formats ### Acceptable Formats
The default [Image Optimization API](#loader-configuration) will automatically detect the browser's supported image formats via the request's `Accept` header. The default [Image Optimization API](#loader) will automatically detect the browser's supported image formats via the request's `Accept` header.
If the `Accept` head matches more than one of the configured formats, the first match in the array is used. Therefore, the array order matters. If there is no match (or the source image is [animated](#animated-images)), the Image Optimization API will fallback to the original image's format. If the `Accept` head matches more than one of the configured formats, the first match in the array is used. Therefore, the array order matters. If there is no match (or the source image is [animated](#animated-images)), the Image Optimization API will fallback to the original image's format.
@ -501,13 +405,15 @@ module.exports = {
> Note: AVIF generally takes 20% longer to encode but it compresses 20% smaller compared to WebP. This means that the first time an image is requested, it will typically be slower and then subsequent requests that are cached will be faster. > Note: AVIF generally takes 20% longer to encode but it compresses 20% smaller compared to WebP. This means that the first time an image is requested, it will typically be slower and then subsequent requests that are cached will be faster.
> Note: If you self-host with a Proxy/CDN in front of Next.js, you must configure the Proxy to forward the `Accept` header.
## Caching Behavior ## 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. 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 expired image is served stale immediately. Then the image is optimized again in the background (also called revalidation) and saved to the cache with the new expiration date. 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 expired image is served stale immediately. Then the image is optimized again in the background (also called revalidation) and saved to the cache with the new expiration date.
The cache status of an image can be determined by reading the value of the `x-nextjs-cache` (`x-vercel-cache` when deployed on Vercel) response header. The possible values are the following: The cache status of an image can be determined by reading the value of the `x-nextjs-cache` response header. The possible values are the following:
- `MISS` - the path is not in the cache (occurs at most once, on the first visit) - `MISS` - the path is not in the cache (occurs at most once, on the first visit)
- `STALE` - the path is in the cache but exceeded the revalidate time so it will be updated in the background - `STALE` - the path is in the cache but exceeded the revalidate time so it will be updated in the background
@ -568,10 +474,6 @@ module.exports = {
} }
``` ```
### Experimental "raw" layout mode
The `layout="raw"` experiment has been moved to a new module. Please use [`next/future/image`](/docs/api-reference/next/future/image.md) instead.
### Animated Images ### Animated Images
The default [loader](#loader) will automatically bypass Image Optimization for animated images and serve the image as-is. The default [loader](#loader) will automatically bypass Image Optimization for animated images and serve the image as-is.

View file

@ -1,27 +1,30 @@
--- ---
description: Try the latest Image Optimization with the new `next/future/image` component. description: Backwards compatible Image Optimization with the Legacy Image component.
--- ---
# next/future/image # next/legacy/image
<details>
<summary><b>Examples</b></summary>
<ul>
<li><a href="https://github.com/vercel/next.js/tree/canary/examples/image-legacy-component">Legacy Image Component</a></li>
</ul>
</details>
<details> <details>
<summary><b>Version History</b></summary> <summary><b>Version History</b></summary>
| Version | Changes | | Version | Changes |
| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | --------- | ------------------------------------------- |
| `v12.3.0` | `next/future/image` component stable. `remotePatterns` config stable. `unoptimized` config stable. `alt` property required. `onLoadingComplete` receives `<img>` | | `v13.0.0` | `next/image` renamed to `next/legacy/image` |
| `v12.2.4` | `fill` property added. |
| `v12.2.0` | Experimental `next/future/image` component introduced. |
</details> </details>
The `next/future/image` component improves both the performance and developer experience of `next/image` by using the native `<img>` element with better default behavior. Starting with Next.js 13, the `next/image` component was rewritten to improves both the performance and developer experience. In order to provide a backwards compatible upgrade solution, the old `next/image` was renamed to `next/legacy/image`.
This component uses browser native [lazy loading](https://caniuse.com/loading-lazy-attr), which may fallback to eager loading for older browsers before Safari 15.4. When using the blur-up placeholder, older browsers before Safari 12 will fallback to empty placeholder. When using styles with `width`/`height` of `auto`, it is possible to cause [Layout Shift](https://web.dev/cls/) on older browsers before Safari 15 that don't [preserve the aspect ratio](https://caniuse.com/mdn-html_elements_img_aspect_ratio_computed_from_attributes). For more details, see [this MDN video](https://www.youtube.com/watch?v=4-d_SoCHeWE).
## Comparison ## Comparison
Compared to `next/image`, the new `next/future/image` component has the following changes: Compared to `next/legacy/image`, the new `next/image` component has the following changes:
- Removes `<span>` wrapper around `<img>` in favor of [native computed aspect ratio](https://caniuse.com/mdn-html_elements_img_aspect_ratio_computed_from_attributes) - Removes `<span>` wrapper around `<img>` in favor of [native computed aspect ratio](https://caniuse.com/mdn-html_elements_img_aspect_ratio_computed_from_attributes)
- Adds support for canonical `style` prop - Adds support for canonical `style` prop
@ -35,111 +38,6 @@ Compared to `next/image`, the new `next/future/image` component has the followin
- Changed `alt` prop from optional to required - Changed `alt` prop from optional to required
- Changed `onLoadingComplete` callback to receive reference to `<img>` element - Changed `onLoadingComplete` callback to receive reference to `<img>` element
## Known Browser Bugs
- [Safari 15+](https://bugs.webkit.org/show_bug.cgi?id=243601) displays a gray border while loading. Possible solutions:
- Use CSS `@media not all and (min-resolution:.001dpcm) { img[loading="lazy"] { clip-path: inset(0.5px) } }`
- Use [`priority`](#priority) if the image is above the fold
- [Firefox 67+](https://bugzilla.mozilla.org/show_bug.cgi?id=1556156) displays a white background while loading progressive jpeg. Possible solutions:
- Enable [AVIF `formats`](#acceptable-formats)
- Use [`placeholder="blur"`](#placeholder)
## Migration
Although `layout` is not available, you can migrate `next/image` to `next/future/image` using a few props. The following code snippets compare the two components:
#### before: `next/image`
```jsx
import Image from 'next/image'
import img from '../img.png'
function Page() {
return <Image src={img} />
}
```
#### after: `next/future/image`
```jsx
import Image from 'next/future/image'
import img from '../img.png'
const css = { maxWidth: '100%', height: 'auto' }
function Page() {
return <Image src={img} style={css} />
}
```
#### before: `next/image`
```jsx
import Image from 'next/image'
import img from '../img.png'
function Page() {
return <Image src={img} layout="responsive" />
}
```
#### after: `next/future/image`
```jsx
import Image from 'next/future/image'
import img from '../img.png'
const css = { width: '100%', height: 'auto' }
function Page() {
return <Image src={img} sizes="100vw" style={css} />
}
```
#### before: `next/image`
```jsx
import Image from 'next/image'
import img from '../img.png'
function Page() {
return <Image src={img} layout="fill" />
}
```
#### after: `next/future/image`
```jsx
import Image from 'next/future/image'
import img from '../img.png'
function Page() {
return <Image src={img} sizes="100vw" fill />
}
```
#### before: `next/image`
```jsx
import Image from 'next/image'
import img from '../img.png'
function Page() {
return <Image src={img} layout="fixed" />
}
```
#### after: `next/future/image`
```jsx
import Image from 'next/future/image'
import img from '../img.png'
function Page() {
return <Image src={img} />
}
```
You can also use `className` instead of `style`.
## Required Props ## Required Props
The `<Image />` component requires the following properties. The `<Image />` component requires the following properties.
@ -150,39 +48,63 @@ Must be one of the following:
1. A [statically imported](/docs/basic-features/image-optimization.md#local-images) image file, 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, 2. A path string. This can be either an absolute external URL,
or an internal path depending on the [loader](#loader) prop. or an internal path depending on the [loader](#loader) prop or [loader configuration](#loader-configuration).
When using an external URL, you must add it to [remotePatterns](#remote-patterns) in `next.config.js`. When using an external URL, you must add it to
[remotePatterns](#remote-patterns) in
`next.config.js`.
### width ### width
The `width` property represents the _rendered_ width in pixels, so it will affect how large the image appears. The `width` property can represent either the _rendered_ width or _original_ width in pixels, depending on the [`layout`](#layout) and [`sizes`](#sizes) properties.
Required, except for [statically imported images](/docs/basic-features/image-optimization.md#local-images) or images with the [`fill` property](#fill). When using `layout="intrinsic"` or `layout="fixed"` the `width` property represents the _rendered_ width in pixels, so it will affect how large the image appears.
When using `layout="responsive"`, `layout="fill"`, the `width` property represents the _original_ width in pixels, so it will only affect the aspect ratio.
The `width` property is required, except for [statically imported images](/docs/basic-features/image-optimization.md#local-images), or those with `layout="fill"`.
### height ### height
The `height` property represents the _rendered_ height in pixels, so it will affect how large the image appears. The `height` property can represent either the _rendered_ height or _original_ height in pixels, depending on the [`layout`](#layout) and [`sizes`](#sizes) properties.
Required, except for [statically imported images](/docs/basic-features/image-optimization.md#local-images) or images with the [`fill` property](#fill). When using `layout="intrinsic"` or `layout="fixed"` the `height` property represents the _rendered_ height in pixels, so it will affect how large the image appears.
### alt When using `layout="responsive"`, `layout="fill"`, the `height` property represents the _original_ height in pixels, so it will only affect the aspect ratio.
The `alt` property is used to describe the image for screen readers and search engines. It is also the fallback text if images have been disabled or an error occurs while loading the image. The `height` property is required, except for [statically imported images](/docs/basic-features/image-optimization.md#local-images), or those with `layout="fill"`.
It should contain text that could replace the image [without changing the meaning of the page](https://html.spec.whatwg.org/multipage/images.html#general-guidelines). It is not meant to supplement the image and should not repeat information that is already provided in the captions above or below the image.
If the image is [purely decorative](https://html.spec.whatwg.org/multipage/images.html#a-purely-decorative-image-that-doesn't-add-any-information) or [not intended for the user](https://html.spec.whatwg.org/multipage/images.html#an-image-not-intended-for-the-user), the `alt` property should be an empty string (`alt=""`).
[Learn more](https://html.spec.whatwg.org/multipage/images.html#alt)
## Optional Props ## Optional Props
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. 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` | Has wrapper and sizer |
| --------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------- | --------------------- |
| `intrinsic` (default) | Scale *down* to fit width of container, up to image size | `1x`, `2x` (based on [imageSizes](#image-sizes)) | N/A | yes |
| `fixed` | Sized to `width` and `height` exactly | `1x`, `2x` (based on [imageSizes](#image-sizes)) | N/A | yes |
| `responsive` | Scale to fit width of container | `640w`, `750w`, ... `2048w`, `3840w` (based on [imageSizes](#image-sizes) and [deviceSizes](#device-sizes)) | `100vw` | yes |
| `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` | yes |
- [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.
- [Demo the `fixed` layout](https://image-component.nextjs.gallery/layout-fixed)
- When `fixed`, the image dimensions will not change as the viewport changes (no responsiveness) similar to the native `img` element.
- [Demo the `responsive` layout](https://image-component.nextjs.gallery/layout-responsive)
- When `responsive`, the image will scale the dimensions down for smaller viewports and scale up for larger viewports.
- Ensure the parent element uses `display: block` in their stylesheet.
- [Demo the `fill` layout](https://image-component.nextjs.gallery/layout-fill)
- When `fill`, the image will stretch both width and height to the dimensions of the parent element, provided the parent element is relative.
- This is usually paired with the [`objectFit`](#objectFit) property.
- Ensure the parent element has `position: relative` in their stylesheet.
- [Demo background image](https://image-component.nextjs.gallery/background)
### loader ### loader
A custom function used to resolve image URLs. 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).
A `loader` is a function returning a URL string for the image, given the following parameters: A `loader` is a function returning a URL string for the image, given the following parameters:
@ -193,7 +115,7 @@ A `loader` is a function returning a URL string for the image, given the followi
Here is an example of using a custom loader: Here is an example of using a custom loader:
```js ```js
import Image from 'next/future/image' import Image from 'next/legacy/image'
const myLoader = ({ src, width, quality }) => { const myLoader = ({ src, width, quality }) => {
return `https://example.com/${src}?w=${width}&q=${quality || 75}` return `https://example.com/${src}?w=${width}&q=${quality || 75}`
@ -212,38 +134,20 @@ const MyImage = (props) => {
} }
``` ```
### fill
A boolean that causes the image to fill the parent element instead of setting [`width`](#width) and [`height`](#height).
The parent element _must_ assign `position: "relative"`, `position: "fixed"`, or `position: "absolute"` style.
By default, the img element will automatically be assigned the `position: "absolute"` style.
The default image fit behavior will stretch the image to fit the container. You may prefer to set `object-fit: "contain"` for an image which is letterboxed to fit the container and preserve aspect ratio.
Alternatively, `object-fit: "cover"` will cause the image to fill the entire container and be cropped to preserve aspect ratio. For this to look correct, the `overflow: "hidden"` style should be assigned to the parent element.
See also:
- [position](https://developer.mozilla.org/en-US/docs/Web/CSS/position)
- [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit)
- [object-position](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position)
### sizes ### sizes
A string that provides information about how wide the image will be at different breakpoints. The value of `sizes` will greatly affect performance for images using [`fill`](#fill) or which are styled to have a responsive size. A string that provides information about how wide the image will be at different breakpoints. The value of `sizes` will greatly affect performance for images using `layout="responsive"` or `layout="fill"`. It will be ignored for images using `layout="intrinsic"` or `layout="fixed"`.
The `sizes` property serves two important purposes related to image performance: The `sizes` property serves two important purposes related to image performance:
First, the value of `sizes` is used by the browser to determine which size of the image to download, from `next/future/image`'s automatically-generated source set. When the browser chooses, it does not yet know the size of the image on the page, so it selects an image that is the same size or larger than the viewport. The `sizes` property allows you to tell the browser that the image will actually be smaller than full screen. If you don't specify a `sizes` value in an image with the `fill` property, a default value of `100vw` (full screen width) is used. First, the value of `sizes` is used by the browser to determine which size of the image to download, from `next/legacy/image`'s automatically-generated source set. When the browser chooses, it does not yet know the size of the image on the page, so it selects an image that is the same size or larger than the viewport. The `sizes` property allows you to tell the browser that the image will actually be smaller than full screen. If you don't specify a `sizes` value, a default value of `100vw` (full screen width) is used.
Second, the `sizes` property configures how `next/future/image` automatically generates an image source set. If no `sizes` value is present, a small source set is generated, suitable for a fixed-size image. If `sizes` is defined, a large source set is generated, suitable for a responsive image. If the `sizes` property includes sizes such as `50vw`, which represent a percentage of the viewport width, then the source set is trimmed to not include any values which are too small to ever be necessary. Second, the `sizes` value is parsed and used to trim the values in the automatically-created source set. If the `sizes` property includes sizes such as `50vw`, which represent a percentage of the viewport width, then the source set is trimmed to not include any values which are too small to ever be necessary.
For example, if you know your styling will cause an image to be full-width on mobile devices, in a 2-column layout on tablets, and a 3-column layout on desktop displays, you should include a sizes property such as the following: For example, if you know your styling will cause an image to be full-width on mobile devices, in a 2-column layout on tablets, and a 3-column layout on desktop displays, you should include a sizes property such as the following:
```js ```js
import Image from 'next/image' import Image from 'next/legacy/image'
const Example = () => ( const Example = () => (
<div className="grid-element"> <div className="grid-element">
<Image <Image
@ -266,7 +170,7 @@ Learn more about `srcset` and `sizes`:
### quality ### quality
The quality of the optimized image, an integer between `1` and `100`, where `100` is the best quality and therefore largest file size. 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 ### priority
@ -301,25 +205,30 @@ In some cases, you may need more advanced usage. The `<Image />` component optio
Allows [passing CSS styles](https://reactjs.org/docs/dom-elements.html#style) to the underlying image element. Allows [passing CSS styles](https://reactjs.org/docs/dom-elements.html#style) to the underlying image element.
Note that all `layout` modes apply their own styles to the image element, and these automatic styles take precedence over the `style` prop.
Also keep in mind that the required `width` and `height` props can interact with your styling. If you use styling to modify an image's `width`, you must set the `height="auto"` style as well, or your image will be distorted. Also keep in mind that the required `width` and `height` props can interact with your styling. If you use styling to modify an image's `width`, you must set the `height="auto"` style as well, or your image will be distorted.
### objectFit
Defines how the image will fit into its parent container when using `layout="fill"`.
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
Defines how the image is positioned within its parent element when using `layout="fill"`.
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 ### onLoadingComplete
A callback function that is invoked once the image is completely loaded and the [placeholder](#placeholder) has been removed. A callback function that is invoked once the image is completely loaded and the [placeholder](#placeholder) has been removed.
The callback function will be called with one argument, a reference to the underlying `<img>` element. The `onLoadingComplete` function accepts one parameter, an object with the following properties:
### onLoad - [`naturalWidth`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalWidth)
- [`naturalHeight`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalHeight)
A callback function that is invoked when the image is loaded.
Note that the load event might occur before the placeholder is removed and the image is fully decoded.
Instead, use [`onLoadingComplete`](#onloadingcomplete).
### onError
A callback function that is invoked if the image fails to load.
### loading ### loading
@ -355,6 +264,66 @@ Try it out:
You can also [generate a solid color Data URL](https://png-pixel.com) to match the image. You can also [generate a solid color Data URL](https://png-pixel.com) to match the image.
### lazyBoundary
A string (with similar syntax to the margin property) that acts as the bounding box used to detect the intersection of the viewport with the image and trigger lazy [loading](#loading). Defaults to `"200px"`.
If the image is nested in a scrollable parent element other than the root document, you will also need to assign the [lazyRoot](#lazyroot) prop.
[Learn more](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/rootMargin)
### lazyRoot
A React [Ref](https://reactjs.org/docs/refs-and-the-dom.html) pointing to the scrollable parent element. Defaults to `null` (the document viewport).
The Ref must point to a DOM element or a React component that [forwards the Ref](https://reactjs.org/docs/forwarding-refs.html) to the underlying DOM element.
**Example pointing to a DOM element**
```jsx
import Image from 'next/legacy/image'
import React from 'react'
const Example = () => {
const lazyRoot = React.useRef(null)
return (
<div ref={lazyRoot} style={{ overflowX: 'scroll', width: '500px' }}>
<Image lazyRoot={lazyRoot} src="/one.jpg" width="500" height="500" />
<Image lazyRoot={lazyRoot} src="/two.jpg" width="500" height="500" />
</div>
)
}
```
**Example pointing to a React component**
```jsx
import Image from 'next/legacy/image'
import React from 'react'
const Container = React.forwardRef((props, ref) => {
return (
<div ref={ref} style={{ overflowX: 'scroll', width: '500px' }}>
{props.children}
</div>
)
})
const Example = () => {
const lazyRoot = React.useRef(null)
return (
<Container ref={lazyRoot}>
<Image lazyRoot={lazyRoot} src="/one.jpg" width="500" height="500" />
<Image lazyRoot={lazyRoot} src="/two.jpg" width="500" height="500" />
</Container>
)
}
```
[Learn more](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/root)
### unoptimized ### unoptimized
When true, the source image will be served as-is instead of changing quality, When true, the source image will be served as-is instead of changing quality,
@ -375,7 +344,9 @@ module.exports = {
Other properties on the `<Image />` component will be passed to the underlying Other properties on the `<Image />` component will be passed to the underlying
`img` element with the exception of the following: `img` element with the exception of the following:
- `srcSet`. Use [Device Sizes](#device-sizes) instead. - `srcSet`. Use
[Device Sizes](#device-sizes)
instead.
- `ref`. Use [`onLoadingComplete`](#onloadingcomplete) instead. - `ref`. Use [`onLoadingComplete`](#onloadingcomplete) instead.
- `decoding`. It is always `"async"`. - `decoding`. It is always `"async"`.
@ -400,7 +371,7 @@ module.exports = {
} }
``` ```
> Note: The example above will ensure the `src` property of `next/future/image` must start with `https://example.com/account123/`. Any other protocol, hostname, port, or unmatched path will respond with 400 Bad Request. > Note: The example above will ensure the `src` property of `next/legacy/image` must start with `https://example.com/account123/`. Any other protocol, hostname, port, or unmatched path will respond with 400 Bad Request.
Below is another example of the `remotePatterns` property in the `next.config.js` file: Below is another example of the `remotePatterns` property in the `next.config.js` file:
@ -417,7 +388,7 @@ module.exports = {
} }
``` ```
> Note: The example above will ensure the `src` property of `next/future/image` must start with `https://img1.example.com` or `https://me.avatar.example.com` or any number of subdomains. Any other protocol or unmatched hostname will respond with 400 Bad Request. > Note: The example above will ensure the `src` property of `next/legacy/image` must start with `https://img1.example.com` or `https://me.avatar.example.com` or any number of subdomains. Any other protocol or unmatched hostname will respond with 400 Bad Request.
Wildcard patterns can be used for both `pathname` and `hostname` and have the following syntax: Wildcard patterns can be used for both `pathname` and `hostname` and have the following syntax:
@ -444,13 +415,43 @@ module.exports = {
} }
``` ```
### 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`](#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/concepts/image-optimization?utm_source=next-site&utm_medium=docs&utm_campaign=next-website)
- [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`](#loader) prop on the `next/legacy/image` component
If you need a different provider, you can use the [`loader`](#loader) prop with `next/legacy/image`.
> Images can not be optimized at build time using [`next export`](/docs/advanced-features/static-html-export.md), only on-demand. To use `next/legacy/image` with `next export`, you will need to use a different loader than the default. [Read more in the discussion.](https://github.com/vercel/next.js/discussions/19065)
> The `next/legacy/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.
## Advanced ## Advanced
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. 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.
### Device Sizes ### 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/future/image` component uses [`sizes`](#sizes) prop to ensure the correct image is served for user's device. 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/legacy/image` 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. If no configuration is provided, the default below is used.
@ -480,7 +481,7 @@ module.exports = {
### Acceptable Formats ### Acceptable Formats
The default [Image Optimization API](#loader) will automatically detect the browser's supported image formats via the request's `Accept` header. The default [Image Optimization API](#loader-configuration) will automatically detect the browser's supported image formats via the request's `Accept` header.
If the `Accept` head matches more than one of the configured formats, the first match in the array is used. Therefore, the array order matters. If there is no match (or the source image is [animated](#animated-images)), the Image Optimization API will fallback to the original image's format. If the `Accept` head matches more than one of the configured formats, the first match in the array is used. Therefore, the array order matters. If there is no match (or the source image is [animated](#animated-images)), the Image Optimization API will fallback to the original image's format.
@ -506,15 +507,13 @@ module.exports = {
> Note: AVIF generally takes 20% longer to encode but it compresses 20% smaller compared to WebP. This means that the first time an image is requested, it will typically be slower and then subsequent requests that are cached will be faster. > Note: AVIF generally takes 20% longer to encode but it compresses 20% smaller compared to WebP. This means that the first time an image is requested, it will typically be slower and then subsequent requests that are cached will be faster.
> Note: If you self-host with a Proxy/CDN in front of Next.js, you must configure the Proxy to forward the `Accept` header.
## Caching Behavior ## 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. 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 expired image is served stale immediately. Then the image is optimized again in the background (also called revalidation) and saved to the cache with the new expiration date. 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 expired image is served stale immediately. Then the image is optimized again in the background (also called revalidation) and saved to the cache with the new expiration date.
The cache status of an image can be determined by reading the value of the `x-nextjs-cache` response header. The possible values are the following: The cache status of an image can be determined by reading the value of the `x-nextjs-cache` (`x-vercel-cache` when deployed on Vercel) response header. The possible values are the following:
- `MISS` - the path is not in the cache (occurs at most once, on the first visit) - `MISS` - the path is not in the cache (occurs at most once, on the first visit)
- `STALE` - the path is in the cache but exceeded the revalidate time so it will be updated in the background - `STALE` - the path is in the cache but exceeded the revalidate time so it will be updated in the background

View file

@ -28,12 +28,6 @@ To add an image to your application, import the [`next/image`](/docs/api-referen
import Image from 'next/image' import Image from 'next/image'
``` ```
Alternatively, you can import [`next/future/image`](/docs/api-reference/next/future/image.md) if you need a component much closer to the native `<img>` element:
```jsx
import Image from 'next/future/image'
```
Now, you can define the `src` for your image (either local or remote). Now, you can define the `src` for your image (either local or remote).
### Local Images ### Local Images
@ -151,15 +145,15 @@ Because `next/image` is designed to guarantee good performance results, it canno
1. Automatically, using a [static import](#local-images) 1. Automatically, using a [static import](#local-images)
2. Explicitly, by including a [`width`](/docs/api-reference/next/image.md#width) and [`height`](/docs/api-reference/next/image.md#height) property 2. Explicitly, by including a [`width`](/docs/api-reference/next/image.md#width) and [`height`](/docs/api-reference/next/image.md#height) property
3. Implicitly, by using [`layout="fill"`](/docs/api-reference/next/image.md#layout) which causes the image to expand to fill its parent element. 3. Implicitly, by using [fill](/docs/api-reference/next/image.md#fill) which causes the image to expand to fill its parent element.
> ### What if I don't know the size of my images? > ### What if I don't know the size of my images?
> >
> If you are accessing images from a source without knowledge of the images' sizes, there are several things you can do: > If you are accessing images from a source without knowledge of the images' sizes, there are several things you can do:
> >
> **Use `layout='fill'`** > **Use `fill``**
> >
> The `fill` layout mode allows your image to be sized by its parent element. Consider using CSS to give the image's parent element space on the page, then using the [`objectFit property`](/docs/api-reference/next/image.md#objectfit) with `fill`, `contain`, or `cover`, along with the [`objectPosition property`](/docs/api-reference/next/image.md#objectposition) to define how the image should occupy that space. > The [`fill`](/docs/api-reference/next/image#fill) prop allows your image to be sized by its parent element. Consider using CSS to give the image's parent element space on the page along [`sizes`](/docs/api-reference/next/image#sizes) prop to match any media query break points. You can also use [`object-fit`](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) with `fill`, `contain`, or `cover`, and [`object-position`](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position) to define how the image should occupy that space.
> >
> **Normalize your images** > **Normalize your images**
> >
@ -175,27 +169,21 @@ If none of the suggested methods works for sizing your images, the `next/image`
> Note: Many of the styling issues listed below can be solved with [`next/future/image`](/docs/api-reference/next/future/image.md) > Note: Many of the styling issues listed below can be solved with [`next/future/image`](/docs/api-reference/next/future/image.md)
Styling the Image component is not that different from styling a normal `<img>` element, but there are a few guidelines to keep in mind: Styling the Image component is similar to styling a normal `<img>` element, but there are a few guidelines to keep in mind:
**Pick the correct layout mode** **Use `className` or `style`, not `styled-jsx`**
The image component has several different [layout modes](/docs/api-reference/next/image.md#layout) that define how it is sized on the page. If the styling of your image isn't turning out the way you want, consider experimenting with other layout modes. In most cases, we recommend using the `className` prop. This can be an imported [CSS Module](/docs/basic-features/built-in-css-support.md#adding-component-level-css), a [global stylesheet](/docs/basic-features/built-in-css-support#adding-a-global-stylesheet), etc.
**Target the image with className, not based on DOM structure** You can also use the `style` prop to assign inline styles.
For most layout modes, the Image component will have a DOM structure of one `<img>` tag wrapped by exactly one `<span>`. For some modes, it may also have a sibling `<span>` for spacing. These additional `<span>` elements are critical to allow the component to prevent layout shifts. You cannot use [styled-jsx](/docs/basic-features/built-in-css-support.md#css-in-js) because it's scoped to the current component (unless you mark the style as `global`).
The recommended way to style the inner `<img>` is to set the `className` prop on the Image component to the value of an imported [CSS Module](/docs/basic-features/built-in-css-support.md#adding-component-level-css). The value of `className` will be automatically applied to the underlying `<img>` element. **When using `fill`, the parent element must have `position: relative`**
Alternatively, you can import a [global stylesheet](/docs/basic-features/built-in-css-support#adding-a-global-stylesheet) and manually set the `className` prop to the same name used in the global stylesheet.
You cannot use [styled-jsx](/docs/basic-features/built-in-css-support.md#css-in-js) because it's scoped to the current component.
**When using `layout='fill'`, the parent element must have `position: relative`**
This is necessary for the proper rendering of the image element in that layout mode. This is necessary for the proper rendering of the image element in that layout mode.
**When using `layout='responsive'`, the parent element must have `display: block`** **When using `fill`, the parent element must have `display: block`**
This is the default for `<div>` elements but should be specified otherwise. This is the default for `<div>` elements but should be specified otherwise.
@ -205,7 +193,7 @@ This is the default for `<div>` elements but should be specified otherwise.
### Styling Examples ### Styling Examples
For examples of the Image component used with the various fill modes, see the [Image component example app](https://image-component.nextjs.gallery/). For examples of the Image component used with the various styles, see the [Image component example app](https://image-component.nextjs.gallery).
## Configuration ## Configuration

View file

@ -427,8 +427,14 @@
} }
}, },
{ {
"title": "next/future/image", "path": "/docs/api-reference/next/future/image",
"path": "/docs/api-reference/next/future/image.md" "redirect": {
"destination": "/docs/api-reference/next/image"
}
},
{
"title": "next/legacy/image",
"path": "/docs/api-reference/next/legacy/image.md"
}, },
{ {
"title": "Edge Runtime", "title": "Edge Runtime",

View file

@ -1,7 +1,14 @@
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
module.exports = { module.exports = {
images: { images: {
domains: ['assets.vercel.com'],
formats: ['image/avif', 'image/webp'], formats: ['image/avif', 'image/webp'],
remotePatterns: [
{
protocol: 'https',
hostname: 'assets.vercel.com',
port: '',
pathname: '/image/upload/**',
},
],
}, },
} }

View file

@ -6,7 +6,7 @@
"start": "next start" "start": "next start"
}, },
"dependencies": { "dependencies": {
"next": "latest", "next": "canary",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0" "react-dom": "^18.2.0"
}, },

View file

@ -1,6 +1,7 @@
import Image from 'next/image' import Image from 'next/image'
import ViewSource from '../components/view-source' import ViewSource from '../components/view-source'
import styles from '../styles.module.css' import styles from '../styles.module.css'
import mountains from '../public/mountains.jpg'
const BackgroundPage = () => ( const BackgroundPage = () => (
<div> <div>
@ -8,10 +9,14 @@ const BackgroundPage = () => (
<div className={styles.bgWrap}> <div className={styles.bgWrap}>
<Image <Image
alt="Mountains" alt="Mountains"
src="/mountains.jpg" src={mountains}
layout="fill" placeholder="blur"
objectFit="cover"
quality={100} quality={100}
fill
sizes="100vw"
style={{
objectFit: 'cover',
}}
/> />
</div> </div>
<p className={styles.bgText}> <p className={styles.bgText}>

View file

@ -27,6 +27,10 @@ const Color = () => (
blurDataURL={rgbDataURL(237, 181, 6)} blurDataURL={rgbDataURL(237, 181, 6)}
width={750} width={750}
height={1000} height={1000}
style={{
maxWidth: '100%',
height: 'auto',
}}
/> />
<Image <Image
alt="Cat" alt="Cat"
@ -35,6 +39,10 @@ const Color = () => (
blurDataURL={rgbDataURL(2, 129, 210)} blurDataURL={rgbDataURL(2, 129, 210)}
width={750} width={750}
height={1000} height={1000}
style={{
maxWidth: '100%',
height: 'auto',
}}
/> />
</div> </div>
) )

View file

@ -0,0 +1,46 @@
import Image from 'next/image'
import ViewSource from '../components/view-source'
import mountains from '../public/mountains.jpg'
const Fill = () => (
<div>
<ViewSource pathname="pages/layout-fill.tsx" />
<h1>Image Component With Layout Fill</h1>
<div style={{ position: 'relative', width: '300px', height: '500px' }}>
<Image
alt="Mountains"
src={mountains}
fill
sizes="100vw"
style={{
objectFit: 'cover',
}}
/>
</div>
<div style={{ position: 'relative', width: '300px', height: '500px' }}>
<Image
alt="Mountains"
src={mountains}
fill
sizes="100vw"
style={{
objectFit: 'contain',
}}
/>
</div>
<div style={{ position: 'relative', width: '300px', height: '500px' }}>
<Image
alt="Mountains"
src={mountains}
quality={100}
fill
sizes="100vw"
style={{
objectFit: 'none',
}}
/>
</div>
</div>
)
export default Fill

View file

@ -29,70 +29,40 @@ const Index = () => (
images on-demand as the browser requests them. images on-demand as the browser requests them.
</p> </p>
<hr className={styles.hr} /> <hr className={styles.hr} />
<h2 id="layout">Layout</h2> <h2 id="examples">Examples</h2>
<p> <p>
The <Code>layout</Code> property tells the image to respond differently Try it the examples below (you may need to disable cache in dev tools to
depending on the device size or the container size. see the effect if you already visited):
</p>
<p>
Select a layout below and try resizing the window or rotating your
device to see how the image reacts.
</p> </p>
<ul> <ul>
<li> <li>
<Link href="/layout-intrinsic"> <Link href="/responsive">
<a>layout="intrinsic"</a> <a>Responsive to viewport</a>
</Link> </Link>
</li> </li>
<li> <li>
<Link href="/layout-responsive"> <Link href="/fill">
<a>layout="responsive"</a> <a>Fill dimensions of parent element</a>
</Link> </Link>
</li> </li>
<li>
<Link href="/layout-fixed">
<a>layout="fixed"</a>
</Link>
</li>
<li>
<Link href="/layout-fill">
<a>layout="fill"</a>
</Link>
</li>
<li>
<Link href="/background">
<a>background demo</a>
</Link>
</li>
</ul>
<hr className={styles.hr} />
<h2 id="placeholder">Placeholder</h2>
<p>
The <Code>placeholder</Code> property tells the image what to do while
loading.
</p>
<p>
You can optionally enable a blur-up placeholder while the high
resolution image loads.
</p>
<p>
Try it out below (you may need to disable cache in dev tools to see the
effect if you already visited):
</p>
<ul>
<li> <li>
<Link href="/placeholder"> <Link href="/placeholder">
<a>placeholder="blur"</a> <a>Blur-up placeholder</a>
</Link> </Link>
</li> </li>
<li> <li>
<Link href="/shimmer"> <Link href="/shimmer">
<a>placeholder="blur" with animated shimmer blurDataURL</a> <a>Shimmer placeholder</a>
</Link> </Link>
</li> </li>
<li> <li>
<Link href="/color"> <Link href="/color">
<a>placeholder="blur" with solid color blurDataURL</a> <a>Color placeholder</a>
</Link>
</li>
<li>
<Link href="/background">
<a>Text on background image</a>
</Link> </Link>
</li> </li>
</ul> </ul>
@ -106,7 +76,16 @@ const Index = () => (
This image is intentionally large so you have to scroll down to the next This image is intentionally large so you have to scroll down to the next
image. image.
</p> </p>
<Image alt="Vercel logo" src={vercel} width={1000} height={1000} /> <Image
alt="Vercel logo"
src={vercel}
width={1000}
height={1000}
style={{
maxWidth: '100%',
height: 'auto',
}}
/>
<hr className={styles.hr} /> <hr className={styles.hr} />
<h2 id="external">External Image</h2> <h2 id="external">External Image</h2>
<p> <p>
@ -114,14 +93,18 @@ const Index = () => (
<Code>assets.vercel.com</Code>. <Code>assets.vercel.com</Code>.
</p> </p>
<p> <p>
External domains must be configured in <Code>next.config.js</Code> using External images must be configured in <Code>next.config.js</Code> using
the <Code>domains</Code> property. the <Code>remotePatterns</Code> property.
</p> </p>
<Image <Image
alt="Next.js logo" alt="Next.js logo"
src="https://assets.vercel.com/image/upload/v1538361091/repositories/next-js/next-js-bg.png" src="https://assets.vercel.com/image/upload/v1538361091/repositories/next-js/next-js-bg.png"
width={1200} width={1200}
height={400} height={400}
style={{
maxWidth: '100%',
height: 'auto',
}}
/> />
<hr className={styles.hr} /> <hr className={styles.hr} />
<h2 id="more">Learn More</h2> <h2 id="more">Learn More</h2>

View file

@ -12,6 +12,10 @@ const PlaceholderBlur = () => (
placeholder="blur" placeholder="blur"
width={700} width={700}
height={475} height={475}
style={{
maxWidth: '100%',
height: 'auto',
}}
/> />
</div> </div>
) )

View file

@ -0,0 +1,23 @@
import Image from 'next/image'
import ViewSource from '../components/view-source'
import mountains from '../public/mountains.jpg'
const Responsive = () => (
<div>
<ViewSource pathname="pages/layout-responsive.tsx" />
<h1>Image Component With Layout Responsive</h1>
<Image
alt="Mountains"
src={mountains}
width={700}
height={475}
sizes="100vw"
style={{
width: '100%',
height: 'auto',
}}
/>
</div>
)
export default Responsive

View file

@ -31,6 +31,10 @@ const Shimmer = () => (
blurDataURL={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} blurDataURL={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`}
width={700} width={700}
height={475} height={475}
style={{
maxWidth: '100%',
height: 'auto',
}}
/> />
</div> </div>
) )

View file

@ -12,7 +12,8 @@
"module": "esnext", "module": "esnext",
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"jsx": "preserve" "jsx": "preserve",
"moduleResolution": "node"
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"] "exclude": ["node_modules"]

View file

@ -0,0 +1,36 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

View file

@ -0,0 +1,29 @@
# Image Component Example
This example shows how to use the [Image Component in Next.js](https://nextjs.org/docs/api-reference/next/image) serve optimized, responsive images.
The index page ([`pages/index.js`](pages/index.js)) has a couple images, one internal image and one external image. In [`next.config.js`](next.config.js), the `domains` property is used to enable external images. The other pages demonstrate the different layouts. Run or deploy the app to see how it works!
## Live demo
[https://image-component.nextjs.gallery/](https://image-component.nextjs.gallery/)
## Deploy your own
Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example) or preview live with [StackBlitz](https://stackblitz.com/github/vercel/next.js/tree/canary/examples/image-legacy-component)
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/image-component&project-name=image-component&repository-name=image-legacy-component)
## How to use
Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init), [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/), or [pnpm](https://pnpm.io) to bootstrap the example:
```bash
npx create-next-app --example image-component image-app
# or
yarn create next-app --example image-component image-app
# or
pnpm create next-app --example image-component image-app
```
Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)).

View file

@ -0,0 +1,19 @@
body {
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
margin: 0;
padding: 0;
background: black;
color: white;
}
a {
cursor: pointer;
color: #0076ff;
text-decoration: none;
transition: all 0.2s ease;
border-bottom: 1px solid black;
}
a:hover {
border-bottom: 1px solid #0076ff;
}

View file

@ -0,0 +1,48 @@
.svg {
position: absolute;
top: 0;
right: 0;
}
.arm {
transform-origin: 130px 106px;
}
.svg:hover .arm {
animation: wave 560ms ease-in-out;
}
@keyframes wave {
0% {
transform: rotate(0deg);
}
20% {
transform: rotate(-25deg);
}
40% {
transform: rotate(10deg);
}
60% {
transform: rotate(-25deg);
}
80% {
transform: rotate(10deg);
}
100% {
transform: rotate(0deg);
}
}
@media (max-width: 500px) {
.svg:hover .arm {
animation: none;
}
.svg:hover .arm {
animation: wave 560ms ease-in-out;
}
}

View file

@ -0,0 +1,30 @@
import styles from './view-source.module.css'
type ViewSourceProps = {
pathname: string
}
const ViewSource = ({ pathname }: ViewSourceProps) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="80"
height="80"
viewBox="0 0 250 250"
fill="#151513"
className={styles.svg}
>
<a
title="View Source"
href={`https://github.com/vercel/next.js/tree/canary/examples/image-legacy-component/${pathname}`}
>
<path d="M0 0l115 115h15l12 27 108 108V0z" fill="#fff" />
<path
className={styles.arm}
d="M128 109c-15-9-9-19-9-19 3-7 2-11 2-11-1-7 3-2 3-2 4 5 2 11 2 11-3 10 5 15 9 16"
/>
<path d="M115 115s4 2 5 0l14-14c3-2 6-3 8-3-8-11-15-24 2-41 5-5 10-7 16-7 1-2 3-7 12-11 0 0 5 3 7 16 4 2 8 5 12 9s7 8 9 12c14 3 17 7 17 7-4 8-9 11-11 11 0 6-2 11-7 16-16 16-30 10-41 2 0 3-1 7-5 11l-12 11c-1 1 1 5 1 5z" />
</a>
</svg>
)
export default ViewSource

View file

@ -0,0 +1,14 @@
/** @type {import('next').NextConfig} */
module.exports = {
images: {
formats: ['image/avif', 'image/webp'],
remotePatterns: [
{
protocol: 'https',
hostname: 'assets.vercel.com',
port: '',
pathname: '/image/upload/**',
},
],
},
}

View file

@ -0,0 +1,18 @@
{
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "canary",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/node": "18.7.14",
"@types/react": "16.9.17",
"typescript": "4.8.2"
}
}

View file

@ -0,0 +1,6 @@
import type { AppProps } from 'next/app'
import '../app.css'
export default function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}

View file

@ -0,0 +1,25 @@
import Image from 'next/legacy/image'
import ViewSource from '../components/view-source'
import styles from '../styles.module.css'
const BackgroundPage = () => (
<div>
<ViewSource pathname="pages/background.tsx" />
<div className={styles.bgWrap}>
<Image
alt="Mountains"
src="/mountains.jpg"
layout="fill"
objectFit="cover"
quality={100}
/>
</div>
<p className={styles.bgText}>
Image Component
<br />
as a Background
</p>
</div>
)
export default BackgroundPage

View file

@ -0,0 +1,42 @@
import Image from 'next/legacy/image'
import ViewSource from '../components/view-source'
// Pixel GIF code adapted from https://stackoverflow.com/a/33919020/266535
const keyStr =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
const triplet = (e1: number, e2: number, e3: number) =>
keyStr.charAt(e1 >> 2) +
keyStr.charAt(((e1 & 3) << 4) | (e2 >> 4)) +
keyStr.charAt(((e2 & 15) << 2) | (e3 >> 6)) +
keyStr.charAt(e3 & 63)
const rgbDataURL = (r: number, g: number, b: number) =>
`data:image/gif;base64,R0lGODlhAQABAPAA${
triplet(0, r, g) + triplet(b, 255, 255)
}/yH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==`
const Color = () => (
<div>
<ViewSource pathname="pages/color.tsx" />
<h1>Image Component With Color Data URL</h1>
<Image
alt="Dog"
src="/dog.jpg"
placeholder="blur"
blurDataURL={rgbDataURL(237, 181, 6)}
width={750}
height={1000}
/>
<Image
alt="Cat"
src="/cat.jpg"
placeholder="blur"
blurDataURL={rgbDataURL(2, 129, 210)}
width={750}
height={1000}
/>
</div>
)
export default Color

View file

@ -0,0 +1,142 @@
import styles from '../styles.module.css'
import Image from 'next/legacy/image'
import Link from 'next/link'
import ViewSource from '../components/view-source'
import vercel from '../public/vercel.png'
import type { PropsWithChildren } from 'react'
const Code = (props: PropsWithChildren<{}>) => (
<code className={styles.inlineCode} {...props} />
)
const Index = () => (
<div className={styles.container}>
<ViewSource pathname="pages/index.tsx" />
<div className={styles.card}>
<h1>Image Component with Next.js</h1>
<p>
This page demonstrates the usage of the{' '}
<a href="https://nextjs.org/docs/api-reference/next/legacy/image">
next/legacy/image
</a>{' '}
component with live examples.
</p>
<p>
This component is designed to{' '}
<a href="https://nextjs.org/docs/basic-features/image-optimization">
automatically optimize
</a>{' '}
images on-demand as the browser requests them.
</p>
<hr className={styles.hr} />
<h2 id="layout">Layout</h2>
<p>
External images must be configured in <Code>next.config.js</Code> using
the <Code>remotePatterns</Code> property.
</p>
<p>
Select a layout below and try resizing the window or rotating your
device to see how the image reacts.
</p>
<ul>
<li>
<Link href="/layout-intrinsic">
<a>layout="intrinsic"</a>
</Link>
</li>
<li>
<Link href="/layout-responsive">
<a>layout="responsive"</a>
</Link>
</li>
<li>
<Link href="/layout-fixed">
<a>layout="fixed"</a>
</Link>
</li>
<li>
<Link href="/layout-fill">
<a>layout="fill"</a>
</Link>
</li>
<li>
<Link href="/background">
<a>background demo</a>
</Link>
</li>
</ul>
<hr className={styles.hr} />
<h2 id="placeholder">Placeholder</h2>
<p>
The <Code>placeholder</Code> property tells the image what to do while
loading.
</p>
<p>
You can optionally enable a blur-up placeholder while the high
resolution image loads.
</p>
<p>
Try it out below (you may need to disable cache in dev tools to see the
effect if you already visited):
</p>
<ul>
<li>
<Link href="/placeholder">
<a>placeholder="blur"</a>
</Link>
</li>
<li>
<Link href="/shimmer">
<a>placeholder="blur" with animated shimmer blurDataURL</a>
</Link>
</li>
<li>
<Link href="/color">
<a>placeholder="blur" with solid color blurDataURL</a>
</Link>
</li>
</ul>
<hr className={styles.hr} />
<h2 id="internal">Internal Image</h2>
<p>
The following is an example of a reference to an internal image from the{' '}
<Code>public</Code> directory.
</p>
<p>
This image is intentionally large so you have to scroll down to the next
image.
</p>
<Image alt="Vercel logo" src={vercel} width={1000} height={1000} />
<hr className={styles.hr} />
<h2 id="external">External Image</h2>
<p>
The following is an example of a reference to an external image at{' '}
<Code>assets.vercel.com</Code>.
</p>
<p>
External images must be configured in <Code>next.config.js</Code> using
the <Code>remotePatterns</Code> property.
</p>
<Image
alt="Next.js logo"
src="https://assets.vercel.com/image/upload/v1538361091/repositories/next-js/next-js-bg.png"
width={1200}
height={400}
/>
<hr className={styles.hr} />
<h2 id="more">Learn More</h2>
<p>
You can optionally configure a cloud provider, device sizes, and more!
</p>
<p>
Checkout the{' '}
<a href="https://nextjs.org/docs/basic-features/image-optimization">
Image Optimization documentation
</a>{' '}
to learn more.
</p>
</div>
</div>
)
export default Index

View file

@ -1,4 +1,4 @@
import Image from 'next/image' import Image from 'next/legacy/image'
import ViewSource from '../components/view-source' import ViewSource from '../components/view-source'
import mountains from '../public/mountains.jpg' import mountains from '../public/mountains.jpg'

View file

@ -1,4 +1,4 @@
import Image from 'next/image' import Image from 'next/legacy/image'
import ViewSource from '../components/view-source' import ViewSource from '../components/view-source'
import mountains from '../public/mountains.jpg' import mountains from '../public/mountains.jpg'

View file

@ -1,4 +1,4 @@
import Image from 'next/image' import Image from 'next/legacy/image'
import ViewSource from '../components/view-source' import ViewSource from '../components/view-source'
import mountains from '../public/mountains.jpg' import mountains from '../public/mountains.jpg'

View file

@ -1,4 +1,4 @@
import Image from 'next/image' import Image from 'next/legacy/image'
import ViewSource from '../components/view-source' import ViewSource from '../components/view-source'
import mountains from '../public/mountains.jpg' import mountains from '../public/mountains.jpg'

View file

@ -0,0 +1,19 @@
import Image from 'next/legacy/image'
import ViewSource from '../components/view-source'
import mountains from '../public/mountains.jpg'
const PlaceholderBlur = () => (
<div>
<ViewSource pathname="pages/placeholder.tsx" />
<h1>Image Component With Placeholder Blur</h1>
<Image
alt="Mountains"
src={mountains}
placeholder="blur"
width={700}
height={475}
/>
</div>
)
export default PlaceholderBlur

View file

@ -0,0 +1,38 @@
import Image from 'next/legacy/image'
import ViewSource from '../components/view-source'
const shimmer = (w: number, h: number) => `
<svg width="${w}" height="${h}" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="g">
<stop stop-color="#333" offset="20%" />
<stop stop-color="#222" offset="50%" />
<stop stop-color="#333" offset="70%" />
</linearGradient>
</defs>
<rect width="${w}" height="${h}" fill="#333" />
<rect id="r" width="${w}" height="${h}" fill="url(#g)" />
<animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" />
</svg>`
const toBase64 = (str: string) =>
typeof window === 'undefined'
? Buffer.from(str).toString('base64')
: window.btoa(str)
const Shimmer = () => (
<div>
<ViewSource pathname="pages/shimmer.tsx" />
<h1>Image Component With Shimmer Data URL</h1>
<Image
alt="Mountains"
src="/mountains.jpg"
placeholder="blur"
blurDataURL={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`}
width={700}
height={475}
/>
</div>
)
export default Shimmer

Binary file not shown.

After

Width:  |  Height:  |  Size: 505 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View file

@ -0,0 +1,50 @@
.container {
padding: 4rem 1rem;
}
.container p {
margin: 1.5rem 0;
}
.card {
max-width: 60rem;
box-shadow: -10px 10px 80px rgba(255, 255, 255, 0.1);
border: 1px solid #333;
border-radius: 8px;
padding: 2rem;
margin: 0 auto;
}
.inlineCode {
color: #be00ff;
font-size: 16px;
white-space: pre-wrap;
}
.inlineCode::before,
.inlineCode::after {
content: '`';
}
.hr {
border: 0;
border-top: 1px solid #333;
margin: 1.5rem 0;
}
.bgWrap {
position: fixed;
height: 100vh;
width: 100vw;
overflow: hidden;
z-index: -1;
}
.bgText {
margin: 0;
font-size: 2rem;
line-height: 3rem;
text-align: center;
padding-top: 40vh;
text-shadow: 1px 1px 1px #3c5c5e;
}

View file

@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"incremental": true,
"esModuleInterop": true,
"module": "esnext",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}

View file

@ -124,6 +124,14 @@ const TRANSFORMER_INQUIRER_CHOICES = [
name: 'new-link: Ensures your <Link> usage is backwards compatible. Used in combination with experimental newNextLinkBehavior', name: 'new-link: Ensures your <Link> usage is backwards compatible. Used in combination with experimental newNextLinkBehavior',
value: 'new-link', value: 'new-link',
}, },
{
name: 'next-image-to-legacy-image: safely migrate Next.js 10, 11, 12 applications importing `next/image` to the renamed `next/legacy/image` import in Next.js 13',
value: 'next-image-to-legacy-image',
},
{
name: 'next-image-experimental (experimental): dangerously migrates from `next/legacy/image` to the new `next/image` by adding inline styles and removing unused props',
value: 'next-image-experimental',
},
] ]
function expandFilePathsIfNeeded(filesBeforeExpansion) { function expandFilePathsIfNeeded(filesBeforeExpansion) {

View file

@ -8,8 +8,8 @@ export default function Home() {
return ( return (
<div> <div>
<h1>Upgrade</h1> <h1>Upgrade</h1>
<Image src="/test.jpg" width="200" height="300" /> <Image src="/test.jpg" width="100" height="200" />
<Image src="/test.jpg" width="200" height="300" layout="intrinsic" /> <Image src="/test.jpg" width="300" height="400" layout="intrinsic" />
<Image src="/test.jpg" width="200" height="300" layout="responsive" /> <Image src="/test.jpg" width="200" height="300" layout="responsive" />
<Image src="/test.jpg" width="200" height="300" layout="fixed" /> <Image src="/test.jpg" width="200" height="300" layout="fixed" />
<div style={{ position: 'relative', width: '300px', height: '500px' }}> <div style={{ position: 'relative', width: '300px', height: '500px' }}>

View file

@ -8,11 +8,18 @@ export default function Home() {
return ( return (
<div> <div>
<h1>Upgrade</h1> <h1>Upgrade</h1>
<Image src="/test.jpg" width="200" height="300" />
<Image <Image
src="/test.jpg" src="/test.jpg"
width="200" width="100"
height="300" height="200"
style={{
maxWidth: "100%",
height: "auto"
}} />
<Image
src="/test.jpg"
width="300"
height="400"
style={{ style={{
maxWidth: "100%", maxWidth: "100%",
height: "auto" height: "auto"

View file

@ -34,7 +34,7 @@ function findAndReplaceProps(
el.value.openingElement.name.name === tagName el.value.openingElement.name.name === tagName
) )
.forEach((el) => { .forEach((el) => {
let layout = 'intrisic' let layout = 'intrinsic'
let objectFit = null let objectFit = null
let objectPosition = null let objectPosition = null
let styleExpProps = [] let styleExpProps = []
@ -43,21 +43,20 @@ function findAndReplaceProps(
if (a.type !== 'JSXAttribute') { if (a.type !== 'JSXAttribute') {
return true return true
} }
// TODO: hanlde case when not Literal
if (a.value?.type === 'Literal') { if (a.name.name === 'layout' && 'value' in a.value) {
if (a.name.name === 'layout') { layout = String(a.value.value)
layout = String(a.value.value) return false
return false
}
if (a.name.name === 'objectFit') {
objectFit = String(a.value.value)
return false
}
if (a.name.name === 'objectPosition') {
objectPosition = String(a.value.value)
return false
}
} }
if (a.name.name === 'objectFit' && 'value' in a.value) {
objectFit = String(a.value.value)
return false
}
if (a.name.name === 'objectPosition' && 'value' in a.value) {
objectPosition = String(a.value.value)
return false
}
if (a.name.name === 'style') { if (a.name.name === 'style') {
if ( if (
a.value?.type === 'JSXExpressionContainer' && a.value?.type === 'JSXExpressionContainer' &&

View file

@ -306,7 +306,7 @@ function handleLoading(
img.getBoundingClientRect().width / window.innerWidth img.getBoundingClientRect().width / window.innerWidth
if (widthViewportRatio < 0.6) { if (widthViewportRatio < 0.6) {
warnOnce( warnOnce(
`Image with src "${src}" has "fill" but is missing "sizes" prop. Please add it to improve page performance. Read more: https://nextjs.org/docs/api-reference/next/future/image#sizes` `Image with src "${src}" has "fill" but is missing "sizes" prop. Please add it to improve page performance. Read more: https://nextjs.org/docs/api-reference/next/image#sizes`
) )
} }
} }

View file

@ -864,7 +864,7 @@ export default function Image({
// https://web.dev/lcp/#measure-lcp-in-javascript // https://web.dev/lcp/#measure-lcp-in-javascript
warnOnce( warnOnce(
`Image with src "${lcpImage.src}" was detected as the Largest Contentful Paint (LCP). Please add the "priority" property if this image is above the fold.` + `Image with src "${lcpImage.src}" was detected as the Largest Contentful Paint (LCP). Please add the "priority" property if this image is above the fold.` +
`\nRead more: https://nextjs.org/docs/api-reference/next/image#priority` `\nRead more: https://nextjs.org/docs/api-reference/next/legacy/image#priority`
) )
} }
} }