OfflineAudioContext: startRendering() method - Web APIs

OfflineAudioContext: startRendering() method
============================================

The `startRendering()` method of the `OfflineAudioContext` Interface starts rendering the audio graph, taking into account the current connections and the current scheduled changes.

The `complete` event (of type `OfflineAudioCompletionEvent`) is raised when the rendering is finished, containing the resulting `AudioBuffer` in its `renderedBuffer` property.

 Browsers currently support two versions of the `startRendering()` method — an older event-based version and a newer promise-based version.
 The former will eventually be removed, but currently both mechanisms are provided for legacy reasons.

Syntax
------

```js
startRendering()
```

### Parameters

None.

### Return value

A `Promise` that fulfills with an `AudioBuffer`.

Examples
--------

### Playing audio with an offline audio context

In this example, we declare both an `AudioContext` and an `OfflineAudioContext` object. We use the `AudioContext` to load an audio track `fetch()`, then the `OfflineAudioContext` to render the audio into an `AudioBufferSourceNode` and play the track through. After the offline audio graph is set up, we render it to an `AudioBuffer` using `OfflineAudioContext.startRendering()`.

When the `startRendering()` promise resolves, rendering has completed and the output `AudioBuffer` is returned out of the promise.

At this point we create another audio context, create an `AudioBufferSourceNode` inside it, and set its buffer to be equal to the promise `AudioBuffer`. This is then played as part of a simple standard audio graph.

**Note:** You can run the full example live, or view the source.

```js
// Define both online and offline audio contexts
let audioCtx; // Must be initialized after a user interaction
const offlineCtx = new OfflineAudioContext(2, 44100 \* 40, 44100);

// Define constants for dom nodes
const play = document.querySelector("#play");

function getData() {
  // Fetch an audio track, decode it and stick it in a buffer.
  // Then we put the buffer into the source and can play it.
  fetch("viper.ogg")
    .then((response) => response.arrayBuffer())
    .then((downloadedBuffer) => audioCtx.decodeAudioData(downloadedBuffer))
    .then((decodedBuffer) => {
      console.log("File downloaded successfully.");
      const source = new AudioBufferSourceNode(offlineCtx, {
        buffer: decodedBuffer,
      });
      source.connect(offlineCtx.destination);
      return source.start();
    })
    .then(() => offlineCtx.startRendering())
    .then((renderedBuffer) => {
      console.log("Rendering completed successfully.");
      play.disabled = false;
      const song = new AudioBufferSourceNode(audioCtx, {
        buffer: renderedBuffer,
      });
      song.connect(audioCtx.destination);

      // Start the song
      song.start();
    })
    .catch((err) => {
      console.error(`Error encountered: ${err}`);
    });
}

// Activate the play button
play.onclick = () => {
  play.disabled = true;
  // We can initialize the context as the user clicked.
  audioCtx = new AudioContext();

  // Fetch the data and start the song
  getData();
};
```

Specifications
--------------

| Specification |
| --- |
| Web Audio API # dom-offlineaudiocontext-startrendering |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Using the Web Audio API


OfflineAudioContext: OfflineAudioContext() constructor - Web APIs

OfflineAudioContext: OfflineAudioContext() constructor
======================================================

 The
 **`OfflineAudioContext()`** constructor—part of the Web Audio API—creates and returns a new
 `OfflineAudioContext` object instance, which can then be used to render
 audio to an `AudioBuffer` rather than to an audio output device.

Syntax
------

```js
new OfflineAudioContext(options)

new OfflineAudioContext(numberOfChannels, length, sampleRate)
```

### Parameters

 You can specify the parameters for the `OfflineAudioContext()` constructor
 as either the same set of parameters as are inputs into the
 `BaseAudioContext.createBuffer` method, or by passing those parameters in an
 `options` object. Either way, the individual parameters are the same.

`numberOfChannels`

 An integer specifying the number of channels the resulting
 `AudioBuffer` should have.

`length`

 An integer specifying the size of the buffer to create for the audio context, in
 sample-frames, where one sample-frame is a unit that can contain a single sample of
 audio data for every channel in the audio data. For example, a 5-second buffer with a
 `sampleRate` of 48000Hz would have a length of
 `5 * 48000 = 240000` sample-frames.

`sampleRate`

 The sample-rate of the linear audio data in sample-frames per second. All user
 agents are required to support a range of 8000Hz to 96000Hz, and may support a wider
 range than that. The most commonly-used rate is 44100Hz, which is the sample rate used
 by CD audio.

 It is important to note that, whereas you can create a new `AudioContext`
 using the `new AudioContext()` constructor
 with no arguments, the `OfflineAudioContext()` constructor requires three
 arguments, since it needs to create an `AudioBuffer`. This works in exactly
 the same way as when you create a new `AudioBuffer` with the
 `BaseAudioContext.createBuffer` method. For more detail, read Audio buffers: frames, samples and channels from our Basic concepts guide.

### Return value

 A new `OfflineAudioContext` object whose associated
 `AudioBuffer` is configured as requested.

 Like a regular `AudioContext`, an
 `OfflineAudioContext` can be the target of events, therefore it implements
 the `EventTarget` interface.

Examples
--------

```js
const offlineCtx = new OfflineAudioContext({
  numberOfChannels: 2,
  length: 44100 \* 40,
  sampleRate: 44100,
});
const source = offlineCtx.createBufferSource();
// …
```

 For a full working example, see our offline-audio-context-promise
 GitHub repo (see the source code too.)

Specifications
--------------

| Specification |
| --- |
| Web Audio API # dom-offlineaudiocontext-offlineaudiocontext |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


Using the Permissions API - Web APIs

Using the Permissions API
=========================

This article provides a basic guide to using the W3C Permissions API, which provides a programmatic way to query the status of API permissions attributed to the current context.

The trouble with asking for permission…
---------------------------------------

Permissions on the Web are a necessary evil, but they are not much fun to deal with as developers.

Historically, different APIs handle their own permissions inconsistently — for example the Notifications API had its own methods for checking the permission status and requesting permission, whereas the Geolocation API did not.

 The Permissions API provides a consistent approach for developers, and allows them to implement a better user experience as far as permissions are concerned.
 Specifically, developers can use `Permissions.query()` to check whether permission to use a particular API in the current context is granted, denied, or requires specific user permission via a prompt.
 Querying permissions in the main thread is broadly supported, and also in Workers (with a notable exception).

Many APIs now enable permission querying, such as the Clipboard API, Notifications API

* Push API, Web MIDI API.
 A list of many permission enabled APIs is provided in the API Overview, and you can get a sense of browser support in the compatibility table here.

`Permissions` has other methods to specifically request permission to use an API, and to revoke permission, but these are deprecated (non-standard, and/or not broadly supported).

A simple example
----------------

For this article, we have put together a simple demo called Location Finder. It uses Geolocation to query the user's current location and plot it out on a Google Map:

![Screenshot showing a map of Greenfield, UK.](/en-US/docs/Web/API/Permissions_API/Using_the_Permissions_API/location-finder-with-permissions-api.png)

You can run the example live, or view the source code on GitHub. Most of the code is simple and unremarkable — below we'll just be walking through the Permissions API-related code, so check the code yourself if you want to study any of the other parts.

### Accessing the Permissions API

The `Navigator.permissions` property has been added to the browser to allow access to the global `Permissions` object. This object will eventually include methods for querying, requesting, and revoking permissions, although currently it only contains `Permissions.query()`; see below.

### Querying permission state

In our example, the Permissions functionality is handled by one function — `handlePermission()`. This starts off by querying the permission status using `Permissions.query()`. Depending on the value of the `state` property of the `PermissionStatus` object returned when the promise resolves, it reacts differently:

`"granted"`

The "Enable Geolocation" button is hidden, as it isn't needed if Geolocation is already active.

`"prompt"`

The "Enable Geolocation" button is hidden, as it isn't needed if the user will be prompted to grant permission for Geolocation. The `Geolocation.getCurrentPosition()` function is then run, which prompts the user for permission; it runs the `revealPosition()` function if permission is granted (which shows the map), or the `positionDenied()` function if permission is denied (which makes the "Enable Geolocation" button appear).

`"denied"`

The "Enable Geolocation" button is revealed (this code needs to be here too, in case the permission state is already set to denied for this origin when the page is first loaded).

```js
function handlePermission() {
  navigator.permissions.query({ name: "geolocation" }).then((result) => {
    if (result.state === "granted") {
      report(result.state);
      geoBtn.style.display = "none";
    } else if (result.state === "prompt") {
      report(result.state);
      geoBtn.style.display = "none";
      navigator.geolocation.getCurrentPosition(
        revealPosition,
        positionDenied,
        geoSettings,
      );
    } else if (result.state === "denied") {
      report(result.state);
      geoBtn.style.display = "inline";
    }
    result.addEventListener("change", () => {
      report(result.state);
    });
  });
}

function report(state) {
  console.log(`Permission ${state}`);
}

handlePermission();
```

### Permission descriptors

The `Permissions.query()` method takes a `PermissionDescriptor` dictionary as a parameter — this contains the name of the API you are interested in. Some APIs have more complex `PermissionDescriptor`s containing additional information, which inherit from the default `PermissionDescriptor`. For example, the `PushPermissionDescriptor` should also contain a Boolean that specifies if `userVisibleOnly` is `true` or `false`.

### Revoking permissions

Starting in Firefox 47, you can now revoke existing permissions, using the `Permissions.revoke()` method. This works in exactly the same way as the `Permissions.query()` method, except that it causes an existing permission to be reverted back to its default state when the promise successfully resolves (which is usually `prompt`). See the following code in our demo:

```js
const revokeBtn = document.querySelector(".revoke");

// ...

revokeBtn.onclick = () => {
  revokePermission();
};

// ...

function revokePermission() {
  navigator.permissions.revoke({ name: "geolocation" }).then((result) => {
    report(result.state);
  });
}
```

**Note:** The `revoke()` function has been disabled by default starting in Firefox 51, since its design has been brought into question in the Web Applications Security Working Group. It can be re-enabled by setting the preference `dom.permissions.revoke.enable` to `true`.

### Responding to permission state changes

You'll notice that we're listening to the `change` event in the code above, attached to the `PermissionStatus` object — this allows us to respond to any changes in the permission status for the API we are interested in. At the moment we are just reporting the change in state.

Conclusion and future work
--------------------------

At the moment this doesn't offer much more than what we had already. If we choose to never share our location from the permission prompt (deny permission), then we can't get back to the permission prompt without using the browser menu options:

* **Firefox**: *Tools > Page Info > Permissions > Access Your Location*. Select *Always Ask*.
* **Chrome**: *Hamburger Menu > Settings > Show advanced settings*. In the *Privacy* section, click *Content Settings*. In the resulting dialog, find the *Location* section and select *Ask when a site tries to…*. Finally, click *Manage Exceptions* and remove the permissions you granted to the sites you are interested in.

However, future additions to browser functionality should provide the `request()` method, which will allow us to programmatically request permissions, any time we like. These should hopefully be available soon.


Using the CSS Painting API - Web APIs

Using the CSS Painting API
==========================

 The CSS Paint API is designed to enable developers to programmatically define images which can then be used anywhere a CSS image can be invoked, such as CSS `background-image`, `border-image`, `mask-image`, etc.

To programmatically create an image used by a CSS stylesheet we need to work through a few steps:

1. Define a paint worklet using the `registerPaint()` function
2. Register the worklet
3. Include the ``paint()`` CSS function

To elaborate over these steps, we're going to start by creating a half-highlight background, like on this header:

![Text reading 'My Cool Header' with a solid yellow background image block on the bottom left two thirds of the header](/en-US/docs/Web/API/CSS_Painting_API/Guide/mycoolheader.png)

**Note:** The complete source for all the examples in this article can be found at https://github.com/mdn/dom-examples/tree/main/css-painting, and the examples are running live at https://mdn.github.io/dom-examples/css-painting/.

CSS paint worklet
-----------------

In an external script file, we employ the `registerPaint()` function to name our CSS Paint worklet. It takes two parameters. The first is the name we give the worklet — this is the name we will use in our CSS as the parameter of the `paint()` function when we want to apply this styling to an element. The second parameter is the class that does all the magic, defining the context options and what to paint to the two-dimensional canvas that will be our image.

```js
registerPaint(
  "headerHighlight",
  class {
    /\*
 define if alphatransparency is allowed alpha
 is set to true by default. If set to false, all
 colors used on the canvas will be fully opaque
 \*/
    static get contextOptions() {
      return { alpha: true };
    }

    /\*
 ctx is the 2D drawing context
 a subset of the HTML Canvas API.
 \*/
    paint(ctx) {
      ctx.fillStyle = "hsl(55 90% 60% / 100%)";
      ctx.fillRect(0, 15, 200, 20); /\* order: x, y, w, h \*/
    }
  },
);
```

In this class example we have defined a single context option with the `contextOptions()` function: we returned a simple object stating alpha transparency is allowed.

We have then used the `paint()` function to paint to our canvas.

A `paint()` function can take three arguments. Here we have provided one argument: the rendering context (we'll look at more in due course), often referred to by the variable name `ctx`. The 2D Rendering Context is a subset of the HTML Canvas API; the version available to Houdini (called the `PaintRenderingContext2D`) is a further subset containing most of the features available in the full Canvas API with the exception of the `CanvasImageData`, `CanvasUserInterface`, `CanvasText`, and `CanvasTextDrawingStyles` APIs.

We define the `fillStyle` as being `hsl(55 90% 60% / 100%)`, which is a shade of yellow, and then call `fillRect()` to create a rectangle of that color. The `fillRect()` parameters are, in order, x-axis origin, y-axis origin, width, and height. `fillRect(0, 15, 200, 20)` results in the creation of a rectangle that is 200 units wide by 20 units tall, positioned 0 units from the left and 15 units from the top of the content box.

We can use the CSS `background-size` and `background-position` properties to re-size or relocate this background image, but this is the default size and placement of the yellow box we created in our paint worklet.

We tried to keep the example simple. For more options, look at the canvas documentation. We also add a little bit of complexity later in this tutorial.

Registering the worklet
-----------------------

To use the paint worklet, we need to register it using `addModule()` and include it in our CSS, ensuring the CSS selector matches a DOM node in our HTML

The setup and design of our paint worklet took place in the external script shown above. We need to register that worklet from our main script.

```js
CSS.paintWorklet.addModule("nameOfPaintWorkletFile.js");
```

This can be done using the paint worklet's `addModule()` method in a `<script>` within the main HTML or in an external JavaScript file linked from the document.

Using the paint worklet
-----------------------

In our example, the paintworklet is stored alongside the main script file. To use it, we first register it:

```js
CSS.paintWorklet.addModule("header-highlight.js");
```

### Reference the paint worklet in CSS

Once we have a registered paint worklet, we can use it in CSS. Employ the CSS `paint()` function like we would any other `<image>` type, using the same string identifier we used in the paintworklet's `registerPaint()` function.

```css
.fancy {
  background-image: paint(headerHighlight);
}
```

### Putting it together

We can then add the fancy class to any element on the page to add a yellow box as a background:

```html
<h1 class="fancy">My Cool Header</h1>
```

The following example will look like the image above in browsers supporting the CSS Painting API.

While you can't play with the worklet's script, you can alter the `background-size` and `background-position` to change the size and location of the background image.

PaintSize
---------

In the example above, we created a 20x200 unit box, painted 15 units from the top of the element it is the same regardless of the size of the element. If the text is small, the yellow box looks like a huge underline. If the text is huge, the box might look like an bar above the first three letters. It would be better if the background image was relative to the size of the element — we can use the element's `paintSize` property to ensure the background image is proportional to the size of the element's box model size.

![The background is 50% of the height and 60% of the width of the element](/en-US/docs/Web/API/CSS_Painting_API/Guide/mycoolheadersized.png)

In the above image, the background proportional to the size of the element. The 3rd example has `width: 50%`; set on the block level element, making the element narrower and therefore the background image narrower.

### The paint worklet

The code to do this looks like so:

```js
registerPaint(
  "headerHighlight",
  class {
    static get contextOptions() {
      return { alpha: true };
    }

    /\*
 ctx is the 2D drawing context
 size is the paintSize, the dimensions (height and width) of the box being painted
 \*/
    paint(ctx, size) {
      ctx.fillStyle = "hsl(55 90% 60% / 100%)";
      ctx.fillRect(0, size.height / 3, size.width \* 0.4, size.height \* 0.6);
    }
  },
);
```

This code example has two differences from our first example:

1. We've included a second argument, which is the paint size.
2. We've changed the dimensions and positioning of our rectangle to be relative to the size of the element box rather than absolute values.

We can pass the second parameter into the `paint()` function to give us access to the width and the height of the element, via `.width` and `.height` properties.

Our header now has a highlight that changes according to its size.

### Using the paint worklet

#### HTML

```html
<h1 class="fancy">Largest Header</h1>
<h6 class="fancy">Smallest Header</h6>
<h3 class="fancy half">50% width header</h3>
```

#### CSS

While you can't play with the worklet's script, you can alter the element's `font-size` and `width` to change the size of the background image.

```css
.fancy {
  background-image: paint(headerHighlight);
}
.half {
  width: 50%;
}
```

#### JavaScript

```js
CSS.paintWorklet.addModule("header-highlight.js");
```

#### Result

In browsers that support the CSS Paint API, the elements in the example below should get yellow backgrounds proportional to their font size.

Custom properties
-----------------

In addition to accessing the size of the element, the worklet can also have access to CSS custom properties and regular CSS properties.

```js
registerPaint(
  "cssPaintFunctionName",
  class {
    static get inputProperties() {
      return ["PropertyName1", "--customPropertyName2"];
    }
    static get inputArguments() {
      return ["<color>"];
    }
    static get contextOptions() {
      return { alpha: true };
    }

    paint(drawingContext, elementSize, styleMap) {
      // Paint code goes here.
    }
  },
);
```

The three parameters of the `paint()` function include the drawing context, paint size and properties. To be able to access properties, we include the static `inputProperties()` method, which provides live access to CSS properties, including regular properties and custom properties, and returns an `array` of property names. We'll take a look at `inputArguments` in the last section.

Let's create a list of items with a background image that rotates between three different colors and three widths.

![The width and color of the background image changes based on the custom properties](/en-US/docs/Web/API/CSS_Painting_API/Guide/boxbg.png)

To achieve this we'll define two custom CSS properties, `--boxColor` and `--widthSubtractor`.

### The paint worklet

In our worklet, we can reference these custom properties.

```js
registerPaint(
  "boxbg",
  class {
    static get contextOptions() {
      return { alpha: true };
    }

    /\*
 use this function to retrieve any custom properties (or regular properties, such as 'height')
 defined for the element, return them in the specified array
 \*/
    static get inputProperties() {
      return ["--boxColor", "--widthSubtractor"];
    }

    paint(ctx, size, props) {
      /\*
 ctx -> drawing context
 size -> paintSize: width and height
 props -> properties: get() method
 \*/

      ctx.fillStyle = props.get("--boxColor");
      ctx.fillRect(
        0,
        size.height / 3,
        size.width \* 0.4 - props.get("--widthSubtractor"),
        size.height \* 0.6,
      );
    }
  },
);
```

We used the `inputProperties()` method in the `registerPaint()` class to get the values of two custom properties set on an element that has `boxbg` applied to it and then used those within our `paint()` function. The `inputProperties()` method can return all properties affecting the element, not just custom properties.

### Using the paint worklet

#### HTML

```html
<ul>
  <li>item 1</li>
  <li>item 2</li>
  <li>item 3</li>
  <li>item 4</li>
  <li>item 5</li>
  <li>item 6</li>
  <li>item 7</li>
  <li>item 8</li>
  <li>item 9</li>
  <li>item 10</li>
  <li>item 11</li>
  <li>item 12</li>
  <li>item 13</li>
  <li>item 14</li>
  <li>item 15</li>
  <li>item 16</li>
  <li>item 17</li>
  <li>item</li>
</ul>
```

#### CSS

In our CSS, we define the `--boxColor` and `--widthSubtractor` custom properties.

```css
li {
  background-image: paint(boxbg);
  --boxColor: hsl(55 90% 60% / 100%);
}

li:nth-of-type(3n) {
  --boxColor: hsl(155 90% 60% / 100%);
  --widthSubtractor: 20;
}

li:nth-of-type(3n + 1) {
  --boxColor: hsl(255 90% 60% / 100%);
  --widthSubtractor: 40;
}
```

#### JavaScript

In our `<script>` we register the worklet:

```js
CSS.paintWorklet.addModule("boxbg.js");
```

#### Result

While you can't play with the worklet's script, you can alter the custom property values in DevTools to change the colors and width of the background image.

Adding complexity
-----------------

The above examples might not seem very exciting, as you could recreate them in a few different ways with existing CSS properties, e.g. by positioning some decorative generated content with `::before,` or including `background: linear-gradient(yellow, yellow) 0 15px / 200px 20px no-repeat;` What makes the CSS Painting API so interesting and powerful is that you can create complex images, passing variables, that automatically resize.

Let's take a look at a more complex paint example.

### The paint worklet

```js
registerPaint(
  "headerHighlight",
  class {
    static get inputProperties() {
      return ["--highColor"];
    }
    static get contextOptions() {
      return { alpha: true };
    }

    paint(ctx, size, props) {
      /\* set where to start the highlight & dimensions \*/
      const x = 0;
      const y = size.height \* 0.3;
      const blockWidth = size.width \* 0.33;
      const highlightHeight = size.height \* 0.85;
      const color = props.get("--highColor");

      ctx.fillStyle = color;

      ctx.beginPath();
      ctx.moveTo(x, y);
      ctx.lineTo(blockWidth, y);
      ctx.lineTo(blockWidth + highlightHeight, highlightHeight);
      ctx.lineTo(x, highlightHeight);
      ctx.lineTo(x, y);
      ctx.closePath();
      ctx.fill();

      /\* create the dashes \*/
      for (let start = 0; start < 8; start += 2) {
        ctx.beginPath();
        ctx.moveTo(blockWidth + start \* 10 + 10, y);
        ctx.lineTo(blockWidth + start \* 10 + 20, y);
        ctx.lineTo(
          blockWidth + start \* 10 + 20 + highlightHeight,
          highlightHeight,
        );
        ctx.lineTo(
          blockWidth + start \* 10 + 10 + highlightHeight,
          highlightHeight,
        );
        ctx.lineTo(blockWidth + start \* 10 + 10, y);
        ctx.closePath();
        ctx.fill();
      }
    } // paint
  },
);
```

### Using the paint worklet

We can then create a little HTML that will accept this image as backgrounds:

```html
<h1 class="fancy">Largest Header</h1>
<h3 class="fancy">Medium size header</h3>
<h6 class="fancy">Smallest Header</h6>
```

We give each header a different value for the `--highColor` custom property

```css
.fancy {
  background-image: paint(headerHighlight);
}
h1 {
  --highColor: hsl(155 90% 60% / 70%);
}
h3 {
  --highColor: hsl(255 90% 60% / 50%);
}
h6 {
  --highColor: hsl(355 90% 60% / 30%);
}
```

And we register our worklet

```js
CSS.paintWorklet.addModule("header-highlight.js");
```

The result looks like this:

While you can't edit the worklet itself, you can play around with the CSS and HTML. Maybe try `float` and `clear` on the headers?

You could try making the background images above without the CSS Paint API. It is doable, but you would have to declare a different, fairly complex linear gradient for each different color you wanted to create. With the CSS Paint API, one worklet can be reused, with different colors passed in this case.

Passing parameters
------------------

**Note:** The following example requires the Experimental Web Platform features flag to be enabled in Chrome or Edge by visiting `about://flags`.

With the CSS Paint API, we not only have access to custom properties and regular properties, but we can pass custom arguments to the `paint()` function as well.

We can add these extra arguments when we call the function in the CSS. Let's say we want to sometimes stroke our background instead of fill it — let's pass in an extra argument for this occasion.

```css
li {
  background-image: paint(hollowHighlights, stroke);
}
```

Now we can use the `inputArguments()` method in the `registerPaint()` class to access the custom argument we have added to our `paint()` function.

```js
static get inputArguments() { return ['\*']; }
```

We then have access to that argument.

```js
paint(ctx, size, props, args) {

  // use our custom arguments
  const hasStroke = args[0].toString();

  // if stroke arg is 'stroke', don't fill
  if (hasStroke === 'stroke') {
    ctx.fillStyle = 'transparent';
    ctx.strokeStyle = color;
  }
  // …
}
```

We can also specify that we want a particular type of argument.

Let's say we add a second argument with how many pixels wide we want the stroke to be:

```css
li {
  background-image: paint(hollowHighlights, stroke, 10px);
}
```

When we `get` our list of argument values, we can ask specifically for a `<length>` unit.

```js
static get inputArguments() { return ['\*', '<length>']; }
```

In this case, we specifically requested the `<length>` attribute. The first element in the returned array will be a `CSSUnparsedValue`. The second will be a `CSSStyleValue`.

If the custom argument is a CSS value, for instance a unit, we can invoke Typed OM CSSStyleValue class (and sub classes) by using the value type keyword when we retrieve it in the `registerPaint()` function.

Now we can access the type and value properties, meaning we can get the number of pixels and a number type right out of the box. (Admittedly, `ctx.lineWidth` takes a float as a value rather than a value with length units, but for example's sake…)

```js
paint(ctx, size, props, args) {

  const strokeWidth = args[1];

  if (strokeWidth.unit === 'px') {
    ctx.lineWidth = strokeWidth.value;
  } else {
    ctx.lineWidth = 1.0;
  }

  // …
}
```

It's worth noting the difference between using custom properties to control different parts of this worklet and the arguments set out here. Custom properties (and in fact any properties on the style map) are global — they can be used elsewhere within our CSS (and JS).

You may for example have a `--mainColor`, which will be useful for setting the color within a `paint()` function, but can also be used to set colors elsewhere in your CSS. If you wanted to change it specifically for paint, it could prove difficult. This is where the custom argument feature comes in handy. Another way to think about it is that arguments are set to control what you are actually drawing, whereas properties are set to control styling.

![The list items have a background image that is either pink, purple or green, with different stroke widths, and the green one being filled.](/en-US/docs/Web/API/CSS_Painting_API/Guide/hollowfilled.png)

Now we can really start to see the benefits of this API, if we can control a myriad of drawing parameters from our CSS through both custom properties and extra `paint()` function arguments, then we can really start to build reusable and highly controllable styling functions.

### The paint worklet

```js
registerPaint(
  "hollowHighlights",
  class {
    static get inputProperties() {
      return ["--boxColor"];
    }
    // Input arguments that can be passed to the `paint` function
    static get inputArguments() {
      return ["\*", "<length>"];
    }

    static get contextOptions() {
      return { alpha: true };
    }

    paint(ctx, size, props, args) {
      // ctx -> drawing context
      // size -> size of the box being painted
      // props -> list of custom properties available to the element
      // args -> list of arguments set when calling the paint() function in the CSS

      // where to start the highlight & dimensions
      const x = 0;
      const y = size.height \* 0.3;
      const blockWidth = size.width \* 0.33;
      const blockHeight = size.height \* 0.85;

      // the values passed in the paint() function in the CSS
      const color = props.get("--boxColor");
      const strokeType = args[0].toString();
      const strokeWidth = parseInt(args[1]);

      // set the stroke width
      ctx.lineWidth = strokeWidth ?? 1.0;
      // set the fill type
      if (strokeType === "stroke") {
        ctx.fillStyle = "transparent";
        ctx.strokeStyle = color;
      } else if (strokeType === "filled") {
        ctx.fillStyle = color;
        ctx.strokeStyle = color;
      } else {
        ctx.fillStyle = "none";
        ctx.strokeStyle = "none";
      }

      // block
      ctx.beginPath();
      ctx.moveTo(x, y);
      ctx.lineTo(blockWidth, y);
      ctx.lineTo(blockWidth + blockHeight, blockHeight);
      ctx.lineTo(x, blockHeight);
      ctx.lineTo(x, y);
      ctx.closePath();
      ctx.fill();
      ctx.stroke();
      // dashes
      for (let i = 0; i < 4; i++) {
        let start = i \* 2;
        ctx.beginPath();
        ctx.moveTo(blockWidth + start \* 10 + 10, y);
        ctx.lineTo(blockWidth + start \* 10 + 20, y);
        ctx.lineTo(blockWidth + start \* 10 + 20 + blockHeight, blockHeight);
        ctx.lineTo(blockWidth + start \* 10 + 10 + blockHeight, blockHeight);
        ctx.lineTo(blockWidth + start \* 10 + 10, y);
        ctx.closePath();
        ctx.fill();
        ctx.stroke();
      }
    } // paint
  },
);
```

### Using the paint worklet

We can set different colors, stroke widths, and pick whether the background image should be filled or hollow:

```css
li {
  --boxColor: hsl(155 90% 60% / 50%);
  background-image: paint(hollowHighlights, stroke, 5px);
}

li:nth-of-type(3n) {
  --boxColor: hsl(255 90% 60% / 50%);
  background-image: paint(hollowHighlights, filled, 3px);
}

li:nth-of-type(3n + 1) {
  --boxColor: hsl(355 90% 60% / 50%);
  background-image: paint(hollowHighlights, stroke, 1px);
}
```

```
<ul>
  <li>item 1</li>
  <li>item 2</li>
  <li>item 3</li>
  <li>item 4</li>
  <li>item 5</li>
  <li>item 6</li>
  <li>item 7</li>
  <li>item 8</li>
  <li>item 9</li>
  <li>item 10</li>
  <li>item 11</li>
  <li>item 12</li>
  <li>item 13</li>
  <li>item 14</li>
  <li>item 15</li>
  <li>item 16</li>
  <li>item 17</li>
  <li>item</li>
</ul>
```

In our `<script>` we register the worklet:

```js
CSS.paintWorklet.addModule("hollow.js");
```

See also
--------

* CSS Painting API
* CSS Typed Object Model API


MessageChannel: MessageChannel() constructor - Web APIs

MessageChannel: MessageChannel() constructor
============================================

 The **`MessageChannel()`** constructor of the `MessageChannel`
 interface returns a new `MessageChannel` object with two new
 `MessagePort` objects.

**Note:** This feature is available in Web Workers

Syntax
------

```js
new MessageChannel()
```

### Parameters

None (`undefined`).

### Return value

A new `MessageChannel` object.

Examples
--------

 In the following code block, you can see a new channel being created using the
 `MessageChannel()` constructor.
 When the `<iframe>` has loaded,
 we pass `port2` to the `<iframe>` using `MessagePort.postMessage` along with a message.
 The `handleMessage` handler then responds to a message being sent back from the
 `<iframe>` (using `onmessage`), putting it into a paragraph.
 The `port1` is listened to, to check when the message arrives.

```js
const channel = new MessageChannel();
const para = document.querySelector("p");

const ifr = document.querySelector("iframe");
const otherWindow = ifr.contentWindow;

ifr.addEventListener("load", iframeLoaded, false);

function iframeLoaded() {
  otherWindow.postMessage("Hello from the main page!", "\*", [channel.port2]);
}

channel.port1.onmessage = handleMessage;
function handleMessage(e) {
  para.innerHTML = e.data;
}
```

 For a full working example,
 see our channel messaging basic demo
 on GitHub (run it live too).

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-messagechannel-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Using channel messaging


MessageChannel: port1 property - Web APIs

MessageChannel: port1 property
==============================

 The **`port1`** read-only property of the
 `MessageChannel` interface returns the first port of the message channel —
 the port attached to the context that originated the channel.

**Note:** This feature is available in Web Workers

Value
-----

 A `MessagePort` object, the first port of the channel, that is the port
 attached to the context that originated the channel.

Examples
--------

 In the following code block, you can see a new channel being created using the
 `MessageChannel()` constructor. When the
 `<iframe>` has loaded, we pass `port2` to the
 `<iframe>` using `MessagePort.postMessage` along with a
 message. The `handleMessage` handler then responds to a message being sent
 back from the `<iframe>` (using `onmessage`),
 putting it into a paragraph. The `handleMessage` method is associated to the
 `port1` to listen when the message arrives.

```js
const channel = new MessageChannel();
const para = document.querySelector("p");

const ifr = document.querySelector("iframe");
const otherWindow = ifr.contentWindow;

ifr.addEventListener("load", iframeLoaded, false);

function iframeLoaded() {
  otherWindow.postMessage("Hello from the main page!", "\*", [channel.port2]);
}

channel.port1.onmessage = handleMessage;
function handleMessage(e) {
  para.innerHTML = e.data;
}
```

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-messagechannel-port1-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Using channel messaging


MessageChannel: port2 property - Web APIs

MessageChannel: port2 property
==============================

 The **`port2`** read-only property of the
 `MessageChannel` interface returns the second port of the message channel —
 the port attached to the context at the other end of the channel, which the message is
 initially sent to.

**Note:** This feature is available in Web Workers

Value
-----

 A `MessagePort` object representing the second port of the channel, the
 port attached to the context at the other end of the channel.

Examples
--------

 In the following code block, you can see a new channel being created using the
 `MessageChannel()` constructor. When the
 IFrame has loaded, we pass `port2` to the IFrame using
 `MessagePort.postMessage` along with a message. The
 `handleMessage` handler then responds to a message being sent back from the
 IFrame (using `onmessage`), putting it into a paragraph.
 `port1` is listened to, to check when the message arrives.

```js
const channel = new MessageChannel();
const para = document.querySelector("p");

const ifr = document.querySelector("iframe");
const otherWindow = ifr.contentWindow;

ifr.addEventListener("load", iframeLoaded, false);

function iframeLoaded() {
  otherWindow.postMessage("Hello from the main page!", "\*", [channel.port2]);
}

channel.port1.onmessage = handleMessage;
function handleMessage(e) {
  para.innerHTML = e.data;
}
```

For a full working example, see our channel messaging basic demo on GitHub (run it live too).

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-messagechannel-port2-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Using channel messaging


TextMetrics: actualBoundingBoxAscent property - Web APIs

TextMetrics: actualBoundingBoxAscent property
=============================================

The read-only **`actualBoundingBoxAscent`** property of the `TextMetrics` interface is a `double` giving the distance from the horizontal line indicated by the `CanvasRenderingContext2D.textBaseline` attribute to the top of the bounding rectangle used to render the text, in CSS pixels.

Examples
--------

```js
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const text = ctx.measureText("foo"); // returns TextMetrics object

text.actualBoundingBoxAscent; // 8;
```

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-textmetrics-actualboundingboxascent-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `TextMetrics`


TextMetrics: ideographicBaseline property - Web APIs

TextMetrics: ideographicBaseline property
=========================================

The read-only `ideographicBaseline` property of the `TextMetrics` interface is a `double` giving the distance from the horizontal line indicated by the `CanvasRenderingContext2D.textBaseline` property to the ideographic baseline of the line box, in CSS pixels.

Examples
--------

```js
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const text = ctx.measureText("foo"); // returns TextMetrics object

text.ideographicBaseline; // -1.201171875;
```

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-textmetrics-ideographicbaseline-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `TextMetrics`


TextMetrics: actualBoundingBoxLeft property - Web APIs

TextMetrics: actualBoundingBoxLeft property
===========================================

The read-only `actualBoundingBoxLeft` property of the `TextMetrics` interface is a `double` giving the distance parallel to the baseline from the alignment point given by the `CanvasRenderingContext2D.textAlign` property to the left side of the bounding rectangle of the given text, in CSS pixels; positive numbers indicating a distance going left from the given alignment point.

Examples
--------

```js
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const text = ctx.measureText("foo"); // returns TextMetrics object

text.actualBoundingBoxLeft; // 0;
```

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-textmetrics-actualboundingboxleft-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `TextMetrics`


TextMetrics: actualBoundingBoxRight property - Web APIs

TextMetrics: actualBoundingBoxRight property
============================================

The read-only `actualBoundingBoxRight` property of the `TextMetrics` interface is a `double` giving the distance parallel to the baseline from the alignment point given by the `CanvasRenderingContext2D.textAlign` property to the right side of the bounding rectangle of the given text, in CSS pixels.

Examples
--------

```js
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const text = ctx.measureText("foo"); // returns TextMetrics object

text.actualBoundingBoxRight; // 15.633333333333333;
```

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-textmetrics-actualboundingboxright-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `TextMetrics`


TextMetrics: fontBoundingBoxDescent property - Web APIs

TextMetrics: fontBoundingBoxDescent property
============================================

The read-only `fontBoundingBoxDescent` property of the `TextMetrics` interface returns the distance from the horizontal line indicated by the `CanvasRenderingContext2D.textBaseline` attribute to the bottom of the bounding rectangle of all the fonts used to render the text, in CSS pixels.

Value
-----

A number, in CSS pixels.

Examples
--------

The code below shows how you can get the `fontBoundingBoxDescent` for text in a particular font.

```js
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");

ctx.font = "25px serif";
const text = "Foo";

const textMetrics = ctx.measureText("foo"); // returns TextMetrics object
const descentCssPixels = textMetrics.fontBoundingBoxDescent;
```

```
<p id="log"></p>
```

```
const log = document.getElementById("log");
log.innerText = `fontBoundingBoxDescent: ${descentCssPixels}`;
```

The descent in CSS pixels for the text "Foo" in a 25px serif font is shown below.

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-textmetrics-fontboundingboxdescent-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `TextMetrics.fontBoundingBoxAscent`
* `TextMetrics`


TextMetrics: fontBoundingBoxAscent property - Web APIs

TextMetrics: fontBoundingBoxAscent property
===========================================

The read-only `fontBoundingBoxAscent` property of the `TextMetrics` interface returns the distance from the horizontal line indicated by the `CanvasRenderingContext2D.textBaseline` attribute, to the top of the highest bounding rectangle of all the fonts used to render the text, in CSS pixels.

Value
-----

A number, in CSS pixels.

Examples
--------

The code below shows how you can get the `fontBoundingBoxAscent` for some text in a particular font.

```js
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");

ctx.font = "25px serif";
const text = "Foo";

const textMetrics = ctx.measureText("foo"); // returns TextMetrics object
const ascentCssPixels = textMetrics.fontBoundingBoxAscent;
```

```
<p id="log"></p>
```

```
const log = document.getElementById("log");
log.innerText = `fontBoundingBoxAscent: ${ascentCssPixels}`;
```

The ascent in CSS pixels for the text "Foo" in a 25px serif font is shown below.

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-textmetrics-fontboundingboxascent-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `TextMetrics.fontBoundingBoxDescent`
* `TextMetrics`


TextMetrics: width property - Web APIs

TextMetrics: width property
===========================

The read-only **`width`** property of the `TextMetrics` interface contains the text's advance width (the width of that inline box) in CSS pixels.

Examples
--------

Start with this `<canvas>` element:

```html
<canvas id="canvas"></canvas>
```

You can get a `TextMetrics` object using the following code:

```js
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

let text = ctx.measureText("foo"); // TextMetrics object
text.width; // 16;
```

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-textmetrics-width-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `TextMetrics`


TextMetrics: emHeightAscent property - Web APIs

TextMetrics: emHeightAscent property
====================================

The read-only `emHeightAscent` property of the `TextMetrics` interface returns the distance from the horizontal line indicated by the `CanvasRenderingContext2D.textBaseline` property to the top of the *em* square in the line box, in CSS pixels.

Value
-----

A number, in CSS pixels.

Examples
--------

```js
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const text = ctx.measureText("foo"); // returns TextMetrics object

text.emHeightAscent; // 7.59765625;
```

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-textmetrics-emheightascent-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `TextMetrics`


TextMetrics: alphabeticBaseline property - Web APIs

TextMetrics: alphabeticBaseline property
========================================

The read-only `alphabeticBaseline` property of the `TextMetrics` interface is a `double` giving the distance from the horizontal line indicated by the `CanvasRenderingContext2D.textBaseline` property to the alphabetic baseline of the line box, in CSS pixels.

Examples
--------

```js
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const text = ctx.measureText("foo"); // returns TextMetrics object

text.alphabeticBaseline; // -0;
```

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-textmetrics-alphabeticbaseline-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `TextMetrics`


TextMetrics: hangingBaseline property - Web APIs

TextMetrics: hangingBaseline property
=====================================

The read-only `hangingBaseline` property of the `TextMetrics` interface is a `double` giving the distance from the horizontal line indicated by the `CanvasRenderingContext2D.textBaseline` property to the hanging baseline of the line box, in CSS pixels.

Examples
--------

```js
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const text = ctx.measureText("foo"); // returns TextMetrics object

text.hangingBaseline; // 6.078125;
```

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-textmetrics-hangingbaseline-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `TextMetrics`


TextMetrics: actualBoundingBoxDescent property - Web APIs

TextMetrics: actualBoundingBoxDescent property
==============================================

The read-only `actualBoundingBoxDescent` property of the `TextMetrics` interface is a `double` giving the distance from the horizontal line indicated by the `CanvasRenderingContext2D.textBaseline` attribute to the bottom of the bounding rectangle used to render the text, in CSS pixels.

Examples
--------

```js
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const text = ctx.measureText("foo"); // returns TextMetrics object

text.actualBoundingBoxDescent; // 0;
```

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-textmetrics-actualboundingboxdescent-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `TextMetrics`


TextMetrics: emHeightDescent property - Web APIs

TextMetrics: emHeightDescent property
=====================================

The read-only `emHeightDescent` property of the `TextMetrics` interface returns the distance from the horizontal line indicated by the `CanvasRenderingContext2D.textBaseline` property to the bottom of the *em* square in the line box, in CSS pixels.

Value
-----

A number, in CSS pixels.

Examples
--------

```js
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const text = ctx.measureText("foo"); // returns TextMetrics object

text.emHeightDescent; // -2.40234375;
```

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-textmetrics-emheightdescent-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `TextMetrics`


PushMessageData: json() method - Web APIs

PushMessageData: json() method
==============================

The **`json()`** method of the `PushMessageData` interface extracts push message data by parsing it as a JSON string and returning the result.

Syntax
------

```js
json()
```

### Parameters

None.

### Return value

The result of parsing push event data as JSON. This could be anything that can be represented by JSON — an object, an array, a string, a number…

Examples
--------

```js
self.addEventListener("push", (event) => {
  const myData = event.data.json();

  // do something with your data
});
```

Specifications
--------------

| Specification |
| --- |
| Push API # dom-pushmessagedata-json |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


PushMessageData: arrayBuffer() method - Web APIs

PushMessageData: arrayBuffer() method
=====================================

The **`arrayBuffer()`** method of the `PushMessageData` interface extracts push message data as an `ArrayBuffer` object.

Syntax
------

```js
arrayBuffer()
```

### Parameters

None.

### Return value

An `ArrayBuffer`.

Examples
--------

```js
self.addEventListener("push", (event) => {
  const buffer = event.data.arrayBuffer();

  // do something with your array buffer
});
```

Specifications
--------------

| Specification |
| --- |
| Push API # dom-pushmessagedata-arraybuffer |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


PushMessageData: blob() method - Web APIs

PushMessageData: blob() method
==============================

The **`blob()`** method of the `PushMessageData` interface extracts push message data as a `Blob` object.

Syntax
------

```js
blob()
```

### Parameters

None.

### Return value

A `Blob`.

Examples
--------

```js
self.addEventListener("push", (event) => {
  const blob = event.data.blob();

  // do something with your Blob
});
```

Specifications
--------------

| Specification |
| --- |
| Push API # dom-pushmessagedata-blob |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


PushMessageData: text() method - Web APIs

PushMessageData: text() method
==============================

The **`text()`** method of the `PushMessageData` interface extracts push message data as a plain text string.

Syntax
------

```js
text()
```

### Parameters

None.

### Return value

A string.

Examples
--------

```js
self.addEventListener("push", (event) => {
  const textObj = event.data.text();

  // do something with your text
});
```

Specifications
--------------

| Specification |
| --- |
| Push API # dom-pushmessagedata-text |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


AudioEncoder: close() method - Web APIs

AudioEncoder: close() method
============================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`close()`** method of the `AudioEncoder` interface ends all pending work and releases system resources.

Syntax
------

```js
close()
```

### Parameters

None.

### Return value

None (`undefined`).

Examples
--------

The following example closes the `AudioEncoder`.

```js
AudioEncoder.close();
```

Specifications
--------------

| Specification |
| --- |
| WebCodecs # dom-audioencoder-close |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


AudioEncoder: state property - Web APIs

AudioEncoder: state property
============================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`state`** read-only property of the `AudioEncoder` interface returns the current state of the underlying codec.

Value
-----

A string containing one of the following values:

`"unconfigured"`

The codec is not configured for decoding.

`"configured"`

The codec has a valid configuration and is ready.

`"closed"`

The codec is no longer usable and system resources have been released.

Examples
--------

The following example prints the state of the `AudioEncoder` to the console.

```js
console.log(AudioEncoder.state);
```

Specifications
--------------

| Specification |
| --- |
| WebCodecs # dom-audioencoder-state |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


AudioEncoder: dequeue event - Web APIs

AudioEncoder: dequeue event
===========================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`dequeue`** event of the `AudioEncoder` interface fires to signal a decrease in `AudioEncoder.encodeQueueSize`.

This eliminates the need for developers to use a `setTimeout()` poll to determine when the queue has decreased, and more work should be queued up.

Syntax
------

Use the event name in methods like `addEventListener()`, or set an event handler property.

```js
addEventListener("dequeue", (event) => {});

ondequeue = (event) => {};
```

Example
-------

```js
audioEncoder.addEventListener("dequeue", (event) => {
  // Queue up more encoding work
});
```

Specifications
--------------

| Specification |
| --- |
| WebCodecs # eventdef-audioencoder-dequeue |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


AudioEncoder: isConfigSupported() static method - Web APIs

AudioEncoder: isConfigSupported() static method
===============================================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`isConfigSupported()`** static method of the `AudioEncoder` interface checks if the given config is supported (that is, if `AudioEncoder` objects can be successfully configured with the given config).

Syntax
------

```js
AudioEncoder.isConfigSupported(config)
```

### Parameters

`config`

The dictionary object accepted by `AudioEncoder.configure`

### Return value

A `Promise` that resolves with an object containing the following members:

`supported`

A boolean value which is `true` if the given config is supported by the encoder.

`config`

A copy of the given config with all the fields recognized by the encoder.

### Exceptions

`TypeError`

Thrown if the provided `config` is invalid; that is, if doesn't have required values (such as an empty `codec` field) or has invalid values (such as a negative `sampleRate`).

Examples
--------

The following example tests if the browser supports several audio codecs.

```js
const codecs = ["mp4a.40.2", "mp3", "alaw", "ulaw"];
const configs = [];
for (const codec of codecs) {
  configs.push({
    codec,
    sampleRate: 48000,
    numberOfChannels: 1,
    not\_supported\_field: 123,
  });
}
for (const config of configs) {
  const support = await AudioEncoder.isConfigSupported(config);
  console.log(
    `AudioEncoder's config ${JSON.stringify(support.config)} support: ${
 support.supported
 }`,
  );
}
```

Specifications
--------------

| Specification |
| --- |
| WebCodecs # dom-audioencoder-isconfigsupported |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


AudioEncoder: encodeQueueSize property - Web APIs

AudioEncoder: encodeQueueSize property
======================================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`encodeQueueSize`** read-only property of the `AudioEncoder` interface returns the number of pending encode requests in the queue.

Value
-----

An integer containing the number of requests.

Examples
--------

The following example prints the size of the queue to the console.

```js
console.log(AudioEncoder.encodeQueueSize);
```

Specifications
--------------

| Specification |
| --- |
| WebCodecs # dom-audioencoder-encodequeuesize |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


AudioEncoder: reset() method - Web APIs

AudioEncoder: reset() method
============================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`reset()`** method of the `AudioEncoder` interface resets all states including configuration, control messages in the control message queue, and all pending callbacks.

Syntax
------

```js
reset()
```

### Parameters

None.

### Return value

None (`undefined`).

Examples
--------

The following example resets the `AudioEncoder`.

```js
AudioEncoder.reset();
```

Specifications
--------------

| Specification |
| --- |
| WebCodecs # dom-audioencoder-reset |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


AudioEncoder: AudioEncoder() constructor - Web APIs

AudioEncoder: AudioEncoder() constructor
========================================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`AudioEncoder()`** constructor creates a new `AudioEncoder` object with the provided `init.output` callback assigned as the output callback, the provided `init.error` callback as the error callback, and the `AudioEncoder.state` set to `"unconfigured"`.

Syntax
------

```js
new AudioEncoder(init)
```

### Parameters

`init`

An object containing two required callbacks.

`output`

A callback which takes a `EncodedAudioChunk` object as the first argument, and an optional metadata object as the second. The metadata object has one member, `decoderConfig` which has an object as its value containing:

`codec`

A string containing a valid codec string.

`sampleRate`

An integer representing the number of frame samples per second.

`numberOfChannels`

An integer representing the number of audio channels.

`description` Optional

An `ArrayBuffer`, a `TypedArray`, or a `DataView` containing a sequence of codec specific bytes, commonly known as extradata.

`error`

A callback which takes an `Error` object as its only argument.

Examples
--------

In the following example an `AudioEncoder` is created with the two required callback functions, one to deal with the decoded frame and the other to handle errors.

```js
const audioEncoder = new AudioEncoder({
  output: processAudio,
  error: onEncoderError,
});
```

Specifications
--------------

| Specification |
| --- |
| WebCodecs # dom-audioencoder-audioencoder |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


AudioEncoder: configure() method - Web APIs

AudioEncoder: configure() method
================================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`configure()`** method of the `AudioEncoder` interface enqueues a control message to configure the audio encoder for encoding chunks.

Syntax
------

```js
configure(config)
```

### Parameters

`config`

A dictionary object containing the following members:

`codec`

A string containing a valid codec string. See "codecs" parameter for details on codec string construction.

`sampleRate`

An integer representing the number of frame samples per second.

`numberOfChannels`

An integer representing the number of audio channels.

`bitrate` Optional

An integer representing the bitrate.

### Return value

None (`undefined`).

### Exceptions

`TypeError`

Thrown if the provided `config` is invalid.

`InvalidStateError` `DOMException`

Thrown if the `state` is `"closed"`.

`NotSupportedError` `DOMException`

Thrown if the provided `config` is valid but the user agent cannot provide a codec that can decode this profile.

Examples
--------

The following example creates a new `AudioEncoder` and configures it with some of the available options.

```js
const init = {
  output: handleOutput,
  error: (e) => {
    console.log(e.message);
  },
};

let config = {
  codec: "opus",
  sampleRate: 44100,
  numberOfChannels: 2,
  bitrate: 128\_000, // 128 kbps
};

let encoder = new AudioEncoder(init);
encoder.configure(config);
```

Specifications
--------------

| Specification |
| --- |
| WebCodecs # dom-audioencoder-configure |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


AudioEncoder: flush() method - Web APIs

AudioEncoder: flush() method
============================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`flush()`** method of the `AudioEncoder` interface returns a Promise that resolves once all pending messages in the queue have been completed.

Syntax
------

```js
flush()
```

### Parameters

None.

### Return value

A `Promise` that resolves with undefined.

### Exceptions

`InvalidStateError` `DOMException`

Thrown if the Promise is rejected because the `state` is not `"configured"`.

Examples
--------

The following example flushes the `AudioEncoder`.

```js
AudioEncoder.flush();
```

Specifications
--------------

| Specification |
| --- |
| WebCodecs # dom-audioencoder-flush |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


AudioEncoder: encode() method - Web APIs

AudioEncoder: encode() method
=============================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`encode()`** method of the `AudioEncoder` interface enqueues a control message to encode a given `AudioData` object.

Syntax
------

```js
encode(data)
```

### Parameters

`data`

An `AudioData` object.

### Return value

None (`undefined`).

### Exceptions

`InvalidStateError` `DOMException`

Thrown if the `state` is not `"configured"`.

`TypeError`

Thrown if the `AudioData` object has been transferred.

Examples
--------

In the following example `encode` is passed an `AudioData` object.

```js
encoder.encode(data);
```

Specifications
--------------

| Specification |
| --- |
| WebCodecs # dom-audioencoder-encode |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HTMLImageElement: alt property - Web APIs

HTMLImageElement: alt property
==============================

The `HTMLImageElement` property **`alt`** provides fallback (alternate) text to display when the image specified by the `<img>` element is not loaded.

This may be the case because of an error, because the user has disabled the loading of images, or because the image hasn't finished loading yet.

 Perhaps the most important reason to use the `alt` property is to support accessibility, as the `alt` text may be used by screen readers and other assistive technologies to help people with a disability make full use of your content.
 It will be read aloud or sent to a braille output device, for example, to support blind or visually impaired users.

>
> **Think of it like this:** When choosing `alt` strings for your images, imagine what you would say when reading the page to someone over the phone without mentioning that there's an image on the page.
>
>
>

The alternate text is displayed in the space the image would occupy and should be able to take the place of the image *without altering the meaning of the page*.

Value
-----

A string which contains the alternate text to display when the image is not loaded or for use by assistive devices.

 The `alt` attribute is officially mandatory; it's meant to always be specified.
 If the image doesn't require a fallback (such as for an image which is decorative or an advisory icon of minimal importance), you may specify an empty string (`""`).
 For compatibility reasons, browsers generally will accept an image without an `alt` attribute, but you should try to get into the habit of using it.

Usage notes
-----------

 The fundamental guideline for the `alt` attribute is that every image's alternate text should be able to replace the image *without altering the meaning of the page*. You should never use `alt` for text that could be construed as a caption or title.
 There are separate attributes and elements designed for those purposes.

Examples
--------

 Beyond that, there are additional guidelines for using `alt` appropriately which vary depending on what the image is being used for.
 These are shown in the examples below.

### Decorative images

 Images with no semantic meaning—such as those which are solely decorative—or of limited informational value, should have their `alt` attributes set to the empty string (`""`).
 This is shown in the example below.

#### HTML

In the HTML for this example, shown below, the `<img>` element includes the `alt` property, which will prevent the image from having any alternate text, since it's a decorative detail.

```html
<div class="container">
  <div class="left-margin">
    <img src="/files/16861/margin-flourish.svg" alt="" />
  </div>
  <div class="contents">
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque quis orci
      ligula. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ac
      neque libero. Vivamus consectetur rhoncus elit eget porta. Etiam pulvinar
      ex id sapien laoreet, quis aliquet odio lobortis. Nam ac mauris at risus
      laoreet cursus vitae et sapien. Etiam molestie auctor eros, ac porta risus
      scelerisque sit amet. Ut nunc neque, porta eu auctor at, tempor et arcu.
    </p>
  </div>
</div>
```

#### CSS

The CSS for this example sets up the styles for the layout as shown in the result below.

```css
body {
  margin: 0;
  padding: 0;
}

p {
  margin-block-start: 0;
  margin-block-end: 1em;
  margin-top: 0;
  margin-bottom: 1em;
}

.container {
  width: 100vh;
  height: 95vh;
  font:
    16px Arial,
    Helvetica,
    sans-serif;
}

.left-margin {
  background-color: rgb(241 240 237);
  width: 9em;
  height: 100%;
  float: left;
  margin-right: 5px;
  padding-right: 1em;
  display: flex;
  align-items: center;
  justify-content: center;
}

.left-margin img {
  width: 6em;
}

.contents {
  background-color: rgb(241 240 235);
  height: 100%;
  margin-left: 2em;
  padding-top: 1em;
  padding-left: 2em;
  padding-right: 1em;
}
```

#### Result

### Images used as buttons

 When using an image as a button (by using it as the only visible child of an `<a>` element representing a hyperlink), the `alt` attribute must be used to convey the purpose of the button.
 In other words, it should be the same text you would use in a textual button to serve the same purpose.

For example, in the snippet of HTML below, a toolbar which uses icon images as link labels provides `alt` attributes for each giving a textual label to use instead of the icon when the icons cannot be or are intentionally not used.

```html
<li class="toolbar" aria-role="toolbar">
  <a href="songs.html" aria-role="button">
    <img src="songicon.svg" alt="Songs" />
  </a>
  <a href="albums.html" aria-role="button">
    <img src="albumicon.svg" alt="Albums"
 /></a>
  <a href="artists.html" aria-role="button">
    <img src="artisticon.svg" alt="Artists" />
  </a>
  <a href="playlists.html" aria-role="button">
    <img src="playlisticon.svg" alt="Playlists" />
  </a>
</li>
```

### Images containing diagrams or maps

 When an image contains information presented as a diagram, chart, graph, or map, the `alt` text should provide the same information, at least in summary form.
 This is true whether the /me image is in a bitmapped format such as PNG or JPEG or in a vector format like SVG.

* For a map, the `alt` text could be directions to the place indicated by the map, similarly to how you would explain it verbally.
* For a chart, the text could describe the items in the chart and their values.
* For a diagram, the text could be an explanation of the concept presented by the diagram.

 Keep in mind that any text included in diagrams and charts presented in SVG format may be read by screen readers.
 This may impact the decisions you make when writing the `alt` text for the diagram.

### Icons or logos

 Logos (such as corporate or brand logos) and informational icons should use the corresponding text in their `alt` strings.
 That is, if an image is a corporate logo, the `alt` text should be the name of the company.
 If the image is an icon representing a status or other information, the text should be the name of that state.

For example, if an image is a badge that's shown on a page to indicate that the content of the page is new and has been updated recently, the corresponding `alt` text might be "`Updated Recently"` or even "`Updated on 27 August 2019"`.

 In this example, a starburst image with the word "New!" is used to indicate that an article is about something new (and probably supposedly also exciting).
 The `alt` attribute is set to `New Page!` to allow that text to be displayed in place of the image if the image isn't available.
 It is also available to be read by screen readers.

#### HTML

 The HTML below creates a snippet of content from a site using the described icon.
 Note the use of the `alt` attribute on the `<img>`, providing a good substitution string to use in case the image doesn't load.

```html
<div class="container">
  <img
 src="https://www.bitstampede.com/mdn-test/new-page.svg"
 alt="New Page!"
 class="pageinfo-badge" />
  <p class="contents">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque quis orci
    ligula. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ac neque
    libero. Vivamus consectetur rhoncus elit eget porta. Etiam pulvinar ex id
    sapien laoreet, quis aliquet odio lobortis. Nam ac mauris at risus laoreet
    cursus vitae et sapien. Etiam molestie auctor eros, ac porta risus
    scelerisque sit amet. Ut nunc neque, porta eu auctor at, tempor et arcu.
  </p>
</div>
```

#### CSS

The main feature of the CSS here is the use of `clip-path` and `shape-outside` to wrap the text around the icon in an appealing way.

```css
.container {
  max-width: 500px;
}

.pageinfo-badge {
  width: 9em;
  padding-right: 1em;
  float: left;
  clip-path: polygon(
    100% 0,
    100% 50%,
    90% 70%,
    80% 80%,
    70% 90%,
    50% 100%,
    0 100%,
    0 0
  );
  shape-outside: polygon(
    100% 0,
    100% 50%,
    90% 70%,
    80% 80%,
    70% 90%,
    50% 100%,
    0 100%,
    0 0
  );
}

.contents {
  margin-top: 1em;
  font:
    16px Arial,
    Helvetica,
    Verdana,
    sans-serif;
}
```

#### Result

### Other images

 Images showing objects or scenes should have `alt` text describing what's seen in the image.
 A photo of a yellow teapot might literally have its `alt` attribute set to "`A yellow teapot"`.

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-img-alt |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HTMLImageElement: vspace property - Web APIs

HTMLImageElement: vspace property
=================================

**Deprecated:** This feature is no longer recommended. Though some browsers might still support it, it may have already been removed from the relevant web standards, may be in the process of being dropped, or may only be kept for compatibility purposes. Avoid using it, and update existing code if possible; see the compatibility table at the bottom of this page to guide your decision. Be aware that this feature may cease to work at any time.

 The *obsolete* **`vspace`** property of the
 `HTMLImageElement` interface specifies the number of pixels of empty space
 to leave empty on the top and bottom of the `<img>` element when laying
 out the page.

Value
-----

 An integer value specifying the height, in pixels, of the vertical margin to apply to
 the top and bottom sides of the image.

Usage notes
-----------

 The value specified for `vspace` is mapped to the `margin-top`
 and `margin-bottom` properties to specify the height of those margins in
 pixels.

**Warning:** This property is obsolete. You should instead use the CSS
 `margin` property and its longhand forms to establish margins around
 an `<img>`.

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-img-vspace |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HTMLImageElement: decoding property - Web APIs

HTMLImageElement: decoding property
===================================

The **`decoding`** property of the `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"`

Decode the image synchronously for atomic presentation with other content.

`"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. Using the `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.

```js
const img = new Image();
img.decoding = "sync";
img.src = "img/logo.png";
document.body.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 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 `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
--------------

| Specification |
| --- |
| HTML Standard # dom-img-decoding |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* The `HTMLImageElement.decode()` method
* The `<img>` element `decoding` attribute
* What does the image decoding attribute actually do? on tunetheweb.com (2023)


HTMLImageElement: useMap property - Web APIs

HTMLImageElement: useMap property
=================================

 The **`useMap`** property on the
 `HTMLImageElement` interface reflects the value of the
 HTML `usemap` attribute, which is a string
 providing the name of the client-side image map to apply to the image.

Value
-----

 A string providing the page-local URL (that is, a URL that begins
 with the hash or pound symbol, "`#`") of the `<map>` element
 which defines the image map to apply to the image.

You can learn more about client-side image maps in our learning article Add a hitmap on top of an image.

Usage notes
-----------

 The string value of `useMap` must be a valid anchor for a
 `<map>` element. In other words, this string should be the value of the
 appropriate `<map>`'s `name` attribute with a
 pound or hash symbol prepended to it.

Consider a `<map>` that looks like this:

```html
<map name="mainmenu-map">
  <area
 shape="circle"
 coords="25, 25, 75"
 href="/index.html"
 alt="Return to home page" />
  <area shape="rect" coords="25, 25, 100, 150" href="/index.html" alt="Shop" />
</map>
```

 Given the image map named `mainmenu-map`, the image which uses it should
 look something like the following:

```html
<img src="menubox.png" usemap="#mainmenu-map" />
```

 For additional examples (including interactive ones), see the articles about the
 `<map>` and `<area>` elements, as well as the guide to using image maps.

Examples
--------

Try it
------

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-img-usemap |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HTMLImageElement: height property - Web APIs

HTMLImageElement: height property
=================================

 The **`height`** property of the
 `HTMLImageElement` interface indicates the height at which the image is
 drawn, in CSS pixels if the image is being drawn or rendered to any
 visual medium such as the screen or a printer; otherwise, it's the natural, pixel
 density corrected height of the image.

Value
-----

 An integer value indicating the height of the image. The terms in which the height is
 defined depends on whether the image is being rendered to a visual medium or not.

* If the image is being rendered to a visual medium such as a screen or printer, the
 height is expressed in CSS pixels.
* Otherwise, the image's height is represented using its natural (intrinsic) height,
 adjusted for the display density as indicated by
 `naturalHeight`.
Examples
--------

 In this example, two different sizes are provided for an image of a clock using the
 `srcset` attribute. One is 200px wide and the other is 400px
 wide. Further, the `sizes` attribute is provided to specify the
 width at which the image should be drawn given the viewport's width.

### HTML

 Specifically, for viewports up to 400px wide, the image is drawn at a width of 200px;
 otherwise, it's drawn at 300px.

```html
<p>Image height: <span class="size">?</span>px (resize to update)</p>
<img
 src="/en-US/docs/Web/HTML/Element/img/clock-demo-200px.png"
 alt="Clock"
 srcset="
 /en-US/docs/Web/HTML/Element/img/clock-demo-200px.png 200w,
 /en-US/docs/Web/HTML/Element/img/clock-demo-400px.png 400w
 "
 sizes="(max-width: 400px) 200px, 300px" />
```

### JavaScript

 The JavaScript code looks at the `height` to determine the height of the
 image given the width at which it's currently drawn.

```js
const clockImage = document.querySelector("img");
let output = document.querySelector(".size");

const updateHeight = (event) => {
  output.innerText = clockImage.height;
};

window.addEventListener("load", updateHeight);
window.addEventListener("resize", updateHeight);
```

### Result

This example may be easier to try out in its own window.

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-img-height-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `HTMLCanvasElement.height`
* `HTMLObjectElement.height`
* `HTMLVideoElement.height`


HTMLImageElement: decode() method - Web APIs

HTMLImageElement: decode() method
=================================

 The **`decode()`**
 method of the `HTMLImageElement` interface returns a
 `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
 that the image can be rendered immediately upon being added to the DOM. This, in turn,
 prevents the rendering of the next frame after adding the image to the DOM from causing
 a delay while the image loads.

Syntax
------

```js
decode()
```

### Parameters

None.

### Return value

A `Promise` that fulfills with `undefined` once the image data is ready to be used.

### Exceptions

`EncodingError`

 A `DOMException` indicating that an error occurred while decoding the
 image.

Usage notes
-----------

 One potential use case for `decode()`: when loading very large images (for
 example, in an online photo album), you can present a low resolution thumbnail image
 initially and then replace that image with the full-resolution image by instantiating a
 new `HTMLImageElement`, setting its source to the full-resolution image's
 URL, then using `decode()` to get a promise which is resolved once the
 full-resolution image is ready for use. At that time, you can then replace the
 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.

```js
const img = new Image();
img.src = "nebula.jpg";
img
  .decode()
  .then(() => {
    document.body.appendChild(img);
  })
  .catch((encodingError) => {
    // Do something with the error.
  });
```

**Note:** Without a `Promise`-returning method, you
 would add the image to the DOM in a `load` event handler,
 and handle the error in the `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
--------------

| Specification |
| --- |
| HTML Standard # dom-img-decode-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* What does the image decoding attribute actually do? on tunetheweb.com (2023)
* The `HTMLImageElement.decoding` property


HTMLImageElement: loading property - Web APIs

HTMLImageElement: loading property
==================================

The `HTMLImageElement` property **`loading`** is a string whose value provides a hint to the user agent on how to handle the loading of the image which is currently outside the window's visual viewport.

This helps to optimize the loading of the document's contents by postponing loading the image until it's expected to be needed, rather than immediately during the initial page load.

Value
-----

 A string providing a hint to the user agent as to how to best schedule the loading of the image to optimize page performance.
 The possible values are:

`eager`

The default behavior, `eager` tells the browser to load the image as soon as the `<img>` element is processed.

`lazy`

 Tells the user agent to hold off on loading the image until the browser estimates that it will be needed imminently.
 For instance, if the user is scrolling through the document, a value of `lazy` will cause the image to only be loaded shortly before it will appear in the window's visual viewport.

Usage notes
-----------

**Note:** In Firefox, the `loading` attribute must be defined before the `src` attribute, otherwise it has no effect (Firefox bug 1647077).

### JavaScript must be enabled

 Loading is only deferred when JavaScript is enabled.
 This is an anti-tracking measure, because if a user agent supported lazy loading when scripting is disabled, it would still be possible for a site to track a user's approximate scroll position throughout a session, by strategically placing images in a page's markup such that a server can track how many images are requested and when.

### Timing of the load event

 The `load` event is fired when the document has been fully processed.
 When images are loaded eagerly (which is the default), every image in the document must be fetched before the `load` event can fire.

By specifying the value `lazy` for `loading`, you prevent the image from delaying the `load` attribute by the amount of time it takes to request, fetch, and process the image.

 Images whose `loading` attribute is set to `lazy` but are located within the visual viewport immediately upon initial page load are loaded as soon as the layout is known, but their loads do not delay the firing of the `load` event.
 In other words, these images aren't loaded immediately when processing the `<img>` element, but are still loaded as part of the initial page load.
 They just don't affect the timing of the `load` event.

That means that when `load` fires, it's possible that any lazy-loaded images located in the visual viewport may not yet be visible.

### Preventing element shift during image lazy loads

When an image whose loading has been delayed by the `loading` attribute being set to `lazy` is finally loaded, the browser will determine the final size of the `<img>` element based on the style and intrinsic size of the image, then reflow the document as needed to update the positions of elements based on any size change made to the element to fit the image.

 To prevent this reflow from occurring, you should explicitly specify the size of the image's presentation using the image element's `width` and
 `height` attributes.
 By establishing the intrinsic aspect ratio in this manner, you prevent elements from shifting around while the document loads, which can be disconcerting or off-putting at best and can cause users to click the wrong thing at worst, depending on the exact timing of the deferred loads and reflows.

Examples
--------

The `addImageToList()` function shown below adds a photo thumbnail to a list of items, using lazy-loading to avoid loading the image from the network until it's actually needed.

```js
function addImageToList(url) {
  const list = document.querySelector("div.photo-list");

  let newItem = document.createElement("div");
  newItem.className = "photo-item";

  let newImg = document.createElement("img");
  newImg.loading = "lazy";
  newImg.width = 320;
  newImg.height = 240;
  newImg.src = url;

  newItem.appendChild(newImg);
  list.appendChild(newItem);
}
```

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-img-loading |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* The `<img>` element
* Web performance in the MDN Learning Area
* Lazy loading in the MDN web
 performance guide


HTMLImageElement: complete property - Web APIs

HTMLImageElement: complete property
===================================

 The read-only `HTMLImageElement` interface's
 **`complete`** attribute is a Boolean value which indicates
 whether or not the image has completely loaded.

Value
-----

 A Boolean value which is `true` if the image has completely loaded;
 otherwise, the value is `false`.

The image is considered completely loaded if any of the following are true:

* Neither the `src` nor the `srcset`
 attribute is specified.
* The `srcset` attribute is absent and the `src` attribute,
 while specified, is the empty string (`""`).
* The image resource has been fully fetched and has been queued for
 rendering/compositing.
* The image element has previously determined that the image is fully available and
 ready for use.
* The image is "broken;" that is, the image failed to load due to an error or because
 image loading is disabled.

 It's worth noting that due to the image potentially being received asynchronously, the
 value of `complete` may change while your script is running.

Examples
--------

 Consider a photo library app that provides the ability to open images into a lightbox
 mode for improved viewing as well as editing of the image. These photos may be very
 large, so you don't want to wait for them to load, so your code
 uses `async`/`await` to load the images in the background.

 But imagine that you have other code that needs to only run when the image has
 completed loading, such as a command that performs red-eye removal on the image in the
 lightbox. While ideally this command wouldn't even be executed if the image hasn't fully
 loaded, for improved reliability you want to check to ensure this is the case.

 So the `fixRedEyeCommand()` function, which is called by the button that
 triggers red-eye removal, checks the value of the lightbox
 image's `complete` property before attempting to do its work. This is
 demonstrated in the code below.

```js
let lightboxElem = document.querySelector("#lightbox");
let lightboxImgElem = lightboxElem.querySelector("img");
let lightboxControlsElem = lightboxElem.querySelector(".toolbar");

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

async function lightBox(url) {
  lightboxElem.style.display = "block";
  await loadImage("https://somesite.net/huge-image.jpg", lightboxImgElem);
  lightboxControlsElem.disabled = false;
}

// …

function fixRedEyeCommand() {
  if (lightboxElem.style.display === "block" && lightboxImgElem.complete) {
    fixRedEye(lightboxImgElem);
  } else {
    /\* can't start doing this until the image is fully loaded \*/
  }
}
```

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-img-complete-dev |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.