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

Add new 'raw' image layout #34339

Merged
merged 62 commits into from Mar 14, 2022
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
889a3c8
Update framework chunk test regex to not select nested dependencies
atcastle Oct 9, 2019
ebafcca
Update webpack-config.ts
Timer Oct 14, 2019
7ab3c8a
Merge branch 'canary' into canary
Timer Oct 14, 2019
2c62327
Add support for raw layout mode
atcastle Feb 14, 2022
4c769d3
Update image documentation for raw layout
atcastle Feb 14, 2022
5843826
documentation autoformatting
atcastle Feb 14, 2022
4252ffb
change typescript text fixture
atcastle Feb 14, 2022
c4fa96b
Merge remote-tracking branch 'origin' into image-layout-raw
atcastle Feb 16, 2022
4006b36
Refactor base image element in image component. Remove raw layout sup…
atcastle Feb 17, 2022
efad4b8
lint fixes
atcastle Feb 17, 2022
26a6103
lint fixes
atcastle Feb 17, 2022
f32440d
Fix typescript test
atcastle Feb 17, 2022
78904f2
fix tests
atcastle Feb 17, 2022
c457914
lint fix
atcastle Feb 17, 2022
bdd8836
Merge remote-tracking branch 'origin' into image-layout-raw
atcastle Feb 17, 2022
e812837
Allow all layouts to use style prop
atcastle Feb 18, 2022
90c778d
Move ImageElement component outside of Image
atcastle Feb 18, 2022
34411f2
Fix handling of noscript image attributes
atcastle Feb 18, 2022
64a0b70
lint fix
atcastle Feb 19, 2022
435091e
Merge remote-tracking branch 'origin' into image-layout-raw
atcastle Feb 19, 2022
2be4e4e
Merge remote-tracking branch 'origin' into image-layout-raw
atcastle Feb 19, 2022
6c9a9e4
Update docs to show style is now allowed on image componenet
atcastle Feb 19, 2022
d9f51f1
Additional test coverage for image style prop and raw
atcastle Feb 20, 2022
ebf5812
auto-lint
atcastle Feb 22, 2022
80ffd7e
Add support for priority to raw image and test it
atcastle Feb 22, 2022
b4fdc15
image.md wording tweak
atcastle Feb 22, 2022
24cf3dc
Test coverage for srcset behavior in raw layout
atcastle Feb 22, 2022
8c12019
Remove test focus
atcastle Feb 22, 2022
74ac553
Update docs/api-reference/next/image.md
atcastle Feb 22, 2022
8904782
Remove raw from ImageProps type and delete typescript-style test suite
atcastle Feb 23, 2022
2f91512
auto-lint
atcastle Feb 23, 2022
cac28f0
Documentation updates and move sizes overwrite warning
atcastle Feb 23, 2022
3be7243
auto-lint
atcastle Mar 9, 2022
9c5b9b8
Update packages/next/client/image.tsx
atcastle Mar 9, 2022
adb3a57
Update docs/api-reference/next/image.md
atcastle Mar 9, 2022
dd21513
Merge branch 'image-layout-raw' of github.com:atcastle/next.js into i…
atcastle Mar 9, 2022
6baa8be
auto-lint
atcastle Mar 9, 2022
19ffddc
Merge remote-tracking branch 'upstream/canary' into image-layout-raw
atcastle Mar 9, 2022
e03c65b
Add experimental flag for raw layout mode
atcastle Mar 9, 2022
20955eb
Fix image style test
atcastle Mar 9, 2022
b64bda7
Add aspect-ratio for raw images and only add height/width without sizes
atcastle Mar 9, 2022
78b9434
Update packages/next/client/image.tsx
atcastle Mar 9, 2022
7338c3a
Update docs/api-reference/next/image.md
atcastle Mar 9, 2022
bc42437
update docs for experimental raw layout
atcastle Mar 9, 2022
5eea550
Fix markdown links
atcastle Mar 9, 2022
d3d82b6
Documentation wording change
atcastle Mar 9, 2022
57edfe0
Merge branch 'canary' of github.com:atcastle/next.js into canary
atcastle Mar 10, 2022
d4e19f2
Merge branch 'canary' into image-layout-raw
atcastle Mar 10, 2022
a3aae1b
Merge branch 'canary' into image-layout-raw
atcastle Mar 10, 2022
2e6e84d
Merge branch 'image-layout-raw' of github.com:atcastle/next.js into i…
atcastle Mar 10, 2022
7525553
Fix type from merge
atcastle Mar 10, 2022
9f41f20
Update packages/next/client/image.tsx
atcastle Mar 10, 2022
c4654fa
Update docs/api-reference/next/image.md
atcastle Mar 10, 2022
820b152
Update packages/next/client/image.tsx
atcastle Mar 10, 2022
8563475
change to isLazy image element prop
atcastle Mar 10, 2022
74076ff
Merge branch 'image-layout-raw' of github.com:atcastle/next.js into i…
atcastle Mar 10, 2022
a000df1
clean up image element props
atcastle Mar 10, 2022
d48b36a
Use optional chaining for experimeental image opts
atcastle Mar 10, 2022
531b623
Add placeholder to imgElementArgs
atcastle Mar 10, 2022
d22691d
Only throw experimentalRaw error in non-prod
atcastle Mar 10, 2022
b5b1375
Apply suggestions from code review
styfle Mar 14, 2022
6a5ffac
Merge branch 'canary' into image-layout-raw
styfle Mar 14, 2022
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
66 changes: 48 additions & 18 deletions docs/api-reference/next/image.md
Expand Up @@ -14,16 +14,17 @@ description: Enable Image Optimization with the built-in Image component.
<details>
<summary><b>Version History</b></summary>

| Version | Changes |
| --------- | ------------------------------------------------------------------------------------------------- |
| `v12.1.0` | `dangerouslyAllowSVG` and `contentSecurityPolicy` configuration added. |
| `v12.0.9` | `lazyRoot` prop added. |
| `v12.0.0` | `formats` configuration added.<br/>AVIF support added.<br/>Wrapper `<div>` changed to `<span>`. |
| `v11.1.0` | `onLoadingComplete` and `lazyBoundary` props added. |
| `v11.0.0` | `src` prop support for static import.<br/>`placeholder` prop added.<br/>`blurDataURL` prop added. |
| `v10.0.5` | `loader` prop added. |
| `v10.0.1` | `layout` prop added. |
| `v10.0.0` | `next/image` introduced. |
| Version | Changes |
| --------- | ----------------------------------------------------------------------------------------------------- |
| `v12.1.1` | `style` prop added. Experimental[\*](#Experimental-raw-layout-mode) support for `layout="raw"` added. |
styfle marked this conversation as resolved.
Show resolved Hide resolved
| `v12.1.0` | `dangerouslyAllowSVG` and `contentSecurityPolicy` configuration added. |
| `v12.0.9` | `lazyRoot` prop added. |
| `v12.0.0` | `formats` configuration added.<br/>AVIF support added.<br/>Wrapper `<div>` changed to `<span>`. |
| `v11.1.0` | `onLoadingComplete` and `lazyBoundary` props added. |
| `v11.0.0` | `src` prop support for static import.<br/>`placeholder` prop added.<br/>`blurDataURL` prop added. |
| `v10.0.5` | `loader` prop added. |
| `v10.0.1` | `layout` prop added. |
| `v10.0.0` | `next/image` introduced. |

</details>

Expand Down Expand Up @@ -65,12 +66,13 @@ The `<Image />` component accepts a number of additional properties beyond those

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

| `layout` | Behavior | `srcSet` | `sizes` |
| --------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------- |
| `intrinsic` (default) | Scale *down* to fit width of container, up to image size | `1x`, `2x` (based on [imageSizes](#image-sizes)) | N/A |
| `fixed` | Sized to `width` and `height` exactly | `1x`, `2x` (based on [imageSizes](#image-sizes)) | N/A |
| `responsive` | Scale to fit width of container | `640w`, `750w`, ... `2048w`, `3840w` (based on [imageSizes](#image-sizes) and [deviceSizes](#device-sizes)) | `100vw` |
| `fill` | Grow in both X and Y axes to fill container | `640w`, `750w`, ... `2048w`, `3840w` (based on [imageSizes](#image-sizes) and [deviceSizes](#device-sizes)) | `100vw` |
| `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 |
| `raw`[\*](#Experimental-raw-layout-mode) | Insert the image element with no automatic layout behavior | Behaves like `responsive` if the image has the `sizes` prop, and like `fixed` if it does not | optional | no |
styfle marked this conversation as resolved.
Show resolved Hide resolved

- [Demo the `intrinsic` layout (default)](https://image-component.nextjs.gallery/layout-intrinsic)
- When `intrinsic`, the image will scale the dimensions down for smaller viewports, but maintain the original dimensions for larger viewports.
Expand All @@ -83,6 +85,9 @@ The layout behavior of the image as the viewport changes size.
- 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.
- When `raw`[\*](#Experimental-raw-layout-mode), the image will be rendered as a single image element with no wrappers, sizers or other responsive behavior.
atcastle marked this conversation as resolved.
Show resolved Hide resolved
- If your image styling will change the size of a `raw` image, you should include the `sizes` property for proper image serving. Otherwise your image will receive a fixed height and width.
- The other layout modes are optimized for performance and should cover nearly all use cases. It is recommended to try to use those modes before using `raw`.
- [Demo background image](https://image-component.nextjs.gallery/background)

### loader
Expand Down Expand Up @@ -121,7 +126,7 @@ const MyImage = (props) => {

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

If you are using `layout="fill"` or `layout="responsive"`, it's important to assign `sizes` for any image that takes up less than the full viewport width.
If you are using `layout="fill"`, `layout="responsive"`, or `layout="raw"`[\*](#Experimental-raw-layout-mode) it's important to assign `sizes` for any image that takes up less than the full viewport width.
styfle marked this conversation as resolved.
Show resolved Hide resolved

For example, when the parent element will constrain the image to always be less than half the viewport width, use `sizes="50vw"`. Without `sizes`, the image will be sent at twice the necessary resolution, decreasing performance.

Expand Down Expand Up @@ -162,6 +167,12 @@ Try it out:

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

### style

Allows [passing CSS styles](https://reactjs.org/docs/dom-elements.html#style) to the underlying image element.

Note that all `layout` modes other than `"raw"`[\*](#Experimental-raw-layout-mode) apply their own styles to the image element, and these automatic styles take precedence over the `style` prop.
styfle marked this conversation as resolved.
Show resolved Hide resolved

### objectFit

Defines how the image will fit into its parent container when using `layout="fill"`.
Expand Down Expand Up @@ -285,7 +296,6 @@ size, or format. Defaults to `false`.
Other properties on the `<Image />` component will be passed to the underlying
`img` element with the exception of the following:

- `style`. Use `className` instead.
- `srcSet`. Use
[Device Sizes](#device-sizes)
instead.
Expand Down Expand Up @@ -455,12 +465,32 @@ module.exports = {
}
```


### Experimental "raw" layout mode

The image component currently supports an additional `layout="raw"` mode, which renders the image without wrappers or styling. This layout mode is currently an experimental feature, while user feedback is gathered. As there is the possibility of breaking changes to the `layout="raw"` interface, the feature is locked behind an experimental feature flag. If you would like to use the `raw` layout mode, you must add the following to your `next.config.js`:

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

> Note on CLS with `layout="raw"`:
> It is possible to cause [layout shift](https://web.dev/cls/) with the image component in `raw` mode. If you include a `sizes` property, the image component will not pass `height` and `width` attributes to the image, to allow you to apply your own responsive sizing.
> An [aspect-ratio](https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio) style property is automatically applied to prevent layout shift, but this won't apply on [older browsers](https://caniuse.com/mdn-css_properties_aspect-ratio).

### Animated Images

The default [loader](#loader) will automatically bypass Image Optimization for animated images and serve the image as-is.

Auto-detection for animated files is best-effort and supports GIF, APNG, and WebP. If you want to explicitly bypass Image Optimization for a given animated image, use the [unoptimized](#unoptimized) prop.


## Related

For an overview of the Image component features and usage guidelines, see:
Expand Down
4 changes: 1 addition & 3 deletions docs/basic-features/image-optimization.md
Expand Up @@ -181,16 +181,14 @@ The image component has several different [layout modes](/docs/api-reference/nex

**Target the image with className, not based on DOM structure**

Regardless of the layout mode used, the Image component will have a consistent 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.
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.

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.

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.

You cannot use the `style` prop because the `<Image>` component does not pass it through to the underlying `<img>`.

**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.
Expand Down
1 change: 1 addition & 0 deletions packages/next/build/webpack-config.ts
Expand Up @@ -1350,6 +1350,7 @@ export default async function getBaseWebpackConfig(
imageSizes: config.images.imageSizes,
path: config.images.path,
loader: config.images.loader,
experimentalLayoutRaw: config.experimental?.images?.layoutRaw,
...(dev
? {
// pass domains in development to allow validating on the client
Expand Down