Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Update next/image docs and examples #41434

Merged
merged 16 commits into from Oct 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
92 changes: 91 additions & 1 deletion docs/advanced-features/codemods.md
Expand Up @@ -64,7 +64,97 @@ Dangerously migrates from `next/legacy/image` to the new `next/image` by adding
- Removes `objectPosition` prop and adds `style`
- Removes `lazyBoundary` prop
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section still says (experimental) - should we update that and link in upgrade guide?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@leerob This codemod is experimental and will remain that way forever. Because static analysis can't capture every dynamic usage of the component so users should be aware that its experimental. (similar to the existing cra-to-next codemod)

- Removes `lazyRoot` prop
- TODO: handle `loader`
- TODO: does not migrate the `loader` config. If you need it, you must manually add a `loader` prop.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note this TODO was merged

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, this is not implemented yet

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@leerob This is implemented in PR #41633


#### 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

Expand Down
258 changes: 80 additions & 178 deletions docs/api-reference/next/image.md

Large diffs are not rendered by default.

Large diffs are not rendered by default.

34 changes: 11 additions & 23 deletions docs/basic-features/image-optimization.md
Expand Up @@ -28,12 +28,6 @@ To add an image to your application, import the [`next/image`](/docs/api-referen
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).

### Local Images
Expand Down Expand Up @@ -151,15 +145,15 @@ Because `next/image` is designed to guarantee good performance results, it canno

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
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?
>
> 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**
>
Expand All @@ -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)

Styling the Image component is not that different from styling a normal `<img>` element, but there are a few guidelines to keep in mind:

**Pick the correct layout mode**

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.

**Target the image with className, not based on DOM structure**
Styling the Image component is similar to styling a normal `<img>` element, but there are a few guidelines to keep in mind:

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.
**Use `className` or `style`, not `styled-jsx`**

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

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 can also use the `style` prop to assign inline styles.

You cannot use [styled-jsx](/docs/basic-features/built-in-css-support.md#css-in-js) because it's scoped to the current component.
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`).

**When using `layout='fill'`, the parent element must have `position: relative`**
**When using `fill`, the parent element must have `position: relative`**

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.

Expand All @@ -205,7 +193,7 @@ This is the default for `<div>` elements but should be specified otherwise.

### 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

Expand Down
10 changes: 8 additions & 2 deletions docs/manifest.json
Expand Up @@ -427,8 +427,14 @@
}
},
{
"title": "next/future/image",
"path": "/docs/api-reference/next/future/image.md"
"path": "/docs/api-reference/next/future/image",
"redirect": {
"destination": "/docs/api-reference/next/image"
}
},
{
"title": "next/legacy/image",
"path": "/docs/api-reference/next/legacy/image.md"
},
{
"title": "Edge Runtime",
Expand Down
9 changes: 8 additions & 1 deletion examples/image-component/next.config.js
@@ -1,7 +1,14 @@
/** @type {import('next').NextConfig} */
module.exports = {
images: {
domains: ['assets.vercel.com'],
formats: ['image/avif', 'image/webp'],
remotePatterns: [
{
protocol: 'https',
hostname: 'assets.vercel.com',
port: '',
pathname: '/image/upload/**',
},
],
},
}
2 changes: 1 addition & 1 deletion examples/image-component/package.json
Expand Up @@ -6,7 +6,7 @@
"start": "next start"
},
"dependencies": {
"next": "latest",
"next": "canary",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
Expand Down
11 changes: 8 additions & 3 deletions examples/image-component/pages/background.tsx
@@ -1,17 +1,22 @@
import Image from 'next/image'
import ViewSource from '../components/view-source'
import styles from '../styles.module.css'
import mountains from '../public/mountains.jpg'

const BackgroundPage = () => (
<div>
<ViewSource pathname="pages/background.tsx" />
<div className={styles.bgWrap}>
<Image
alt="Mountains"
src="/mountains.jpg"
layout="fill"
objectFit="cover"
src={mountains}
placeholder="blur"
quality={100}
fill
sizes="100vw"
style={{
objectFit: 'cover',
}}
/>
</div>
<p className={styles.bgText}>
Expand Down
8 changes: 8 additions & 0 deletions examples/image-component/pages/color.tsx
Expand Up @@ -27,6 +27,10 @@ const Color = () => (
blurDataURL={rgbDataURL(237, 181, 6)}
width={750}
height={1000}
style={{
maxWidth: '100%',
height: 'auto',
}}
/>
<Image
alt="Cat"
Expand All @@ -35,6 +39,10 @@ const Color = () => (
blurDataURL={rgbDataURL(2, 129, 210)}
width={750}
height={1000}
style={{
maxWidth: '100%',
height: 'auto',
}}
/>
</div>
)
Expand Down
46 changes: 46 additions & 0 deletions examples/image-component/pages/fill.tsx
@@ -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