Navigator: getVRDisplays() method - Web APIs

Navigator: getVRDisplays() method
=================================

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

**Non-standard:** This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.

The **`getVRDisplays()`** method of the `Navigator` interface returns a promise that resolves to an array of `VRDisplay` objects representing any available VR displays connected to the computer.

Syntax
------

```js
getVRDisplays()
```

### Parameters

None.

### Return value

A promise that resolves to an array of `VRDisplay` objects.

Examples
--------

See `VRDisplay` for example code.

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

#### No specification found

No specification data found for `api.Navigator.getVRDisplays`.
Check for problems with this page or contribute a missing `spec_url` to mdn/browser-compat-data. Also make sure the specification is included in w3c/browser-specs.

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

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

See also
--------

* WebVR API homepage


Navigator: userAgent property - Web APIs

Navigator: userAgent property
=============================

 The **`Navigator.userAgent`** read-only property returns the
 user agent string for the current browser.

**Note:** The specification asks browsers to provide as little information via this field as
 possible. Never assume that the value of this property will stay the same in future
 versions of the same browser. Try not to use it at all, or only for current and past
 versions of a browser. New browsers may start using the same UA, or part of it, as an
 older browser: you really have no guarantee that the browser agent is indeed the one
 advertised by this property.

 Also keep in mind that users of a browser can change the value of this field if they
 want (UA spoofing).

 Browser identification based on detecting the user agent string is
 **unreliable** and **is not recommended**, as the user agent
 string is user configurable. For example:

* In Firefox, you can change the preference `general.useragent.override` in
 `about:config`. Some Firefox extensions do that; however, this only changes
 the HTTP header that gets sent and that is returned by `navigator.userAgent`.
 There might be other methods that utilize JavaScript code to identify the browser.
* Opera 6+ allows users to set the browser identification string via a menu.
Value
-----

 A string specifying the complete user agent string the browser
 provides both in HTTP headers and in response to this and other related
 methods on the `Navigator` object.

 The user agent string is built on a formal structure which can be decomposed into
 several pieces of info. Each of these pieces of info comes from other navigator
 properties which are also settable by the user. Gecko-based browsers comply with the
 following general structure:
```

userAgent = appCodeName/appVersion number (Platform; Security; OS-or-CPU;
Localization; rv: revision-version-number) product/productSub
Application-Name Application-Name-version
```

Examples
--------

```js
alert(window.navigator.userAgent);
// alerts "Mozilla/5.0 (Windows; U; Win98; en-US; rv:0.9.2) Gecko/20010725 Netscape6/6.1"
```

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

| Specification |
| --- |
| HTML Standard # dom-navigator-useragent-dev |

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

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

See also
--------

* `User-Agent` HTTP header


Navigator: activeVRDisplays property - Web APIs

Navigator: activeVRDisplays property
====================================

**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

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

**Non-standard:** This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.

 The **`activeVRDisplays`** read-only property of the
 `Navigator` interface returns an array containing every
 `VRDisplay` object that is currently presenting
 (`VRDisplay.ispresenting` is `true`).

**Note:** This property was part of the old WebVR API. It has been superseded by the WebXR Device API.

Value
-----

An array of `VRDisplay` objects.

Examples
--------

```js
function showActive() {
  const displays = navigator.activeVRDisplays;
  for (const display of displays) {
    console.log(`Display ${display.displayId} is active.`);
  }
}
```

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

This property was part of the old WebVR API that has been superseded by the WebXR Device API. It is no longer on track to becoming a standard.

Until all browsers have implemented the new WebXR APIs, it is recommended to rely on frameworks, like A-Frame, Babylon.js, or Three.js, or a polyfill, to develop WebXR applications that will work across all browsers [1].

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

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

See also
--------

* WebVR API


Navigator: sendBeacon() method - Web APIs

Navigator: sendBeacon() method
==============================

 The **`navigator.sendBeacon()`**
 method asynchronously sends an HTTP POST request containing a small amount of data to a web server.

 It's intended to be used for
 sending analytics data to a web server, and avoids some of the problems with
 legacy techniques for sending analytics, such as the use of
 `XMLHttpRequest`.

**Note:** For use cases that need the ability to send requests with methods other than `POST`, or to change any request properties, or that need access to the server response, instead use the `fetch()` method with `keepalive` set to true.

Syntax
------

```js
sendBeacon(url)
sendBeacon(url, data)
```

### Parameters

`url`

The URL that will receive the *data*. Can be relative or absolute.

`data` Optional

 An `ArrayBuffer`, a `TypedArray`, a `DataView`, a `Blob`,
 a string literal or object, a `FormData` or a `URLSearchParams`
 object containing the data to send.

### Return values

 The **`sendBeacon()`** method returns `true` if the
 user agent successfully queued the `data` for transfer.
 Otherwise, it returns `false`.

Description
-----------

This method is intended for analytics and diagnostics code to send data to a server.

 A problem with sending analytics is that a site often wants to send analytics
 when the user has finished with a page: for example, when the user navigates
 to another page. In this situation the browser may be about to unload the page,
 and in that case the browser may choose not to send asynchronous
 `XMLHttpRequest` requests.

 In the past, web pages have tried to delay page unload long enough to send data. To do this they have
 used workarounds such as:

* Submitting the data with a blocking synchronous `XMLHttpRequest` call.
* Creating an `<img>` element and setting its `src`. Most user agents will delay the unload to load the image.
* Creating a no-op loop for several seconds.

 All these methods block unloading the document, which slows down navigation to the next page.
 There's nothing the next page can do to avoid this, so the new page seems
 slow, even though it's the fault of the previous page.

 With the `sendBeacon()` method, the data is transmitted asynchronously when the user
 agent has an opportunity to do so, without delaying unload or the next navigation.
 This means:

* The data is sent reliably
* It's sent asynchronously
* It doesn't impact the loading of the next page

The data is sent as an HTTP POST request.

### Sending analytics at the end of a session

 Websites often want to send analytics or diagnostics to the server when the user has finished with the page.
 The most reliable way to do this is to send the data on the `visibilitychange` event:

```js
document.addEventListener("visibilitychange", function logData() {
  if (document.visibilityState === "hidden") {
    navigator.sendBeacon("/log", analyticsData);
  }
});
```

#### Avoid unload and beforeunload

 In the past, many websites have used the `unload`
 or `beforeunload` events to send analytics at the end of a session.
 However, this is extremely unreliable. In many situations, especially on mobile, the browser will not fire the
 `unload`, `beforeunload`, or `pagehide` events. For example, these events will not fire in the following situation:

1. The user loads the page and interacts with it.
2. When they are finished, they switch to a different app, instead of closing the tab.
3. Later, they close the browser app using the phone's app manager.

 Additionally, the `unload` event is incompatible with the back/forward cache (bfcache)
 implemented in modern browsers. Some browsers, such as Firefox, handle this incompatibility by excluding pages from the bfcache if they contain unload handlers,
 thus hurting performance. Others, such as Safari and Chrome on Android, handle it by not firing the `unload` event when the user navigates to another page in the same tab.

Firefox will also exclude pages from the bfcache if they contain `beforeunload` handlers.

#### Use pagehide as a fallback

 To support browsers which don't implement `visibilitychange`, use the `pagehide` event.
 Like `beforeunload` and `unload`, this event is not reliably fired, especially on mobile. However, it is compatible with the bfcache.

Examples
--------

The following example specifies a handler for the `visibilitychange` event. The handler calls `sendBeacon()` to send analytics.

```js
document.addEventListener("visibilitychange", function logData() {
  if (document.visibilityState === "hidden") {
    navigator.sendBeacon("/log", analyticsData);
  }
});
```

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

| Specification |
| --- |
| Beacon # sendbeacon-method |

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

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

See also
--------

* The `visibilitychange` event.
* Beacon API overview page.
* Don't lose user and app state, use Page Visibility explains in
 detail why you should use `visibilitychange`, not
 `beforeunload`/`unload`.
* Page Lifecycle API gives best-practices guidance on handling
 page lifecycle behavior in your web applications.
* PageLifecycle.js: a JavaScript library that deals with cross-browser inconsistencies in page lifecycle behavior.
* Back/forward cache explains what the back/forward cache is, and its implications for various page lifecycle events.


Navigator: geolocation property - Web APIs

Navigator: geolocation property
===============================

**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

 The **`Navigator.geolocation`** read-only property returns a
 `Geolocation` object that gives Web content access to the location of the
 device. This allows a website or app to offer customized results based on the user's
 location.

**Note:** For security reasons, when a web page tries to access location
 information, the user is notified and asked to grant permission. Be aware that each
 browser has its own policies and methods for requesting this permission.

Value
-----

A `Geolocation` object.

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

| Specification |
| --- |
| Geolocation API # dom-navigator-geolocation |

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

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

See also
--------

* Using the Geolocation API


Navigator: connection property - Web APIs

Navigator: connection property
==============================

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

The **`Navigator.connection`** read-only property returns a `NetworkInformation` object containing information about the system's connection, such as the current bandwidth of the user's device or whether the connection is metered.

This could be used to select high definition content or low definition content based on the user's connection.

Value
-----

A `NetworkInformation` object.

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

| Specification |
| --- |
| Network Information API # connection-attribute |

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

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

See also
--------

* Online and offline events


Navigator: appName property - Web APIs

Navigator: appName 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 value of the **`Navigator.appName`** property is always
 "`Netscape`", in any browser. This property is kept only for compatibility
 purposes.

**Note:** Do not rely on this property to return a real browser name. All browsers return "`Netscape`" as the value of this property.

Value
-----

The string "`Netscape`".

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

| Specification |
| --- |
| HTML Standard # dom-navigator-appname-dev |

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

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

See also
--------

* `Navigator.appCodeName`
* `Navigator.product`


Navigator: product property - Web APIs

Navigator: product 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 value of the **`Navigator.product`** property is always
 "`Gecko`", in any browser. This property is kept only for compatibility
 purposes.

**Note:** Do not rely on this property to return a real product name. All browsers return "`Gecko`" as the value of this property.

Value
-----

The string "`Gecko`".

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

| Specification |
| --- |
| HTML Standard # dom-navigator-product-dev |

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

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

See also
--------

* `Navigator.appCodeName`
* `Navigator.appName`


Navigator: getAutoplayPolicy() method - Web APIs

Navigator: getAutoplayPolicy() method
=====================================

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

The **`getAutoplayPolicy()`** method of the *Autoplay Policy Detection API* provides information about whether autoplay of media elements and audio contexts is allowed, disallowed, or only allowed if the audio is muted.

 Applications can use this information to provide an appropriate user experience.
 For example, if the user agent policy only allows autoplay of inaudible content, the application might mute videos so that they can still autoplay.

The method can be used to get either the broad autoplay policy for all items of a particular type in the document, or for specific media elements or audio contexts.

Syntax
------

```js
// Test autoplay policy for a particular media playing feature
getAutoplayPolicy(type)

// Test autoplay support for a specific element or context
getAutoplayPolicy(element)
getAutoplayPolicy(context)
```

### Parameters

The method must be called with one (and only one) of the following three parameters:

`type` Optional

A string indicating the media playing *feature* for which the broad autoplay policy is required.

The supported values are:

`mediaelement`

 Get the broad autoplay policy for media elements in the document.
 Media elements are `HTMLMediaElement` derived objects such as `HTMLAudioElement` and `HTMLVideoElement`, and their corresponding tags `<audio>` and `<video>`.

`audiocontext`

Get the broad autoplay policy for Web Audio API players in the document.

`element` Optional

 A specific media element.
 This must be an `HTMLMediaElement`, including derived elements such as `HTMLVideoElement` and `HTMLAudioElement`.

`context` Optional

A specific `AudioContext`.

### Return value

 A string indicating the autoplay policy for the specified media feature type, element, or context.
 This will be a string containing one of the following values:

`allowed`

Autoplay is allowed.

`allowed-muted`

 Autoplay is allowed only for inaudible media.
 This includes media that has no audio track, or for which the audio has been muted.

`disallowed`

Autoplay is not allowed.

 Note that the autoplay policy returned for a `type` parameter is the *broad* policy for items of the indicated type.
 On page load, all items of a type will have the same policy as the type.
 Once the user has interacted with the page/site, on some browsers individual items *may* have a different policy to the corresponding type.

### Exceptions

`TypeError`

 The object passed to the method is not an allowed type.
 The allowed types include `HTMLMediaElement` (or a derived element such as `HTMLVideoElement` and `HTMLAudioElement`), or `AudioContext`.

Description
-----------

 "Autoplay" refers to any feature that causes content to begin to play without the user specifically requesting that playback begin.
 This includes the `autoplay` attribute in the HTML `<video>` and `<audio>` elements, and using JavaScript code to start playback without any user interaction.

 User agents commonly block autoplay, or only allow inaudible content to autoplay, because unexpected sounds when a page first loads can result in a jarring and unpleasant user experience.
 The mechanisms used to determine whether content can autoplay or not, or only play for inaudible content, differ between user agents.

 The **`getAutoplayPolicy()`** method provides a standard mechanism to determine the policy for a particular user agent to autoplay a particular type or item of content.
 This enables application customization such as automatic muting of video on sites where autoplay of audible content is not allowed, or modifying the application to behave without autoplay.

 The recommended use of the method is to call it *on page load* (or before the content playing elements are created) specifying the type of feature to check, and then configuring autoplay of media elements based on the result.
 For example, if the application wants to autoplay video elements that have an audio track, you might use the following code to mute the video if only inaudible content is allowed to play.

```js
if (navigator.getAutoplayPolicy("mediaelement") === "allowed") {
  // Do nothing. The content can autoplay.
} else if (navigator.getAutoplayPolicy("mediaelement") === "allowed-muted") {
  // Mute the video so it can autoplay.
} else {
  // Autoplay disallowed.
  // Add a play button to the video element.
}
```

 The method can also be called to check the autoplay policy for a specific media element or audio context.
 As shown below, the code looks exactly the same except you pass in the specify item rather than the `type` string.

```js
const video = document.getElementById("video\_element\_id");
if (navigator.getAutoplayPolicy(video) === "allowed") {
  // Do nothing. The content can autoplay.
} else if (navigator.getAutoplayPolicy(video) === "allowed-muted") {
  // Mute the video so it can autoplay.
} else {
  // Autoplay disallowed.
  // Add a play button to the video element.
}
```

 On page load, before the user has interacted with the page or site, the autoplay policy for the type and the individual items will be the same.
 After the user interacts with the site, page, or specific elements, the autoplay policy may change for the whole `type`.
 It is also possible that the policy for a specific item will change, even if the overall policy for the `type` does not.

 There is no way to be notified that the autoplay policy has changed.
 For this reason, while you can check the policy for a type or item at any time, usually you will only do so on page load or before attempting to play content.

Examples
--------

### Checking if the feature is supported

The code below shows how to check if `navigator.getAutoplayPolicy()` is supported:
```

<div id="reportResult"></div>
```

```
const log = document.getElementById("reportResult");
```

```js
if (!navigator.getAutoplayPolicy) {
  log.textContent = "navigator.getAutoplayPolicy() not supported.";
} else {
  log.textContent = "navigator.getAutoplayPolicy() is supported.";
}
```

The result of running the code on this page is:

### Test autoplay policy for media element type

This example demonstrates how you can check the autoplay policy for the media elements type.

 The code creates a video element that has the `autoplay` attribute and is not muted by default.
 If the autoplay policy is "allowed-muted", the video will be muted to allow it to play.

#### HTML

 The HTML below has a `div` element that is used as a reporting log, and also displays a `<video>` that has the `autoplay` attribute.
 This should not be muted by default, and should play automatically if autoplay is not blocked.

```html
<div id="reportResult"></div>
<!-- Simple video example -->
<!-- 'Big Buck Bunny' licensed under CC 3.0 by the Blender foundation. Hosted by archive.org -->
<!-- Poster from peach.blender.org -->
<video
 id="bunny\_vid"
 autoplay
 controls
 src="https://archive.org/download/BigBuckBunny\_124/Content/big\_buck\_bunny\_720p\_surround.mp4"
 poster="https://peach.blender.org/wp-content/uploads/title\_anouncement.jpg?x11217"
 width="620">
  Sorry, your browser doesn't support embedded videos, but don't worry, you can
  <a href="https://archive.org/details/BigBuckBunny\_124">download it</a> and
  watch it with your favorite video player!
</video>
```

#### JavaScript

The code reports whether or not the `getAutoplayPolicy()` method is supported, and if it is, the policy for media elements.

 If the policy is `allowed-muted`, only muted videos can be played.
 In this case we add some text explaining what is happening and mute the video.

```js
const log = document.getElementById("reportResult");
const video = document.getElementById("bunny\_vid");

if (!navigator.getAutoplayPolicy) {
  log.textContent =
    "navigator.getAutoplayPolicy() not supported. It may or may not autoplay, depending on the browser!";
} else {
  log.textContent = `Autoplay policy for media elements is: ${navigator.getAutoplayPolicy(
 "mediaelement",
 )}. `;

  if (navigator.getAutoplayPolicy("mediaelement") === "allowed-muted") {
    // Mute the video so it can autoplay
    video.muted = true;
    log.textContent += "Video has been muted to allow it to autoplay.";
  }
}
```

Note that you might similarly check for `allowed` and `disallowed`.

#### Result

The video is displayed below along with information about whether the `getAutoplayPolicy()` method is supported, and if so, the policy.

 If `getAutoplayPolicy()` is supported and the policy is `allowed`, the video will play automatically with sound.
 If the policy is `allowed-muted`, the video will play without sound.

 Note that if `getAutoplayPolicy()` is not supported, the video will either autoplay with audio or not play.
 The code has no control over this behavior: you're at the mercy of the browser implementation!

### Test autoplay policy for a specific media element

 This example shows how you can check whether a specific media element will autoplay.
 It is almost exactly the same as the previous example (an `AudioContext` check would also be similar).
 Note that it is possible for specific elements to autoplay even if a check on the `mediaelement` type indicates that autoplay is `disallowed`; in other words, a check on a specific element is more reliable (though it doesn't matter on page load).

 The code creates a video element that has the `autoplay` attribute.
 If the autoplay policy is "allowed-muted", the video will be muted to allow it to play.

#### HTML

 The HTML below has a `div` element that is used as a reporting log, and also displays a `<video>` that has the `autoplay` attribute.
 This should not be muted by default, and should play automatically if autoplay is not blocked.

```html
<div id="reportResult"></div>
<!-- Simple video example -->
<!-- 'Big Buck Bunny' licensed under CC 3.0 by the Blender foundation. Hosted by archive.org -->
<!-- Poster from peach.blender.org -->
<video
 id="bunny\_vid"
 autoplay
 controls
 src="https://archive.org/download/BigBuckBunny\_124/Content/big\_buck\_bunny\_720p\_surround.mp4"
 poster="https://peach.blender.org/wp-content/uploads/title\_anouncement.jpg?x11217"
 width="620">
  Sorry, your browser doesn't support embedded videos, but don't worry, you can
  <a href="https://archive.org/details/BigBuckBunny\_124">download it</a> and
  watch it with your favorite video player!
</video>
```

#### JavaScript

The code reports whether or not the `getAutoplayPolicy()` method is supported, and if it is, the policy for media elements.

If the policy is `allowed-muted`, only muted videos can be played, so the code mutes the video.

```js
const log = document.getElementById("reportResult");
const video = document.getElementById("bunny\_vid");

if (!navigator.getAutoplayPolicy) {
  log.textContent =
    "navigator.getAutoplayPolicy() not supported. It may or may not autoplay, depending on the browser!";
} else {
  // Here we pass in the HTMLVideoElement to check
  log.textContent = `navigator.getAutoplayPolicy(video) == ${navigator.getAutoplayPolicy(
 "mediaelement",
 )}`;

  if (navigator.getAutoplayPolicy(video) === "allowed-muted") {
    // Mute the video so it can autoplay
    video.muted = true;
    log.textContent += "Video has been muted to allow it to autoplay.";
  }
}
```

#### Result

The result is the same as in the previous example:

* The video should autoplay with sound if `allowed` is returned, and no sound if `allowed-muted` is returned.
* If `getAutoplayPolicy()` is not supported, the video autoplay behavior depends only on the browser.

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

| Specification |
| --- |
| Autoplay Policy Detection # dom-navigator-getautoplaypolicy |

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

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

See also
--------

* Autoplay guide for media and Web Audio APIs


Navigator: virtualKeyboard property - Web APIs

Navigator: virtualKeyboard property
===================================

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

 The **`virtualKeyboard`** read-only property
 of the `navigator` interface returns a reference to the `VirtualKeyboard` instance object.

The VirtualKeyboard API gives developers control over the layout of their applications when the on-screen virtual keyboard appears and disappears on devices such as tablets, mobile phones, or other devices where a hardware keyboard may not be available.

Value
-----

A `VirtualKeyboard` object you can use to opt-out of the automatic virtual keyboard behavior, show or hide the virtual keyboard programmatically, and get the current position and size of the virtual keyboard.

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

| Specification |
| --- |
| VirtualKeyboard API # dom-navigator-virtualkeyboard |

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

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


Navigator: buildID property - Web APIs

Navigator: buildID property
===========================

**Non-standard:** This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.

Returns the build identifier of the browser. In modern browsers this property now returns a fixed timestamp as a privacy measure, e.g. `20181001000000` in Firefox 64 onwards.

Value
-----

A string representing the build identifier of the application. The build ID is in the form `YYYYMMDDHHMMSS`.

Examples
--------

```js
console.log(navigator.buildID);
```

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

Not part of any public standard.

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

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


Navigator: ink property - Web APIs

Navigator: ink property
=======================

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

The **`ink`** read-only property of the `Navigator` interface returns an `Ink` object for the current document, providing access to Ink API functionality.

Value
-----

An `Ink` object.

Example
-------

```js
async function inkInit() {
  const ink = navigator.ink;
  let presenter = await ink.requestPresenter({ presentationArea: canvas });

  //...
}
```

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

| Specification |
| --- |
| Ink API # navigator-interface-extensions |

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

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

See also
--------

* Enhancing Inking on the Web


Navigator: storage property - Web APIs

Navigator: storage property
===========================

**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

 The **`Navigator.storage`**
 read-only property returns the singleton `StorageManager` object used to
 access the overall storage capabilities of the browser for the current site or app.
 The returned object lets you examine and configure persistence of data stores and
 learn approximately how much more space your browser has available for local storage
 use.

Value
-----

 A `StorageManager` object you can use to maintain persistence for stored
 data, as well as to determine roughly how much room there is for data to be stored.

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

| Specification |
| --- |
| Storage Standard # dom-navigatorstorage-storage |

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

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

See also
--------

* `StorageManager`
* `Navigator`


Navigator: platform property - Web APIs

Navigator: platform 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 **`platform`** property read-only property of the `Navigator` interface returns a string identifying the platform on which the user's browser is running.

**Note:** In general, you should whenever possible avoid writing code that uses methods or properties like this one to try to find out information about the user's environment, and instead write code that does feature detection.

Value
-----

A string identifying the platform on which the user's browser is running; for example: `"MacIntel"`, `"Win32"`, `"Linux x86_64"`, `"Linux armv81"`.

Examples
--------

`navigator.platform` should almost always be avoided in favor of feature detection. But there is one case where, among the options you could use, `navigator.platform` may be the least-bad option: When you need to show users advice about whether the modifier key for keyboard shortcuts is the `⌘` command key (found on Apple systems) rather than the `⌃` control key (on non-Apple systems):

```js
let modifierKeyPrefix = "^"; // control key
if (
  navigator.platform.indexOf("Mac") === 0 ||
  navigator.platform === "iPhone"
) {
  modifierKeyPrefix = "⌘"; // command key
}
```

That is, check if `navigator.platform` starts with `"Mac"` or else is an exact match for `"iPhone"`, and then based on whether either of those is true, choose the modifier key your web application's UI will advise users to press in keyboard shortcuts.

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

On Windows, modern browsers return `"Win32"` even if running on a 64-bit version of Windows.

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

| Specification |
| --- |
| HTML Standard # dom-navigator-platform-dev |

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

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

See also
--------

* `navigator.userAgentData.platform`


Navigator: canShare() method - Web APIs

Navigator: canShare() method
============================

**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

The **`Navigator.canShare()`** method of the Web Share API returns `true` if the equivalent call to `navigator.share()` would succeed.

The method returns `false` if the data cannot be *validated*. Reasons the data might be invalid include:

* The `data` parameter has been omitted or only contains properties with unknown values. Note that any properties that are not recognized by the user agent are ignored.
* A URL is badly formatted.
* Files are specified but the implementation does not support file sharing.
* Sharing the specified data would be considered a "hostile share" by the user-agent.

 The Web Share API is gated by the web-share permission policy.
 The **`canShare()`** method will return `false` if the permission is supported but has not been granted.

Syntax
------

```js
canShare()
canShare(data)
```

### Parameters

`data` Optional

 An object defining the share data to test.
 Typically, an object with the same properties is passed to `navigator.share()` if this call returns `true`.

 Properties that are unknown to the user agent are ignored; share data is only assessed on properties understood by the user agent.
 All properties are optional but at least one known data property must be specified or the method will return `false`.

Possible values are:

* `url`: A string representing a URL to be shared.
* `text`: A string representing text to be shared.
* `title`: A string representing the title to be shared.
* `files`: An array of `File` objects representing files to be shared.

### Return value

Returns `true` if the specified `data` can be shared with `Navigator.share()`, otherwise `false`.

Examples
--------

### Sending the MDN URL

The example uses `navigator.canShare()` to check whether `navigator.share()` can share the specified data.

#### HTML

The HTML just creates a paragraph in which to display the result of the test.

```html
<p class="result"></p>
```

#### JavaScript

```js
let shareData = {
  title: "MDN",
  text: "Learn web development on MDN!",
  url: "https://developer.mozilla.org",
};

const resultPara = document.querySelector(".result");

if (!navigator.canShare) {
  resultPara.textContent = "navigator.canShare() not supported.";
} else if (navigator.canShare(shareData)) {
  resultPara.textContent =
    "navigator.canShare() supported. We can use navigator.share() to send the data.";
} else {
  resultPara.textContent = "Specified data cannot be shared.";
}
```

#### Result

The box below should state whether `navigator.canShare()` is supported on this browser, and if so, whether or not we can use `navigator.share()` to share the specified data:

### Feature checking example

 This method feature tests whether a particular data property is valid and shareable.
 If used with a single `data` property it will return `true` only if that property is valid and can be shared on the platform.

The code below demonstrates verifying that a data property is supported.

```js
// Feature that may not be supported
let testShare = { someNewProperty: "Data to share" };

// Complex data that uses new key
const shareData = {
  title: "MDN",
  text: "Learn web development on MDN!",
  url: "https://developer.mozilla.org",
  someNewProperty: "Data to share",
};

// Test that the key is valid and supported before sharing
if (navigator.canShare(testShare)) {
  // Use navigator.share() to share 'shareData'
} else {
  // Handle case that new data property can't be shared.
}
```

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

| Specification |
| --- |
| Web Share API # canshare-data-method |

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

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

See also
--------

* `navigator.share()`


Navigator: requestMediaKeySystemAccess() method - Web APIs

Navigator: requestMediaKeySystemAccess() method
===============================================

 The **`Navigator.requestMediaKeySystemAccess()`** method
 returns a `Promise` which delivers a `MediaKeySystemAccess`
 object that can be used to access a particular media key system, which can in turn be
 used to create keys for decrypting a media stream. This method is part of the Encrypted Media Extensions API, which brings support for encrypted media and DRM-protected video to the web.

 This method may have user-visible effects such as asking for permission to access one
 or more system resources. Consider that when deciding when to call
 `requestMediaKeySystemAccess()`; you don't want those requests
 to happen at inconvenient times. As a general rule, this function should be called only
 when it's about time to create and use a `MediaKeys` object by calling the
 returned `MediaKeySystemAccess` object's
 `createMediaKeys()` method.

Syntax
------

```js
requestMediaKeySystemAccess(keySystem, supportedConfigurations)
```

### Parameters

`keySystem`

 A string identifying the key system. For example
 `com.example.somesystem` or `org.w3.clearkey`.

`supportedConfigurations`

A non-empty `Array` of objects conforming to the object returned by `MediaKeySystemAccess.getConfiguration`. The first element with a satisfiable configuration will be used.

### Return value

 A `Promise` that, when resolved, delivers a
 `MediaKeySystemAccess` object to your fulfillment handler function. The
 fulfillment handler receives as input just one parameter:

`mediaKeySystemAccess`

 A `MediaKeySystemAccess` object representing the media key system
 configuration described by `keySystem` and
 `supportedConfigurations`

### Exceptions

 In case of an error, the returned `Promise` is rejected with a
 `DOMException` whose name indicates what kind of error occurred.

`NotSupportedError` `DOMException`

 Either the specified `keySystem` isn't supported by the platform or the
 browser, or none of the configurations specified by
 `supportedConfigurations` can be satisfied (if, for example, none of the
 `codecs` specified in `contentType` are available).

`SecurityError` `DOMException`

Use of this feature was blocked by a Permissions Policy.

`TypeError``

 Either `keySystem` is an empty string or the
 `supportedConfigurations` array is empty.

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

| Specification |
| --- |
| Encrypted Media Extensions # navigator-extension-requestmediakeysystemaccess |

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

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

### Firefox compatibility notes

 Firefox 55 outputs a warning to the console if a candidate
 `MediaKeySystemConfiguration` included in
 `supportedConfigurations` includes an `audioCapabilities` or
 `videoCapabilities` object whose value of `contentType` doesn't
 specify a `"codecs"` substring defining which codecs within the media wrapper
 format should be allowed.

For example:

```js
const clearKeyOptions = [
  {
    initDataTypes: ["keyids", "webm"],
    audioCapabilities: [{ contentType: "audio/webm" }],
    videoCapabilities: [{ contentType: "video/webm" }],
  },
];

navigator
  .requestMediaKeySystemAccess("org.w3.clearkey", clearKeyOptions)
  .then((keySystemAccess) => {
    /\* use the access to get create keys \*/
  });
```

 The code above works in Firefox up to version 55, but version 55 onwards will output a
 warning to console, because `"codecs"` is not included in the
 `contentType` strings. This could be corrected as follows:

```js
const clearKeyOptions = [
  {
    initDataTypes: ["keyids", "webm"],
    audioCapabilities: [
      { contentType: 'audio/webm; codecs="opus"' },
      { contentType: 'audio/webm; codecs="vorbis"' },
    ],
    videoCapabilities: [
      { contentType: 'video/webm; codecs="vp9"' },
      { contentType: 'video/webm; codecs="vp8"' },
    ],
  },
];

navigator
  .requestMediaKeySystemAccess("org.w3.clearkey", clearKeyOptions)
  .then((keySystemAccess) => {
    /\* use the access to get create keys \*/
  });
```

 In this revised example, the audio and video capabilities include possible codecs which
 should be permitted, and therefore are valid requests.

See also
--------

* Encrypted Media Extensions API
* Media Capture and Streams API
* WebRTC API


Navigator: mediaSession property - Web APIs

Navigator: mediaSession property
================================

 The read-only **`mediaSession`** property of the `Navigator`
 interface returns a `MediaSession`
 object that can be used to share with the browser metadata and other information about
 the current playback state of media being handled by a document.

 This
 information may, in turn, be shared with the device and/or operating system in order to
 a device's standard media control user experience to describe and control the playback
 of the media.

 In addition, the `MediaSession` interface provides the
 `setActionHandler()` method, which lets
 you receive events when the user engages device controls such as either onscreen or
 physical play, pause, seek, and other similar controls. An internet radio app, for
 example, can use `setActionHandler()` to let the media controls on a keyboard
 or elsewhere on the user's device be used to control the app's media playback.

Value
-----

 A `MediaSession` object the current document can use to share information
 about media it's playing and its current playback status. This information can include
 typical metadata such as the title, artist, and album name of the song being played as
 well as potentially one or more images containing things like album art, artist photos,
 and so forth.

Examples
--------

 In this example, metadata is submitted to the `mediaSession` object. Note
 that the code begins by ensuring that the `navigator.mediaSession` property
 is available before attempting to use it.

```js
if ("mediaSession" in navigator) {
  navigator.mediaSession.metadata = new MediaMetadata({
    title: "Podcast Episode Title",
    artist: "Podcast Host",
    album: "Podcast Name",
    artwork: [{ src: "podcast.jpg" }],
  });
}
```

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

| Specification |
| --- |
| Media Session # dom-navigator-mediasession |

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

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


Web-based protocol handlers - Web APIs

Web-based protocol handlers
===========================

Background
----------

It's fairly common to find web pages link to resources using non-`http` protocols. An example is the `mailto:` protocol:

```html
<a href="mailto:webmaster@example.com">Web Master</a>
```

Web authors can use a `mailto:` link when they want to provide a convenient way for users to send an email, directly from the webpage. When the link is activated, the browser should launch the default desktop application for handling email. You can think of this as a *desktop-based* protocol handler.

Web-based protocol handlers allow web-based applications to participate in the process too. This is becoming more important as more types of applications migrate to the web. In fact, there are many web-based email handling applications that could process a `mailto` link.

Registering
-----------

Setting up a web application as a protocol handler is not a difficult process. Basically, the web application uses `registerProtocolHandler()` to register itself with the browser as a potential handler for a given protocol. For example:

```js
navigator.registerProtocolHandler(
  "web+burger",
  "http://www.google.co.uk/?uri=%s",
  "Burger handler",
);
```

Where the parameters are:

* The protocol.
* The URL template, used as the handler. The "%s" is replaced with the `href` of the link and a GET is executed on the resultant URL.
* The user friendly name for the protocol handler.

When a browser executes this code, it should let the user choose how to handle the protocol. The browser could prompt the user for registration immediately, or wait until the user clicks on a link that uses the protocol. Firefox displays a prompt in the notification bar area:

![Screenshot of a prompt that reads: Add Burger handler (google.co.uk) as an application for burger links. An Add Application button is next to the text.](/en-US/docs/Web/API/Navigator/registerProtocolHandler/Web-based_protocol_handlers/protocolregister.png)

**Note:** The URL template supplied when registering **must** be of the same domain as the webpage attempting to perform the registration or the registration will fail. For example, `http://example.com/homepage.html` can register a protocol handler for `http://example.com/handle_mailto/%s`, but not for `http://example.org/handle_mailto/%s`.

### Example

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>Web Protocol Handler Sample - Register</title>
    <script>
 navigator.registerProtocolHandler(
 "web+burger",
 "http://www.google.co.uk/?uri=%s",
 "Burger handler",
 );
 </script>
  </head>
  <body>
    <h1>Web Protocol Handler Sample</h1>
    <p>
      This web page will install a web protocol handler for the
      <code>web+burger:</code> protocol.
    </p>
  </body>
</html>
```

Activating
----------

Now, anytime the user activates a link that uses the registered protocol, the browser will route the action to the URL supplied when the web application registered. Firefox will, by default, prompt the user before handling off the action.

### Example

```html
<!doctype html>
<html lang="en">
  <head>
    <title>Web Protocol Handler Sample - Test</title>
  </head>
  <body>
    <p>Hey have you seen <a href="web+burger:cheeseburger">this</a> before?</p>
  </body>
</html>
```

Handling
--------

The next phase is handling the action. The browser extracts the `href` from the activated link, combines it with the URL template supplied during handler registration and performs an HTTP GET on the URL. So, using the above examples, the browser would perform a GET on this URL:

```url
http://www.google.co.uk/?uri=web+burger:cheeseburger
```

Server side code can extract the query string parameters and perform the desired action.

**Note:** The server side code is passed the **entire** contents of the `href`. This means the server side code will have to parse out the protocol from the data.

### Example

```php
<?php
$value = "";
if ( isset ( $\_GET["value"] ) ) {
 $value = $\_GET["value"];
}
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Web Protocol Handler Sample</title>
</head>
<body>
  <h1>Web Protocol Handler Sample - Handler</h1>
  <p>This web page is called when handling a <code>web+burger:</code> protocol action. The data sent:</p>
  <textarea>
<?php echo(htmlspecialchars($value, ENT\_QUOTES, 'UTF-8')); ?>
  </textarea>
</body>
</html>
```

References
----------

* http://www.w3.org/TR/2011/WD-html5-20110525/timers.html#custom-handlers
See also
--------

* `nsIProtocolHandler` (XUL only)
* RegisterProtocolHandler Enhancing the Federated Web at Mozilla Webdev
* Register a custom protocolHandler at web.dev.


Origin private file system - Web APIs

Origin private file system
==========================

**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

The origin private file system (OPFS) is a storage endpoint provided as part of the File System API, which is private to the origin of the page and not visible to the user like the regular file system. It provides access to a special kind of file that is highly optimized for performance and offers in-place write access to its content.

Working with files using the File System Access API
---------------------------------------------------

The File System Access API, which extends the File System API, provides access to files using picker methods. For example:

1. `Window.showOpenFilePicker()` allows the user to choose a file to access, which results in a `FileSystemFileHandle` object being returned.
2. `FileSystemFileHandle.getFile()` is called to get access to the file's contents, the content is modified using `FileSystemFileHandle.createWritable()` / `FileSystemWritableFileStream.write()`.
3. `FileSystemHandle.requestPermission({mode: 'readwrite'})` is used to request the user's permission to save the changes.
4. If the user accepts the permission request, the changes are saved back to the original file.

This works, but it has some restrictions. These changes are being made to the user-visible file system, so there are a lot of security checks in place (for example, safe browsing in Chrome) to guard against malicious content being written to that file system. These writes are not in-place, and instead use a temporary file. The original is not modified unless it passes all the security checks.

As a result, these operations are fairly slow. It is not so noticeable when you are making small text updates, but the performance suffers when making more significant, large-scale file updates such as SQLite database modifications.

How does the OPFS solve such problems?
--------------------------------------

The OPFS offers low-level, byte-by-byte file access, which is private to the origin of the page and not visible to the user. As a result, it doesn't require the same series of security checks and permission grants and is therefore faster than File System Access API calls. It also has a set of synchronous calls available (other File System API calls are asynchronous) that can be run inside web workers only so as not to block the main thread.

To summarize how the OPFS differs from the user-visible file system:

* The OPFS is subject to browser storage quota restrictions, just like any other origin-partitioned storage mechanism (for example IndexedDB API). You can access the amount of storage space the OPFS is using via `navigator.storage.estimate()`.
* Clearing storage data for the site deletes the OPFS.
* Permission prompts and security checks are not required to access files in the OPFS.
* Browsers persist the contents of the OPFS to disk somewhere, but you cannot expect to find the created files matched one-to-one. The OPFS is not intended to be visible to the user.
How do you access the OPFS?
---------------------------

To access the OPFS in the first place, you call the `navigator.storage.getDirectory()` method. This returns a reference to a `FileSystemDirectoryHandle` object that represents the root of the OPFS.

Manipulating the OPFS from the main thread
------------------------------------------

When accessing the OPFS from the main thread, you will use asynchronous, `Promise`-based APIs. You can access file (`FileSystemFileHandle`) and directory (`FileSystemDirectoryHandle`) handles by calling `FileSystemDirectoryHandle.getFileHandle()` and `FileSystemDirectoryHandle.getDirectoryHandle()` respectively on the `FileSystemDirectoryHandle` object representing the OPFS root (and child directories, as they are created).

**Note:** Passing `{ create: true }` into the above methods causes the file or folder to be created if it doesn't exist.

```js
// Create a hierarchy of files and folders
const fileHandle = await opfsRoot.getFileHandle("my first file", {
  create: true,
});
const directoryHandle = await opfsRoot.getDirectoryHandle("my first folder", {
  create: true,
});
const nestedFileHandle = await directoryHandle.getFileHandle(
  "my first nested file",
  { create: true },
);
const nestedDirectoryHandle = await directoryHandle.getDirectoryHandle(
  "my first nested folder",
  { create: true },
);

// Access existing files and folders via their names
const existingFileHandle = await opfsRoot.getFileHandle("my first file");
const existingDirectoryHandle =
  await opfsRoot.getDirectoryHandle("my first folder");
```

### Reading a file

1. Make a `FileSystemDirectoryHandle.getFileHandle()` call to return a `FileSystemFileHandle` object.
2. Call the `FileSystemFileHandle.getFile()` object to return a `File` object. This is a specialized type of `Blob`, and as such can be manipulated just like any other `Blob`. For example, you could access the text content directly via `Blob.text()`.
### Writing a file

1. Make a `FileSystemDirectoryHandle.getFileHandle()` call to return a `FileSystemFileHandle` object.
2. Call `FileSystemFileHandle.createWritable()` to return a `FileSystemWritableFileStream` object, which is a specialized type of `WritableStream`.
3. Write contents to it using a `FileSystemWritableFilestream.write()` call.
4. Close the stream using `WritableStream.close()`.
### Deleting a file or folder

You can call `FileSystemDirectoryHandle.removeEntry()` on the parent directory, passing it the name of the item you want to remove:

```js
directoryHandle.removeEntry("my first nested file");
```

You can also call `FileSystemHandle.remove()` on the `FileSystemFileHandle` or `FileSystemDirectoryHandle` representing the item you want to remove. To delete a folder including all subfolders, pass the `{ recursive: true }` option.

```js
await fileHandle.remove();
await directoryHandle.remove({ recursive: true });
```

The following provides a quick way to clear the entire OPFS:

```js
await (await navigator.storage.getDirectory()).remove({ recursive: true });
```

### Listing the contents of a folder

`FileSystemDirectoryHandle` is an asynchronous iterator. As such, you can iterate over it with a `for await…of` loop and standard methods such as `entries()`, `values()`, and `keys()`.

For example:

```js
for await (let [name, handle] of directoryHandle) {
}
for await (let [name, handle] of directoryHandle.entries()) {
}
for await (let handle of directoryHandle.values()) {
}
for await (let name of directoryHandle.keys()) {
}
```

Manipulating the OPFS from a web worker
---------------------------------------

Web Workers don't block the main thread, which means you can use the synchronous file access APIs in this context. Synchronous APIs are faster as they avoid having to deal with promises.

You can synchronously access a file by calling `FileSystemFileHandle.createSyncAccessHandle()` on a regular `FileSystemFileHandle`:

**Note:** Despite having "Sync" in its name, the `createSyncAccessHandle()` method itself is asynchronous.

```js
const opfsRoot = await navigator.storage.getDirectory();
const fileHandle = await opfsRoot.getFileHandle("my highspeed file.txt", {
  create: true,
});
const syncAccessHandle = await fileHandle.createSyncAccessHandle();
```

There are a number of *synchronous* methods available on the returned `FileSystemSyncAccessHandle`:

* `getSize()`: Returns the size of the file in bytes.
* `write()`: Writes the content of a buffer into the file, optionally at a given offset, and returns the number of written bytes. Checking the returned number of written bytes allows callers to detect and handle errors and partial writes.
* `read()`: Reads the contents of the file into a buffer, optionally at a given offset.
* `truncate()`: Resizes the file to the given size.
* `flush()`: Ensures that the file contents contain all the modifications done through `write()`.
* `close()`: Closes the access handle.

Here is an example that uses all the methods mentioned above:

```js
const opfsRoot = await navigator.storage.getDirectory();
const fileHandle = await opfsRoot.getFileHandle("fast", { create: true });
const accessHandle = await fileHandle.createSyncAccessHandle();

const textEncoder = new TextEncoder();
const textDecoder = new TextDecoder();

// Initialize this variable for the size of the file.
let size;
// The current size of the file, initially `0`.
size = accessHandle.getSize();
// Encode content to write to the file.
const content = textEncoder.encode("Some text");
// Write the content at the beginning of the file.
accessHandle.write(content, { at: size });
// Flush the changes.
accessHandle.flush();
// The current size of the file, now `9` (the length of "Some text").
size = accessHandle.getSize();

// Encode more content to write to the file.
const moreContent = textEncoder.encode("More content");
// Write the content at the end of the file.
accessHandle.write(moreContent, { at: size });
// Flush the changes.
accessHandle.flush();
// The current size of the file, now `21` (the length of
// "Some textMore content").
size = accessHandle.getSize();

// Prepare a data view of the length of the file.
const dataView = new DataView(new ArrayBuffer(size));

// Read the entire file into the data view.
accessHandle.read(dataView);
// Logs `"Some textMore content"`.
console.log(textDecoder.decode(dataView));

// Read starting at offset 9 into the data view.
accessHandle.read(dataView, { at: 9 });
// Logs `"More content"`.
console.log(textDecoder.decode(dataView));

// Truncate the file after 4 bytes.
accessHandle.truncate(4);
```

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

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

See also
--------

* The origin private file system on web.dev


CanvasRenderingContext2D: textAlign property - Web APIs

CanvasRenderingContext2D: textAlign property
============================================

 The
 **`CanvasRenderingContext2D.textAlign`**
 property of the Canvas 2D API specifies the current text alignment used when drawing
 text.

 The alignment is relative to the `x` value of the
 `fillText()` method. For example, if
 `textAlign` is `"center"`, then the text's left edge will be at
 `x - (textWidth / 2)`.

Value
-----

Possible values:

`"left"`

The text is left-aligned.

`"right"`

The text is right-aligned.

`"center"`

The text is centered.

`"start"`

 The text is aligned at the normal start of the line (left-aligned for left-to-right
 locales, right-aligned for right-to-left locales).

`"end"`

 The text is aligned at the normal end of the line (right-aligned for left-to-right
 locales, left-aligned for right-to-left locales).

The default value is `"start"`.

Examples
--------

### General text alignment

 This example demonstrates the three "physical" values of the `textAlign`
 property: `"left"`, `"center"`, and `"right"`.

#### HTML

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

#### JavaScript

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

ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, canvas.height);
ctx.stroke();

ctx.font = "30px serif";

ctx.textAlign = "left";
ctx.fillText("left-aligned", x, 40);

ctx.textAlign = "center";
ctx.fillText("center-aligned", x, 85);

ctx.textAlign = "right";
ctx.fillText("right-aligned", x, 130);
```

#### Result

### Direction-dependent text alignment

 This example demonstrates the two direction-dependent values of the
 `textAlign` property: `"start"` and `"end"`. Note that
 the `direction` property is manually
 specified as `"ltr"`, although this is also the default for English-language
 text.

#### HTML

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

#### JavaScript

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

ctx.font = "30px serif";
ctx.direction = "ltr";

ctx.textAlign = "start";
ctx.fillText("Start-aligned", 0, 50);

ctx.textAlign = "end";
ctx.fillText("End-aligned", canvas.width, 120);
```

#### Result

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

| Specification |
| --- |
| HTML Standard # dom-context-2d-textalign-dev |

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

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

See also
--------

* The interface defining this property: `CanvasRenderingContext2D`


CanvasRenderingContext2D: createConicGradient() method - Web APIs

CanvasRenderingContext2D: createConicGradient() method
======================================================

The **`CanvasRenderingContext2D.createConicGradient()`** method of the Canvas 2D API creates a gradient around a point with given coordinates.

This method returns a conic `CanvasGradient`. To be applied to a shape, the gradient must first be assigned to the `fillStyle` or `strokeStyle` properties.

**Note:** Gradient coordinates are global, i.e., relative to the current coordinate space. When applied to a shape, the coordinates are NOT relative to the shape's coordinates.

Syntax
------

```js
createConicGradient(startAngle, x, y)
```

### Parameters

`startAngle`

The angle at which to begin the gradient, in radians. The angle starts from a line going horizontally right from the center, and proceeds clockwise.

`x`

The x-axis coordinate of the center of the gradient.

`y`

The y-axis coordinate of the center of the gradient.

### Return value

`CanvasGradient`

A conic `CanvasGradient`.

Examples
--------

### Filling a rectangle with a conic gradient

This example initializes a conic gradient using the `createConicGradient()` method. Five color stops between around the center coordinate are then created. Finally, the gradient is assigned to the canvas context, and is rendered to a filled rectangle.

#### HTML

```html
<canvas id="canvas" width="240" height="240"></canvas>
```

#### JavaScript

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

// Create a conic gradient
// The start angle is 0
// The center position is 100, 100
const gradient = ctx.createConicGradient(0, 100, 100);

// Add five color stops
gradient.addColorStop(0, "red");
gradient.addColorStop(0.25, "orange");
gradient.addColorStop(0.5, "yellow");
gradient.addColorStop(0.75, "green");
gradient.addColorStop(1, "blue");

// Set the fill style and draw a rectangle
ctx.fillStyle = gradient;
ctx.fillRect(20, 20, 200, 200);
```

#### Rectangle result

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

| Specification |
| --- |
| HTML Standard # dom-context-2d-createconicgradient-dev |

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

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

See also
--------

* The interface defining this method: `CanvasRenderingContext2D`
* `CanvasGradient`
* `CanvasRenderingContext2D.createLinearGradient()`
* `CanvasRenderingContext2D.createRadialGradient()`


CanvasRenderingContext2D: canvas property - Web APIs

CanvasRenderingContext2D: canvas property
=========================================

 The **`CanvasRenderingContext2D.canvas`** property, part of the
 Canvas API, is a read-only reference to the
 `HTMLCanvasElement` object that is associated with a given context. It
 might be `null` if there is no associated `<canvas>` element.

Value
-----

A `HTMLCanvasElement` object.

Examples
--------

Given this `<canvas>` element:

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

 … you can get a reference to the canvas element within the
 `CanvasRenderingContext2D` by using the `canvas` property:

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

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

| Specification |
| --- |
| HTML Standard # dom-context-2d-canvas-dev |

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

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

See also
--------

* `CanvasRenderingContext2D` interface
* Canvas API


CanvasRenderingContext2D: filter property - Web APIs

CanvasRenderingContext2D: filter property
=========================================

 The
 **`CanvasRenderingContext2D.filter`**
 property of the Canvas 2D API provides filter effects such as blurring and grayscaling.
 It is similar to the CSS `filter` property and accepts the same values.

Value
-----

 The `filter` property accepts a value of `"none"` or one or more
 of the following filter functions in a string.

`url()`

 A CSS `url()`. Takes an IRI pointing to an SVG filter element,
 which may be embedded in an external XML file.

`blur()`

 A CSS `<length>`. Applies a Gaussian blur to the drawing. It
 defines the value of the standard deviation to the Gaussian function, i.e., how many
 pixels on the screen blend into each other; thus, a larger value will create more
 blur. A value of `0` leaves the input unchanged.

`brightness()`

 A CSS `<percentage>`. Applies a linear multiplier to the drawing,
 making it appear brighter or darker. A value under `100%` darkens the
 image, while a value over `100%` brightens it. A value of `0%`
 will create an image that is completely black, while a value of `100%`
 leaves the input unchanged.

`contrast()`

 A CSS `<percentage>`. Adjusts the contrast of the drawing. A
 value of `0%` will create a drawing that is completely black. A value of
 `100%` leaves the drawing unchanged.

`drop-shadow()`

 Applies a drop shadow effect to the drawing. A drop shadow is effectively a blurred,
 offset version of the drawing's alpha mask drawn in a particular color, composited
 below the drawing. This function takes up to five arguments:

`<offset-x>`

 See `<length>` for possible
 units. Specifies the horizontal distance of the shadow.

`<offset-y>`

 See `<length>` for possible
 units. Specifies the vertical distance of the shadow.

`<blur-radius>`

 The larger this value, the bigger the blur, so
 the shadow becomes bigger and lighter. Negative values are not allowed.

`<color>`

 See `<color>` values for possible
 keywords and notations.

`grayscale()`

 A CSS `<percentage>`. Converts the drawing to grayscale. A value
 of `100%` is completely grayscale. A value of `0%` leaves the
 drawing unchanged.

`hue-rotate()`

 A CSS `<angle>`. Applies a hue rotation on the drawing. A value
 of `0deg` leaves the input unchanged.

`invert()`

 A CSS `<percentage>`. Inverts the drawing. A value of
 `100%` means complete inversion. A value of `0%` leaves the
 drawing unchanged.

`opacity()`

 A CSS `<percentage>`. Applies transparency to the drawing. A
 value of `0%` means completely transparent. A value of `100%`
 leaves the drawing unchanged.

`saturate()`

 A CSS `<percentage>`. Saturates the drawing. A value of
 `0%` means completely un-saturated. A value of `100%` leaves the
 drawing unchanged.

`sepia()`

 A CSS `<percentage>`. Converts the drawing to sepia. A value of
 `100%` means completely sepia. A value of `0%` leaves the
 drawing unchanged.

`none`

No filter is applied. Initial value.

Examples
--------

 To view these examples, make sure to use a browser that supports this feature; see the
 compatibility table below.

### Applying a blur

This example blurs a piece of text using the `filter` property.

#### HTML

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

#### JavaScript

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

ctx.filter = "blur(4px)";
ctx.font = "48px serif";
ctx.fillText("Hello world", 50, 100);
```

#### Result

### Applying multiple filters

 You can combine as many filters as you like. This example applies the
 `contrast`, `sepia`, and `drop-shadow` filters to a
 photo of a rhino.

#### HTML

```html
<canvas id="canvas" width="400" height="150"></canvas>
<div style="display:none;">
  <img id="source" src="rhino.jpg" />
</div>
```

#### JavaScript

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

image.addEventListener("load", (e) => {
  // Draw unfiltered image
  ctx.drawImage(image, 0, 0, image.width \* 0.6, image.height \* 0.6);

  // Draw image with filter
  ctx.filter = "contrast(1.4) sepia(1) drop-shadow(-9px 9px 3px #e81)";
  ctx.drawImage(image, 400, 0, -image.width \* 0.6, image.height \* 0.6);
});
```

#### Result

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

| Specification |
| --- |
| HTML Standard # dom-context-2d-filter-dev |

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

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

See also
--------

* The interface defining this property: `CanvasRenderingContext2D`
* CSS `filter`
* CSS `<filter-function>`


CanvasRenderingContext2D: createImageData() method - Web APIs

CanvasRenderingContext2D: createImageData() method
==================================================

 The **`CanvasRenderingContext2D.createImageData()`** method of
 the Canvas 2D API creates a new, blank `ImageData` object with the
 specified dimensions. All of the pixels in the new object are transparent black.

Syntax
------

```js
createImageData(width, height)
createImageData(width, height, settings)
createImageData(imagedata)
```

### Parameters

`width`

 The width to give the new `ImageData` object. A negative value flips the
 rectangle around the vertical axis.

`height`

 The height to give the new `ImageData` object. A negative value flips the
 rectangle around the horizontal axis.

`settings` Optional

An object with the following properties:

* `colorSpace`: Specifies the color space of the image data. Can be set to `"srgb"` for the sRGB color space or `"display-p3"` for the display-p3 color space.

`imagedata`

 An existing `ImageData` object from which to copy the width and height.
 The image itself is **not** copied.

### Return value

 A new `ImageData` object with the specified width and height. The new
 object is filled with transparent black pixels.

### Exceptions

`IndexSizeError` `DOMException`

Thrown if either of the `width` or `height` arguments is zero.

Examples
--------

### Creating a blank ImageData object

 This snippet creates a blank `ImageData` object using the
 `createImageData()` method.

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

 The generated object is 100 pixels wide and 50 pixels tall, making 5,000 pixels in all.
 Each pixel within an `ImageData` object consists of four array values, so the
 object's `data` property has a length of 4 × 5,000, or
 20,000.

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

const imageData = ctx.createImageData(100, 50);
console.log(imageData);
// ImageData { width: 100, height: 50, data: Uint8ClampedArray[20000] }
```

### Filling a blank ImageData object

This example creates and fills a new `ImageData` object with purple pixels.

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

 Since each pixel consists of four values, the `for` loop iterates by
 multiples of four. The array values associated with each pixel are R (red), G (green), B
 (blue), and A (alpha), in that order.

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

// Iterate through every pixel
for (let i = 0; i < imageData.data.length; i += 4) {
  // Modify pixel data
  imageData.data[i + 0] = 190; // R value
  imageData.data[i + 1] = 0; // G value
  imageData.data[i + 2] = 210; // B value
  imageData.data[i + 3] = 255; // A value
}

// Draw image data to the canvas
ctx.putImageData(imageData, 20, 20);
```

#### Result

### More examples

 For more examples using `createImageData()` and the `ImageData`
 object, see Pixel manipulation with canvas and `ImageData.data`.

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

| Specification |
| --- |
| HTML Standard # dom-context-2d-createimagedata-dev |

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

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

See also
--------

* The interface defining this method: `CanvasRenderingContext2D`
* `ImageData`
* Pixel manipulation with canvas


CanvasRenderingContext2D: strokeRect() method - Web APIs

CanvasRenderingContext2D: strokeRect() method
=============================================

 The
 **`CanvasRenderingContext2D.strokeRect()`**
 method of the Canvas 2D API draws a rectangle that is stroked (outlined) according to
 the current `strokeStyle` and other
 context settings.

 This method draws directly to the canvas without modifying the current path, so any
 subsequent `fill()` or
 `stroke()` calls will have no effect
 on it.

Syntax
------

```js
strokeRect(x, y, width, height)
```

 The `strokeRect()` method draws a stroked rectangle whose starting point is
 at `(x, y)` and whose size is specified by `width` and
 `height`.

### Parameters

`x`

The x-axis coordinate of the rectangle's starting point.

`y`

The y-axis coordinate of the rectangle's starting point.

`width`

The rectangle's width. Positive values are to the right, and negative to the left.

`height`

The rectangle's height. Positive values are down, and negative are up.

### Return value

None (`undefined`).

Examples
--------

### A simple stroked rectangle

 This example draws a rectangle with a green outline using the `strokeRect()`
 method.

#### HTML

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

#### JavaScript

 The rectangle's top-left corner is at (20, 10). It has a width of 160 and a height of
 100.

```js
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
ctx.strokeStyle = "green";
ctx.strokeRect(20, 10, 160, 100);
```

#### Result

### Applying various context settings

This example draws a rectangle with a drop shadow and thick, beveled outlines.

#### HTML

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

#### JavaScript

```js
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
ctx.shadowColor = "#d53";
ctx.shadowBlur = 20;
ctx.lineJoin = "bevel";
ctx.lineWidth = 15;
ctx.strokeStyle = "#38f";
ctx.strokeRect(30, 30, 160, 90);
```

#### Result

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

| Specification |
| --- |
| HTML Standard # dom-context-2d-strokerect-dev |

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

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

See also
--------

* The interface defining this method: `CanvasRenderingContext2D`
* `CanvasRenderingContext2D.strokeStyle`
* `CanvasRenderingContext2D.clearRect()`
* `CanvasRenderingContext2D.fillRect()`


CanvasRenderingContext2D: clearRect() method - Web APIs

CanvasRenderingContext2D: clearRect() method
============================================

 The
 **`CanvasRenderingContext2D.clearRect()`**
 method of the Canvas 2D API erases the pixels in a rectangular area by setting them to
 transparent black.

**Note:** Be aware that `clearRect()` may cause unintended
 side effects if you're not using paths properly. Make sure to call
 `beginPath()` before starting to
 draw new items after calling `clearRect()`.

Syntax
------

```js
clearRect(x, y, width, height)
```

 The `clearRect()` method sets the pixels in a rectangular area to
 transparent black (`rgb(0 0 0 / 0%)`). The rectangle's top-left corner is at
 `(x, y)`, and its size is specified by `width` and
 `height`.

### Parameters

`x`

The x-axis coordinate of the rectangle's starting point.

`y`

The y-axis coordinate of the rectangle's starting point.

`width`

The rectangle's width. Positive values are to the right, and negative to the left.

`height`

The rectangle's height. Positive values are down, and negative are up.

### Return value

None (`undefined`).

Examples
--------

### Erasing the whole canvas

 This code snippet erases the entire canvas. This is commonly required at the start of
 each frame in an animation. The dimensions of the cleared area are set to equal the
 `<canvas>` element's `width` and `height`
 attributes.

```js
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
```

### Erasing part of a canvas

 This example draws a blue triangle on top of a yellowish background. The
 `clearRect()` method then erases part of the canvas.

#### HTML

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

#### JavaScript

 The cleared area is rectangular in shape, with its top-left corner at (10, 10). The
 cleared area has a width of 120 and a height of 100.

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

// Draw yellow background
ctx.beginPath();
ctx.fillStyle = "#ff6";
ctx.fillRect(0, 0, canvas.width, canvas.height);

// Draw blue triangle
ctx.beginPath();
ctx.fillStyle = "blue";
ctx.moveTo(20, 20);
ctx.lineTo(180, 20);
ctx.lineTo(130, 130);
ctx.closePath();
ctx.fill();

// Clear part of the canvas
ctx.clearRect(10, 10, 120, 100);
```

#### Result

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

| Specification |
| --- |
| HTML Standard # dom-context-2d-clearrect-dev |

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

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

See also
--------

* The interface defining this method: `CanvasRenderingContext2D`
* `CanvasRenderingContext2D.fillRect()`
* `CanvasRenderingContext2D.strokeRect()`


CanvasRenderingContext2D: putImageData() method - Web APIs

CanvasRenderingContext2D: putImageData() method
===============================================

 The **`CanvasRenderingContext2D.putImageData()`**
 method of the Canvas 2D API paints data from the given `ImageData` object
 onto the canvas. If a dirty rectangle is provided, only the pixels from that rectangle
 are painted. This method is not affected by the canvas transformation matrix.

**Note:** Image data can be retrieved from a canvas using the
 `getImageData()` method.

 You can find more information about `putImageData()` and general
 manipulation of canvas contents in the article Pixel manipulation with canvas.

Syntax
------

```js
putImageData(imageData, dx, dy)
putImageData(imageData, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight)
```

### Parameters

`imageData`

An `ImageData` object containing the array of pixel values.

`dx`

 Horizontal position (x coordinate) at which to place the image data in the
 destination canvas.

`dy`

 Vertical position (y coordinate) at which to place the image data in the destination
 canvas.

`dirtyX` Optional

 Horizontal position (x coordinate) of the top-left corner from which the image data
 will be extracted. Defaults to `0`.

`dirtyY` Optional

 Vertical position (y coordinate) of the top-left corner from which the image data
 will be extracted. Defaults to `0`.

`dirtyWidth` Optional

Width of the rectangle to be painted. Defaults to the width of the image data.

`dirtyHeight` Optional

Height of the rectangle to be painted. Defaults to the height of the image data.

### Return value

None (`undefined`).

### Exceptions

`NotSupportedError` `DOMException`

Thrown if any of the arguments is infinite.

`InvalidStateError` `DOMException`

Thrown if the `ImageData` object's data has been detached.

Examples
--------

### Understanding putImageData

 To understand what this algorithm does under the hood, here is an implementation on top
 of `CanvasRenderingContext2D.fillRect()`.

#### HTML

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

#### JavaScript

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

function putImageData(
  ctx,
 imageData,
 dx,
 dy,
 dirtyX,
 dirtyY,
 dirtyWidth,
 dirtyHeight,
) {
  const data = imageData.data;
  const height = imageData.height;
  const width = imageData.width;
  dirtyX = dirtyX || 0;
  dirtyY = dirtyY || 0;
  dirtyWidth = dirtyWidth !== undefined ? dirtyWidth : width;
  dirtyHeight = dirtyHeight !== undefined ? dirtyHeight : height;
  const limitBottom = dirtyY + dirtyHeight;
  const limitRight = dirtyX + dirtyWidth;
  for (let y = dirtyY; y < limitBottom; y++) {
    for (let x = dirtyX; x < limitRight; x++) {
      const pos = y \* width + x;
      ctx.fillStyle = `rgb(${data[pos \* 4 + 0]} ${data[pos \* 4 + 1]}
 ${data[pos \* 4 + 2]} / ${data[pos \* 4 + 3] / 255})`;
      ctx.fillRect(x + dx, y + dy, 1, 1);
    }
  }
}

// Draw content onto the canvas
ctx.fillRect(0, 0, 100, 100);
// Create an ImageData object from it
const imagedata = ctx.getImageData(0, 0, 100, 100);
// use the putImageData function that illustrates how putImageData works
putImageData(ctx, imagedata, 150, 0, 50, 50, 25, 25);
```

#### Result

### Data loss due to browser optimization

**Warning:** Due to the lossy nature of converting to and from premultiplied alpha color values,
 pixels that have just been set using `putImageData()` might be returned to
 an equivalent `getImageData()` as different values.

#### JavaScript

```js
const canvas = document.createElement("canvas");
canvas.width = 1;
canvas.height = 1;
const context = canvas.getContext("2d");
const imgData = context.getImageData(0, 0, canvas.width, canvas.height);
const pixels = imgData.data;
pixels[0 + 0] = 1;
pixels[0 + 1] = 127;
pixels[0 + 2] = 255;
pixels[0 + 3] = 1;
console.log("before:", pixels);
context.putImageData(imgData, 0, 0);
const imgData2 = context.getImageData(0, 0, canvas.width, canvas.height);
const pixels2 = imgData2.data;
console.log("after:", pixels2);
```

The output might look like:
```

before: Uint8ClampedArray(4) [ 1, 127, 255, 1 ]
after: Uint8ClampedArray(4) [ 255, 255, 255, 1 ]
```

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

| Specification |
| --- |
| HTML Standard # dom-context-2d-putimagedata-dev |

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

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

See also
--------

* The interface defining this method: `CanvasRenderingContext2D`
* `ImageData` object
* `CanvasRenderingContext2D.getImageData()`
* Pixel manipulation with canvas


CanvasRenderingContext2D: lineDashOffset property - Web APIs

CanvasRenderingContext2D: lineDashOffset property
=================================================

 The
 **`CanvasRenderingContext2D.lineDashOffset`**
 property of the Canvas 2D API sets the line dash offset, or "phase."

**Note:** Lines are drawn by calling the
 `stroke()` method.

Value
-----

A float specifying the amount of the line dash offset. The default value is `0.0`.

Examples
--------

### Offsetting a line dash

 This example draws two dashed lines. The first has no dash offset. The second has a
 dash offset of 4.

#### HTML

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

#### JavaScript

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

ctx.setLineDash([4, 16]);

// Dashed line with no offset
ctx.beginPath();
ctx.moveTo(0, 50);
ctx.lineTo(300, 50);
ctx.stroke();

// Dashed line with offset of 4
ctx.beginPath();
ctx.strokeStyle = "red";
ctx.lineDashOffset = 4;
ctx.moveTo(0, 100);
ctx.lineTo(300, 100);
ctx.stroke();
```

#### Result

The line with a dash offset is drawn in red.

### Marching ants

 The marching ants effect is
 an animation technique often found in selection tools of computer graphics programs. It
 helps the user to distinguish the selection border from the image background by
 animating the border.
```

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

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

function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.setLineDash([4, 2]);
  ctx.lineDashOffset = -offset;
  ctx.strokeRect(10, 10, 100, 100);
}

function march() {
  offset++;
  if (offset > 5) {
    offset = 0;
  }
  draw();
  setTimeout(march, 20);
}

march();
```

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

| Specification |
| --- |
| HTML Standard # dom-context-2d-linedashoffset-dev |

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

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

See also
--------

* The interface defining this property: `CanvasRenderingContext2D`
* `CanvasRenderingContext2D.getLineDash()`
* `CanvasRenderingContext2D.setLineDash()`
* Applying styles and color


CanvasRenderingContext2D: reset() method - Web APIs

CanvasRenderingContext2D: reset() method
========================================

The **`CanvasRenderingContext2D.reset()`** method of the Canvas 2D API resets the rendering context to its default state, allowing it to be reused for drawing something else without having to explicitly reset all the properties.

 Resetting clears the backing buffer, drawing state stack, any defined paths, and styles.
 This includes the current transformation matrix, compositing properties, clipping region, dash list, line styles, text styles, shadows, image smoothing, filters, and so on.

Syntax
------

```js
reset()
```

### Parameters

None.

### Return value

None (`undefined`).

Examples
--------

This example shows how we can use `reset()` to completely clear the context before redrawing.

First we define a button and a canvas.

```css
#toggle-reset {
  display: block;
}
```

```html
<button id="toggle-reset">Toggle</button>
<canvas id="my-house" width="500" height="200"></canvas>
```

 The code first gets a `2d` context for the canvas.
 It then defines functions that can use the context to draw a rectangle and a circle, respectively.

```js
// Get the 2d context
const canvas = document.getElementById("my-house");
const ctx = canvas.getContext("2d");

function drawRect() {
  // Set line width
  ctx.lineWidth = 10;

  // Stroke rect outline
  ctx.strokeRect(50, 50, 150, 100);

  // Create filled text
  ctx.font = "50px serif";
  ctx.fillText("Rect!", 70, 110);
}

function drawCircle() {
  // Set line width
  ctx.lineWidth = 5;

  // Stroke out circle
  ctx.beginPath();
  ctx.arc(300, 100, 50, 0, 2 \* Math.PI);
  ctx.stroke();

  // Create filled text
  ctx.font = "25px sans-serif";
  ctx.fillText("Circle!", 265, 100);
}
```

 We then draw the rectangle using its function.
 The button toggles drawing the circle and rectangle.
 Note how `reset()` is called before drawing to clear the context.

```js
drawRect();

// Toggle between circle and rectangle using button
let toggle = true;
const mybutton = document.getElementById("toggle-reset");

mybutton.addEventListener("click", () => {
  ctx.reset(); // Clear the context!
  if (toggle) {
    drawCircle();
  } else {
    drawRect();
  }
  toggle = !toggle;
});
```

The result looks like this:

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

| Specification |
| --- |
| HTML Standard # dom-context-2d-reset |

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

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

See also
--------

* The interface defining this method: `CanvasRenderingContext2D`


CanvasRenderingContext2D: getContextAttributes() method - Web APIs

CanvasRenderingContext2D: getContextAttributes() method
=======================================================

The **`CanvasRenderingContext2D.getContextAttributes()`** method returns an object that contains attributes used by the context.

Note that context attributes may be requested when creating the context with `HTMLCanvasElement.getContext()`, but the attributes that are actually supported and used may differ.

Syntax
------

```js
getContextAttributes()
```

### Parameters

None.

### Return value

 A `CanvasRenderingContext2DSettings` object that contains the actual context parameters.
 It has the following members:

`alpha` Optional

 A Boolean indicating if the canvas contains an alpha channel.
 If `false`, the backdrop is always opaque, which can speed up drawing of transparent content and images.

`colorSpace` Optional

Specifies the color space of the rendering context. Possible values are:

* `srgb`: denotes the sRGB color space
* `display-p3`: denotes the display-p3 color space

`desynchronized` Optional

A Boolean indicating the user agent reduced the latency by desynchronizing the canvas paint cycle from the event loop.

`willReadFrequently` Optional

A Boolean indicating whether or not this canvas uses software acceleration (instead of hardware acceleration) to support frequent read-back operations via`getImageData()`.

Examples
--------

This example shows how you can specify context attributes when creating a canvas context, and then call `getContextAttributes()` to read back the actual parameters that the browser used.
```

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

```
const logElement = document.getElementById("log");
function log(text) {
  logElement.innerText += text;
}
```

First we create a context using `HTMLCanvasElement.getContext()`, specifying just one context attribute.

```js
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d", { alpha: false });
```

If the `getContextAttributes()` method is supported, we use it to read back the actual attributes used by the browser (including those we explicitly specified):

```js
if (ctx.getContextAttributes) {
  const attributes = ctx.getContextAttributes();
  log(JSON.stringify(attributes));
} else {
  log("CanvasRenderingContext2D.getContextAttributes() is not supported");
}
```

Depending on the attributes supported by the browser, the log below should display a string that looks something like: `{alpha: false, colorSpace: 'srgb', desynchronized: false, willReadFrequently: false}`

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

| Specification |
| --- |
| HTML Standard # 2dcontext:dom-context-2d-canvas-getcontextattributes-2 |

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

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

See also
--------

* `HTMLCanvasElement.getContext()`
* `WebGLRenderingContext.getContextAttributes()`


CanvasRenderingContext2D: setLineDash() method - Web APIs

CanvasRenderingContext2D: setLineDash() method
==============================================

 The **`setLineDash()`** method of the Canvas 2D API's
 `CanvasRenderingContext2D` interface sets the line dash pattern used when
 stroking lines. It uses an array of values that specify alternating lengths of lines
 and gaps which describe the pattern.

**Note:** To return to using solid lines, set the line dash list to an
 empty array.

Syntax
------

```js
setLineDash(segments)
```

### Parameters

`segments`

 An `Array` of numbers that specify distances to alternately draw a
 line and a gap (in coordinate space units). If the number of elements in the array
 is odd, the elements of the array get copied and concatenated. For example,
 `[5, 15, 25]` will become `[5, 15, 25, 5, 15, 25]`. If the
 array is empty, the line dash list is cleared and line strokes return to being
 solid.

### Return value

None (`undefined`).

Examples
--------

### Basic example

 This example uses the `setLineDash()` method to draw a dashed line above a
 solid line.

#### HTML

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

#### JavaScript

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

// Dashed line
ctx.beginPath();
ctx.setLineDash([5, 15]);
ctx.moveTo(0, 50);
ctx.lineTo(300, 50);
ctx.stroke();

// Solid line
ctx.beginPath();
ctx.setLineDash([]);
ctx.moveTo(0, 100);
ctx.lineTo(300, 100);
ctx.stroke();
```

#### Result

### Some common patterns

This example illustrates a variety of common line dash patterns.

#### HTML

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

#### JavaScript

 The `drawDashedLine()` function created below makes the drawing of multiple
 dashed lines simple. It receives a pattern array as its only parameter.

```js
function drawDashedLine(pattern) {
  ctx.beginPath();
  ctx.setLineDash(pattern);
  ctx.moveTo(0, y);
  ctx.lineTo(300, y);
  ctx.stroke();
  y += 20;
}

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
let y = 15;

drawDashedLine([]);
drawDashedLine([1, 1]);
drawDashedLine([10, 10]);
drawDashedLine([20, 5]);
drawDashedLine([15, 3, 3, 3]);
drawDashedLine([20, 3, 3, 3, 3, 3, 3, 3]);
drawDashedLine([12, 3, 3]); // Equals [12, 3, 3, 12, 3, 3]
```

#### Result

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

| Specification |
| --- |
| HTML Standard # dom-context-2d-setlinedash-dev |

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

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

See also
--------

* The interface defining this method: `CanvasRenderingContext2D`
* `CanvasRenderingContext2D.getLineDash()`
* `CanvasRenderingContext2D.lineDashOffset`


CanvasRenderingContext2D: restore() method - Web APIs

CanvasRenderingContext2D: restore() method
==========================================

 The
 **`CanvasRenderingContext2D.restore()`**
 method of the Canvas 2D API restores the most recently saved canvas state by popping the
 top entry in the drawing state stack. If there is no saved state, this method does
 nothing.

For more information about the drawing state, see `CanvasRenderingContext2D.save()`.

Syntax
------

```js
restore()
```

### Parameters

None.

### Return value

None (`undefined`).

Examples
--------

### Restoring a saved state

 This example uses the `save()` method to save the current state and
 `restore()` to restore it later, so that you are able to draw a rect with the
 current state later.

#### HTML

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

#### JavaScript

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

// Save the current state
ctx.save();

ctx.fillStyle = "green";
ctx.fillRect(10, 10, 100, 100);

// Restore to the state saved by the most recent call to save()
ctx.restore();

ctx.fillRect(150, 40, 100, 100);
```

#### Result

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

| Specification |
| --- |
| HTML Standard # dom-context-2d-restore-dev |

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

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

See also
--------

* The interface defining this method: `CanvasRenderingContext2D`
* `CanvasRenderingContext2D.save()`


CanvasRenderingContext2D: lineJoin property - Web APIs

CanvasRenderingContext2D: lineJoin property
===========================================

 The
 **`CanvasRenderingContext2D.lineJoin`**
 property of the Canvas 2D API determines the shape used to join two line segments where
 they meet.

 This property has no effect wherever two connected segments have the same direction,
 because no joining area will be added in this case. Degenerate segments with a length of
 zero (i.e., with all endpoints and control points at the exact same position) are also
 ignored.

**Note:** Lines can be drawn with the
 `stroke()`,
 `strokeRect()`,
 and `strokeText()` methods.

Value
-----

There are three possible values for this property: `"round"`, `"bevel"`, and `"miter"`. The default is `"miter"`.

![Three horizontal zigzag lines with round, bevel, and miter values, shown from top to bottom respectively.](/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin/canvas_linejoin.png)

`"round"`

 Rounds off the corners of a shape by filling an additional sector of disc centered
 at the common endpoint of connected segments. The radius for these rounded corners is
 equal to the line width.

`"bevel"`

 Fills an additional triangular area between the common endpoint of connected
 segments, and the separate outside rectangular corners of each segment.

`"miter"`

 Connected segments are joined by extending their outside edges to connect at a
 single point, with the effect of filling an additional lozenge-shaped area. This
 setting is affected by the `miterLimit` property. Default value.

Examples
--------

### Changing the joins in a path

This example applies rounded line joins to a path.

#### HTML

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

#### JavaScript

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

ctx.lineWidth = 20;
ctx.lineJoin = "round";
ctx.beginPath();
ctx.moveTo(20, 20);
ctx.lineTo(190, 100);
ctx.lineTo(280, 20);
ctx.lineTo(280, 150);
ctx.stroke();
```

#### Result

### Comparison of line joins

 The example below draws three different paths, demonstrating each of the three
 `lineJoin` options.
```

<canvas id="canvas" width="150" height="150"></canvas>
```

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

["round", "bevel", "miter"].forEach((join, i) => {
  ctx.lineJoin = join;
  ctx.beginPath();
  ctx.moveTo(-5, 5 + i \* 40);
  ctx.lineTo(35, 45 + i \* 40);
  ctx.lineTo(75, 5 + i \* 40);
  ctx.lineTo(115, 45 + i \* 40);
  ctx.lineTo(155, 5 + i \* 40);
  ctx.stroke();
});
```

| Screenshot | Live sample |
| --- | --- |
|  |  |

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

| Specification |
| --- |
| HTML Standard # dom-context-2d-linejoin-dev |

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

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

### WebKit/Blink-specific notes

* In WebKit- and Blink-based Browsers, a non-standard and deprecated method
 `ctx.setLineJoin()` is implemented in addition to this property.
See also
--------

* The interface defining this property: `CanvasRenderingContext2D`
* `CanvasRenderingContext2D.lineCap`
* `CanvasRenderingContext2D.lineWidth`
* Applying styles and color