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 16 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
28 changes: 28 additions & 0 deletions files/en-us/web/api/htmlimageelement/decode/index.md
Expand Up @@ -51,6 +51,8 @@ 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
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -70,6 +72,32 @@ img
});
```

### 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}}
Expand Down
65 changes: 51 additions & 14 deletions files/en-us/web/api/htmlimageelement/decoding/index.md
Expand Up @@ -8,36 +8,68 @@ 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 default values — Chromium defaults to `"sync"`, Firefox defaults to `"async"`, and Safari seems to use different values in different circumstances.
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved

## 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.
In theory, this 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 `decoding` attribute for APIs is often not that useful, and there are often better ways of handling this.

For images that are not downloaded before being inserted into the DOM, the browser will likely render the empty image initially, and then handle the image when it is available, independently of the other content anyway.

For images that are downloaded before being inserted into the DOM, using the {{domxref("HTMLImageElement.decode()")}} method is a better way to assure atomic presentation without holding up other content.
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved

## 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 +79,8 @@ img.src = "img/logo.png";
## Browser compatibility

{{Compat}}

## See also

- The {{domxref("HTMLImageElement.decode()")}} method
- The {{htmlelement("img")}} element `decoding` attribute.
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved
36 changes: 34 additions & 2 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 image is decoded and it is safe to append
Rumyra marked this conversation as resolved.
Show resolved Hide resolved
the image to the DOM.

## Syntax

Expand All @@ -32,6 +32,38 @@ by appending it to the DOM, replacing an existing image, and so forth.

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 Down
65 changes: 58 additions & 7 deletions files/en-us/web/api/svgimageelement/decoding/index.md
Expand Up @@ -8,27 +8,77 @@ 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 default values — Chromium defaults to `"sync"`, Firefox defaults to `"async"`, and Safari seems to use different values in different circumstances.
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved

## Usage notes

In theory, this 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 `decoding` attribute for APIs is often not that useful, and there are often better ways of handling this.

For images that are not downloaded before being inserted into the DOM, the browser will likely render the empty image initially, and then handle the image when it is available, independently of the other content anyway.

For images that are downloaded before being inserted into the DOM, using the {{domxref("HTMLImageElement.decode()")}} method is a better way to assure atomic presentation without holding up other content.
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved

## 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 +91,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")}} 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).
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved
- {{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
16 changes: 11 additions & 5 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.
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved

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 Expand Up @@ -156,7 +162,7 @@ This element includes the [global attributes](/en-US/docs/Web/HTML/Global_attrib

- : One or more strings separated by commas, indicating a set of source sizes. Each source size consists of:

1. A [media condition](/en-US/docs/Web/CSS/Media_Queries/Using_media_queries#syntax). This must be omitted for the last item in the list.
1. A [media condition](/en-US/docs/Web/CSS/CSS_media_queries/Using_media_queries). This must be omitted for the last item in the list.
2. A source size value.

Media Conditions describe properties of the _viewport_, not of the _image_. For example, `(max-height: 500px) 1000px` proposes to use a source of 1000px width, if the _viewport_ is not higher than 500px.
Expand Down
47 changes: 47 additions & 0 deletions files/en-us/web/svg/attribute/decoding/index.md
@@ -0,0 +1,47 @@
---
title: decoding
slug: Web/SVG/Attribute/decoding
page-type: svg-attribute
browser-compat: svg.elements.image.decoding
---

{{SVGRef}}

The `decoding` attribute, valid on {{SVGElement("image")}} elements, provides a hint to the browser as to whether it should perform image decoding along with rendering other content in a single presentation step that looks more "correct" (`sync`), or render and present the other 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 `<image>` 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.

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

Allowed values:

- `sync`
- : Decode the image synchronously along with rendering the other content, and present everything together.
- `async`
- : Decode the image asynchronously, after rendering and presenting the other content.
- `auto`
- : No preference for the decoding mode; the browser decides what is best for the user. This is the default value.

## Example

```html
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<image
href="https://example.com/mdn_logo_dark.png"
height="200"
width="200"
decoding="async" />
</svg>
```

## Specifications

{{Specifications}}

## Browser compatibility

{{Compat}}

## See also

- [SVGImageElement: decoding property](/en-US/docs/Web/API/SVGImageElement/decoding)
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved
1 change: 1 addition & 0 deletions files/en-us/web/svg/element/image/index.md
Expand Up @@ -41,6 +41,7 @@ SVG files displayed with `<image>` are [treated as an image](/en-US/docs/Web/SVG
- {{SVGAttr("href")}} and {{SVGAttr("xlink:href")}}: Points at a URL for the image file.
- {{SVGAttr("preserveAspectRatio")}}: Controls how the image is scaled.
- {{SVGAttr("crossorigin")}}: Defines the value of the credentials flag for CORS requests.
- {{SVGAttr("decoding")}}: Provides a hint to the browser as to whether it should perform image decoding synchronously or asynchronously.

## DOM Interface

Expand Down