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

Adding information about the decoding attribute #27166

Merged
merged 26 commits into from Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b39298d
Adding information about the decoding attribute
chrisdavidmills Jun 6, 2023
db31928
Merge branch 'main' into update-image-decoding-content
chrisdavidmills Jun 6, 2023
b43698f
Merge branch 'main' into update-image-decoding-content
chrisdavidmills Jun 7, 2023
23e0764
Updates based on useful research notes from Barry Pollard
chrisdavidmills Jun 7, 2023
e744587
Merge branch 'main' into update-image-decoding-content
chrisdavidmills Jun 7, 2023
79672c4
more updates as per barry pollard comments
chrisdavidmills Jun 12, 2023
ad69439
Merge branch 'main' into update-image-decoding-content
chrisdavidmills Jun 12, 2023
422df27
Update files/en-us/web/api/htmlimageelement/decoding/index.md
chrisdavidmills Jun 19, 2023
90f8b1e
Update files/en-us/web/api/htmlimageelement/decoding/index.md
chrisdavidmills Jun 19, 2023
f378fc6
Update files/en-us/web/api/htmlimageelement/index.md
chrisdavidmills Jun 19, 2023
cb7d33f
Merge branch 'main' into update-image-decoding-content
chrisdavidmills Jun 19, 2023
2180498
More content updates
chrisdavidmills Jun 19, 2023
98cb7ed
Update files/en-us/web/html/element/img/index.md
chrisdavidmills Jun 20, 2023
978e04f
Update files/en-us/web/svg/attribute/decoding/index.md
chrisdavidmills Jun 20, 2023
11c74b8
Merge branch 'main' into update-image-decoding-content
chrisdavidmills Jun 20, 2023
2049a1b
A few more wording tweaks
chrisdavidmills Jun 20, 2023
6181f42
Merge branch 'main' into update-image-decoding-content
chrisdavidmills Jul 5, 2023
7813b05
Update files/en-us/web/api/htmlimageelement/decoding/index.md
chrisdavidmills Jul 5, 2023
75b10dd
Update files/en-us/web/api/svgimageelement/index.md
chrisdavidmills Jul 5, 2023
291611b
Update files/en-us/web/svg/attribute/decoding/index.md
chrisdavidmills Jul 5, 2023
0152596
A few more weaks
chrisdavidmills Jul 5, 2023
90aea8e
Merge branch 'main' into update-image-decoding-content
chrisdavidmills Jul 5, 2023
8306789
Merge branch 'main' into update-image-decoding-content
chrisdavidmills Jul 25, 2023
5d1f381
Merge branch 'main' into update-image-decoding-content
chrisdavidmills Aug 4, 2023
19412d5
Merge branch 'main' into update-image-decoding-content
chrisdavidmills Aug 9, 2023
4a9657e
Fixes for Rumyra comments
chrisdavidmills Aug 9, 2023
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
48 changes: 41 additions & 7 deletions files/en-us/web/api/htmlimageelement/decode/index.md
Expand Up @@ -10,8 +10,8 @@ browser-compat: api.HTMLImageElement.decode

The **`decode()`**
method of the {{domxref("HTMLImageElement")}} interface returns a
{{jsxref("Promise")}} that resolves when the image is decoded and it is safe to append
the image to the DOM.
{{jsxref("Promise")}} that resolves once the image is decoded and it is safe to append
it to the DOM.

This can be used to initiate loading of the image prior
to attaching it to an element in the DOM (or adding it to the DOM as a new element), so
Expand All @@ -31,7 +31,7 @@ None.

### Return value

A {{jsxref('Promise')}} which is resolved once the image data is ready to be used.
A {{jsxref('Promise')}} that fulfills with `undefined` once the image data is ready to be used.

### Exceptions

Expand All @@ -51,11 +51,10 @@ low-resolution image with the full-resolution one that's now available.

## Examples

### Basic usage

The following example shows how to use the `decode()` method to control when
an image is appended to the DOM. Without a {{jsxref('Promise')}}-returning method, you
would add the image to the DOM in a {{domxref("Window/load_event", "load")}} event handler, such as by using
the {{domxref("HTMLImageElement.load_event", "img.onload")}} event handler, and by
handling the error in the {{domxref("HTMLElement/error_event", "error")}} event's handler.
an image is appended to the DOM.

```js
const img = new Image();
Expand All @@ -70,10 +69,45 @@ img
});
```

> **Note:** Without a {{jsxref('Promise')}}-returning method, you
> would add the image to the DOM in a {{domxref("Window/load_event", "load")}} event handler,
> and handle the error in the {{domxref("Element/error_event", "error")}} event's handler.

### Avoiding empty images

In the below example, you'll likely get an empty image shown on the page as the image is downloaded:

```js
const img = new Image();
img.src = "img/logo.png";
document.body.appendChild(img);
```

Using `decode()` will delay inserting the image into the DOM until it is fully downloaded and decoded, thereby avoiding the empty image problem:

```js
async function getImage() {
const img = new Image();
img.src = "img/logo.png";
await img.decode();
document.body.appendChild(img);
const p = document.createElement("p");
p.textContent = "Image is fully loaded!";
document.body.appendChild(p);
}
```

This is particularly useful if you're dynamically swapping an existing image for a new one, and also prevents unrelated paints outside of this code from being held up while the image is decoding.

## Specifications

{{Specifications}}

## Browser compatibility

{{Compat}}

## See also

- [What does the image decoding attribute actually do?](https://www.tunetheweb.com/blog/what-does-the-image-decoding-attribute-actually-do/) on tunetheweb.com (2023)
- The {{domxref("HTMLImageElement.decoding")}} property
69 changes: 55 additions & 14 deletions files/en-us/web/api/htmlimageelement/decoding/index.md
Expand Up @@ -8,36 +8,71 @@ browser-compat: api.HTMLImageElement.decoding

{{APIRef}}

The **`decoding`** property of the
{{domxref("HTMLImageElement")}} interface represents a hint given to the browser on how
it should decode the image.
The **`decoding`** property of the {{domxref("HTMLImageElement")}} interface provides a hint to the browser as to how it should decode the image. More specifically, whether it should wait for the image to be decoded before presenting other content updates or not.

## Value

A string representing the decoding hint. Possible values are:

- `sync`
- `"sync"`
- : Decode the image synchronously for atomic presentation with other content.
- `async`
- : Decode the image asynchronously to reduce delay in presenting other content.
- `auto`
- : Default mode, which indicates no preference for the decoding mode.
The browser decides what is best for the user.
- `"async"`
- : Decode the image asynchronously and allow other content to be rendered before this completes.
- `"auto"`
- : No preference for the decoding mode; the browser decides what is best for the user. This is the default value, but different browsers have different defaults:
- Chromium defaults to `"sync"`.
- Firefox defaults to `"async"`.
- Safari defaults to `"sync"` except in a small number of circumstances.

## Usage notes

The `decoding` property allows you to control whether or not the browser is
allowed to try to parallelize loading your image. If doing so would cause problems, you
can specify `sync` to disable asynchronous loading. This can be useful when
applied to {{HTMLElement("img")}} elements, but may be even more so when used for
offscreen image objects.
The `decoding` property provides a hint to the browser as to whether it should perform image decoding along with other tasks in a single step (`"sync"`), or allow other content to be rendered before this completes (`"async"`). In reality, the differences between the two values are often difficult to perceive and, where there are differences, there is often a better way.

For images that are inserted into the DOM inside the viewport, `"async"` can result in flashes of unstyled content, while `"sync"` can result in small amounts of [jank](/en-US/docs/Glossary/Jank). Using the {{domxref("HTMLImageElement.decode()")}} method is usually a better way to achieve atomic presentation without holding up other content.

For images inserted into the DOM outside of the viewport, modern browsers will usually decode them before they are scrolled into view and there will be no noticeable difference using either value.

## Examples

In the below example, you'll likely get an empty image shown on the page as the image is downloaded. Setting `decoding` won't prevent that.
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved

```js
const img = new Image();
img.decoding = "sync";
img.src = "img/logo.png";
document.body.appendChild(img);
```

chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved
Inserting an image after download can make the `decoding` property more relevant:

```js
async function loadImage(url, elem) {
return new Promise((resolve, reject) => {
elem.onload = () => resolve(elem);
elem.onerror = reject;
elem.src = url;
});
}

const img = new Image();
await loadImage("img/logo.png", img);
// Using `sync` can ensure other content is only updated with the image
img.decoding = "sync";
document.body.appendChild(img);
const p = document.createElement("p");
p.textContent = "Image is fully loaded!";
document.body.appendChild(p);
```

A better solution, however, is to use the {{domxref("HTMLImageElement.decode()")}} method to solve this problem. It provides a way to asynchronously decode an image, delaying inserting it into the DOM until it is fully downloaded and decoded, thereby avoiding the empty image problem mentioned above. This is particularly useful if you're dynamically swapping an existing image for a new one, and also prevents unrelated paints outside of this code from being held up while the image is decoding.

Using `img.decoding = "async"` may avoid holding up other content from displaying if the decoding time is long:

```js
const img = new Image();
img.decoding = "async";
img.src = "img/logo.png";
document.body.appendChild(img);
```

## Specifications
Expand All @@ -47,3 +82,9 @@ img.src = "img/logo.png";
## Browser compatibility

{{Compat}}

## See also

- The {{domxref("HTMLImageElement.decode()")}} method
- The {{htmlelement("img")}} element `decoding` attribute
- [What does the image decoding attribute actually do?](https://www.tunetheweb.com/blog/what-does-the-image-decoding-attribute-actually-do/) on tunetheweb.com (2023)
43 changes: 37 additions & 6 deletions files/en-us/web/api/svgimageelement/decode/index.md
Expand Up @@ -10,8 +10,8 @@ browser-compat: api.SVGImageElement.decode

The **`decode()`** method of the
{{domxref("SVGImageElement")}} interface initiates asynchronous decoding of an image,
returning a {{jsxref('Promise')}} that resolves once the image data is ready
for use.
returning a {{jsxref('Promise')}} that resolves once the image is decoded and it is safe to append
it to the DOM.

## Syntax

Expand All @@ -25,13 +25,44 @@ None.

### Return value

A {{jsxref('Promise')}} which resolves once the image data is ready to be used, such as
by appending it to the DOM, replacing an existing image, and so forth.
A {{jsxref('Promise')}} that fulfills with `undefined` once the image data is ready to be used, for example by appending it to the DOM, replacing an existing image, and so forth.

### Exceptions

None.

## Examples

In the below example, you'll likely get an empty image shown on the page as the image is downloaded:

```js
const SVG_NS = "http://www.w3.org/2000/svg";
const svg = document.querySelector("svg");

const img = document.createElementNS(SVG_NS, "image");
img.src = "img/logo.svg";
svg.appendChild(img);
```

Using `decode()` will delay inserting the image into the DOM until it is fully downloaded and decoded, thereby avoiding the empty image problem:

```js
const SVG_NS = "http://www.w3.org/2000/svg";
const svg = document.querySelector("svg");

async function getImage() {
const img = document.createElementNS(SVG_NS, "image");
img.src = "img/logo.svg";
await img.decode();
svg.appendChild(img);
const text = document.createElementNS(SVG_NS, "text");
text.textContent = "Image is fully loaded!";
svg.appendChild(text);
}
```

This is particularly useful if you're dynamically swapping an existing image for a new one, and also prevents unrelated paints outside of this code from being held up while the image is decoding.
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved

## Specifications

{{Specifications}}
Expand All @@ -42,5 +73,5 @@ None.

## See also

- {{domxref("HTMLImageElement.decode()")}}: The same thing, but for HTML
{{HTMLElement("image")}} elements
- {{domxref("HTMLImageElement.decode()")}}: The same thing, but for HTML `<img>` elements
- [What does the image decoding attribute actually do?](https://www.tunetheweb.com/blog/what-does-the-image-decoding-attribute-actually-do/) on tunetheweb.com (2023)
68 changes: 61 additions & 7 deletions files/en-us/web/api/svgimageelement/decoding/index.md
Expand Up @@ -8,27 +8,80 @@ browser-compat: api.SVGImageElement.decoding

{{APIRef}}

The **`decoding`** property of the {{domxref("SVGImageElement")}} interface represents a hint given to the browser on how it should decode the image.
The **`decoding`** property of the {{domxref("SVGImageElement")}} interface provides a hint to the browser as to whether it should perform image decoding synchronously or asynchronously.
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved

## Value

A string representing the decoding hint. Possible values are:

- `sync`
- `"sync"`
- : Decode the image synchronously for atomic presentation with other content.
- `async`
- : Decode the image asynchronously to reduce delay in presenting other content.
- `auto`
- : Default mode, which indicates no preference for the decoding mode. The browser decides what is best for the user.
- `"async"`
- : Decode the image asynchronously and allow other content to be rendered before this completes.
- `"auto"`
- : No preference for the decoding mode; the browser decides what is best for the user. This is the default value, but different browsers have different defaults:
- Chromium defaults to `"sync"`.
- Firefox defaults to `"async"`.
- Safari defaults to `"sync"` except in a small number of circumstances.

## Usage notes

The `decoding` property provides a hint to the browser as to whether it should perform image decoding along with other tasks in a single step (`"sync"`), or allow other content to be rendered before this completes (`"async"`). In reality, the differences between the two values are often difficult to perceive and, where there are differences, there is often a better way.

For images that are inserted into the DOM inside the viewport, `"async"` can result in flashes of unstyled content, while `"sync"` can result in small amounts of [jank](/en-US/docs/Glossary/Jank). Using the {{domxref("SVGImageElement.decode()")}} method is usually a better way to achieve atomic presentation without holding up other content.

For images inserted into the DOM outside of the viewport, modern browsers will usually decode them before they are scrolled into view and there will be no noticeable difference using either value.

## Examples

In the below example, you'll likely get an empty image shown on the page as the image is downloaded. Setting `decoding` won't prevent that.

```js
const SVG_NS = "http://www.w3.org/2000/svg";
const svg = document.querySelector("svg");

const img = document.createElementNS(SVG_NS, "image");
img.decoding = "sync";
img.setAttribute("href", "img/logo.svg");
svg.appendChild(img);
```

Inserting an image after download can make the `decoding` property more relevant:

```js
async function loadImage(url, elem) {
return new Promise((resolve, reject) => {
elem.onload = () => resolve(elem);
elem.onerror = reject;
elem.src = url;
});
}

const SVG_NS = "http://www.w3.org/2000/svg";
const svg = document.querySelector("svg");

const img = document.createElementNS(SVG_NS, "image");
await loadImage("img/logo.svg", img);
// Using `sync` can ensure other content is only updated with the image
img.decoding = "sync";
svg.appendChild(img);
const text = document.createElementNS(SVG_NS, "text");
text.textContent = "Image is fully loaded!";
svg.appendChild(text);
```

A better solution, however, is to use the {{domxref("SVGImageElement.decode()")}} method to solve this problem. It provides a way to asynchronously decode an image, delaying inserting it into the DOM until it is fully downloaded and decoded, thereby avoiding the empty image problem mentioned above. This is particularly useful if you're dynamically swapping an existing image for a new one, and also prevents unrelated paints outside of this code from being held up while the image is decoding.

Using `img.decoding = "async"` may avoid holding up other content from displaying if the decoding time is long:

```js
const SVG_NS = "http://www.w3.org/2000/svg";
const svg = document.querySelector("svg");

const img = document.createElementNS(SVG_NS, "image");
img.decoding = "async";
img.setAttribute("href", "img/logo.svg");
svg.appendChild(img);
```

## Specifications
Expand All @@ -41,4 +94,5 @@ img.setAttribute("href", "img/logo.svg");

## See also

- [`<img>`: The Image Embed element](/en-US/docs/Web/HTML/Element/img)
- The {{domxref("SVGImageElement.decode()")}} method
- The SVG {{SVGElement("image")}} element {{SVGAttr("decoding")}} attribute.
2 changes: 1 addition & 1 deletion files/en-us/web/api/svgimageelement/index.md
Expand Up @@ -18,7 +18,7 @@ _This interface also inherits properties from its parent, {{domxref("SVGGraphics
- {{domxref("SVGImageElement.href")}} {{ReadOnlyInline}}
- : An {{domxref("SVGAnimatedString")}} corresponding to the {{SVGAttr("href")}} or {{SVGAttr("xlink:href")}} {{deprecated_inline}} attribute of the given {{SVGElement("image")}} element.
- {{domxref("SVGImageElement.decoding")}}
- : A string representing a hint given to the browser on how it should decode the image.
- : Represents a hint given to the browser on how it should decode the image. If this value is provided, it must be one of the possible permitted values: `"sync"` to decode the image synchronously, `"async"` to decode it asynchronously, or `"auto"` to indicate no preference (which is the default).
- {{domxref("SVGImageElement.height")}} {{ReadOnlyInline}}
- : An {{domxref("SVGAnimatedLength")}} corresponding to the {{SVGAttr("height")}} attribute of the given {{SVGElement("image")}} element.
- {{domxref("SVGImageElement.preserveAspectRatio")}} {{ReadOnlyInline}}
Expand Down
14 changes: 10 additions & 4 deletions files/en-us/web/html/element/img/index.md
Expand Up @@ -92,14 +92,20 @@ This element includes the [global attributes](/en-US/docs/Web/HTML/Global_attrib

- `decoding`

- : Provides an image decoding hint to the browser. Allowed values:
- : This attribute provides a hint to the browser as to whether it should perform image decoding along with rendering the other DOM content in a single presentation step that looks more "correct" (`sync`), or render and present the other DOM content first and then decode the image and present it later (`async`). In practice, `async` means that the next paint does not wait for the image to decode.

It is often difficult to perceive any noticeable effect when using `decoding` on static `<img>` elements. They'll likely be initially rendered as empty images while the image files are fetched (either from the network or from the cache) and then handled independently anyway, so the "syncing" of content updates is less apparent. However, the blocking of rendering while decoding happens, while often quite small, _can_ be measured — even if it is difficult to observe with the human eye. See [What does the image decoding attribute actually do?](https://www.tunetheweb.com/blog/what-does-the-image-decoding-attribute-actually-do/) for a more detailed analysis (tunetheweb.com, 2023).

Using different `decoding` types can result in more noticeable differences when dynamically inserting `<img>` elements into the DOM via JavaScript — see {{domxref("HTMLImageElement.decoding")}} for more details.

Allowed values:

- `sync`
- : Decode the image synchronously, for atomic presentation with other content.
- : Decode the image synchronously along with rendering the other DOM content, and present everything together.
- `async`
- : Decode the image asynchronously, to reduce delay in presenting other content.
- : Decode the image asynchronously, after rendering and presenting the other DOM content.
- `auto`
- : Default: no preference for the decoding mode. The browser decides what is best for the user.
- : No preference for the decoding mode; the browser decides what is best for the user. This is the default value.

- `elementtiming`

Expand Down