<input type="search"> - HTML: HyperText Markup Language

<input type="search">
=====================

`<input>` elements of type **`search`** are text fields designed for the user to enter search queries into. These are functionally identical to `text` inputs, but may be styled differently by the user agent.

Try it
------

Value
-----

The `value` attribute contains a string representing the value contained in the search field. You can retrieve this using the `HTMLInputElement.value` property in JavaScript.

```js
searchTerms = mySearch.value;
```

If no validation constraints are in place for the input (see Validation for more details), the value can be any text string or an empty string (`""`).

Additional attributes
---------------------

In addition to the attributes that operate on all `<input>` elements regardless of their type, search field inputs support the following attributes.

### list

The values of the list attribute is the `id` of a `<datalist>` element located in the same document. The `<datalist>` provides a list of predefined values to suggest to the user for this input. Any values in the list that are not compatible with the `type` are not included in the suggested options. The values provided are suggestions, not requirements: users can select from this predefined list or provide a different value.

### maxlength

The maximum string length (measured in UTF-16 code units) that the user can enter into the search field. This must be an integer value of 0 or higher. If no `maxlength` is specified, or an invalid value is specified, the search field has no maximum length. This value must also be greater than or equal to the value of `minlength`.

The input will fail constraint validation if the length of the text entered into the field is greater than `maxlength` UTF-16 code units long.

### minlength

The minimum string length (measured in UTF-16 code units) that the user can enter into the search field. This must be a non-negative integer value smaller than or equal to the value specified by `maxlength`. If no `minlength` is specified, or an invalid value is specified, the search input has no minimum length.

The search field will fail constraint validation if the length of the text entered into the field is fewer than `minlength` UTF-16 code units long.

### pattern

The `pattern` attribute, when specified, is a regular expression that the input's `value` must match for the value to pass constraint validation. It must be a valid JavaScript regular expression, as used by the `RegExp` type, and as documented in our guide on regular expressions; the `'u'` flag is specified when compiling the regular expression so that the pattern is treated as a sequence of Unicode code points, instead of as ASCII. No forward slashes should be specified around the pattern text.

If the specified pattern is not specified or is invalid, no regular expression is applied and this attribute is ignored completely.

**Note:** Use the `title` attribute to specify text that most browsers will display as a tooltip to explain what the requirements are to match the pattern. You should also include other explanatory text nearby.

See the section Specifying a pattern for details and an example.

### placeholder

The `placeholder` attribute is a string that provides a brief hint to the user as to what kind of information is expected in the field. It should be a word or short phrase that demonstrates the expected type of data, rather than an explanatory message. The text *must not* include carriage returns or line feeds.

If the control's content has one directionality (LTR or RTL) but needs to present the placeholder in the opposite directionality, you can use Unicode bidirectional algorithm formatting characters to override directionality within the placeholder; see How to use Unicode controls for bidi text for more information.

**Note:** Avoid using the `placeholder` attribute if you can. It is not as semantically useful as other ways to explain your form, and can cause unexpected technical issues with your content. See `<input>` labels for more information.

### readonly

A Boolean attribute which, if present, means this field cannot be edited by the user. Its `value` can, however, still be changed by JavaScript code directly setting the `HTMLInputElement` `value` property.

**Note:** Because a read-only field cannot have a value, `required` does not have any effect on inputs with the `readonly` attribute also specified.

### size

The `size` attribute is a numeric value indicating how many characters wide the input field should be. The value must be a number greater than zero, and the default value is 20. Since character widths vary, this may or may not be exact and should not be relied upon to be so; the resulting input may be narrower or wider than the specified number of characters, depending on the characters and the font (`font` settings in use).

This does *not* set a limit on how many characters the user can enter into the field. It only specifies approximately how many can be seen at a time. To set an upper limit on the length of the input data, use the `maxlength` attribute.

### spellcheck

`spellcheck` is a global attribute which is used to indicate whether to enable spell checking for an element. It can be used on any editable content, but here we consider specifics related to the use of `spellcheck` on `<input>` elements. The permitted values for `spellcheck` are:

`false`

Disable spell checking for this element.

`true`

Enable spell checking for this element.

"" (empty string) or no value

Follow the element's default behavior for spell checking. This may be based upon a parent's `spellcheck` setting or other factors.

An input field can have spell checking enabled if it doesn't have the readonly attribute set and is not disabled.

The value returned by reading `spellcheck` may not reflect the actual state of spell checking within a control, if the user agent's preferences override the setting.

Non-standard attributes
-----------------------

The following non-standard attributes are available to search input fields. As a general rule, you should avoid using them unless it can't be helped.

### autocorrect

A Safari extension, the `autocorrect` attribute is a string which indicates whether to activate automatic correction while the user is editing this field. Permitted values are:

`on`

Enable automatic correction of typos, as well as processing of text substitutions if any are configured.

`off`

Disable automatic correction and text substitutions.

### incremental

The Boolean attribute `incremental` is a WebKit and Blink extension (so supported by Safari, Opera, Chrome, etc.) which, if present, tells the user agent to process the input as a live search. As the user edits the value of the field, the user agent sends `search` events to the `HTMLInputElement` object representing the search box. This allows your code to update the search results in real time as the user edits the search.

If `incremental` is not specified, the `search` event is only sent when the user explicitly initiates a search (such as by pressing the `Enter` or `Return` key while editing the field).

The `search` event is rate-limited so that it is not sent more frequently than an implementation-defined interval.

### mozactionhint
Deprecated

A Mozilla extension, which provides a hint as to what sort of action will be taken if the user presses the `Enter` or `Return` key while editing the field.

**Deprecated: Use `enterkeyhint` instead.**

### results

The `results` attribute—supported only by Safari—is a numeric value that lets you override the maximum number of entries to be displayed in the `<input>` element's natively-provided drop-down menu of previous search queries.

The value must be a non-negative decimal number. If not provided, or an invalid value is given, the browser's default maximum number of entries is used.

Using search inputs
-------------------

`<input>` elements of type `search` are very similar to those of type `text`, except that they are specifically intended for handling search terms. They are basically equivalent in behavior, but user agents may choose to style them differently by default (and, of course, sites may use stylesheets to apply custom styles to them).

### Basic example

```html
<form>
  <div>
    <input type="search" id="mySearch" name="q" />
    <button>Search</button>
  </div>
</form>
```

This renders like so:

`q` is the most common `name` given to search inputs, although it's not mandatory. When submitted, the data name/value pair sent to the server will be `q=searchterm`.

**Note:** You must remember to set a `name` for your input, otherwise nothing will be submitted.

### Differences between search and text types

The main basic differences come in the way browsers handle them. The first thing to note is that some browsers show a cross icon that can be clicked on to remove the search term instantly if desired, in Chrome this action is also triggered when pressing escape. The following screenshot comes from Chrome:

![Focused search input, with focus ring, with the text 'cats'. There is an x icon in the input abutting the right side.](/en-US/docs/Web/HTML/Element/input/search/chrome-cross-icon.png)

In addition, modern browsers also tend to automatically store search terms previously entered across domains, which then come up as autocomplete options when subsequent searches are performed in search inputs on that domain. This helps users who tend to do searches on the same or similar search queries over time. This screenshot is from Firefox:

![An input in error state with a red focus ring. The user has entered the letter 'h'. A pop-up selection list is open directly under the input box with two options: hello and hermansje.](/en-US/docs/Web/HTML/Element/input/search/firefox-auto-complete.png)At this point, let's look at some useful techniques you can apply to your search forms.

### Setting placeholders

You can provide a useful placeholder inside your search input that could give a hint on what to do using the `placeholder` attribute. Look at the following example:

```html
<form>
  <div>
    <input
 type="search"
 id="mySearch"
 name="q"
 placeholder="Search the site…" />
    <button>Search</button>
  </div>
</form>
```

You can see how the placeholder is rendered below:

### Search form labels and accessibility

One problem with search forms is their accessibility; a common design practice is not to provide a label for the search field (although there might be a magnifying glass icon or similar), as the purpose of a search form is normally fairly obvious for sighted users due to placement (this example shows a typical pattern).

This could, however, cause confusion for screen reader users, since they will not have any verbal indication of what the search input is. One way around this that won't impact on your visual design is to use WAI-ARIA features:

* A `role` attribute of value `search` on the `<form>` element will cause screen readers to announce that the form is a search form.
* If that isn't enough, you can use an `aria-label` attribute on the `<input>` itself. This should be a descriptive text label that will be read out by the screen reader; it's used as a non-visual equivalent to `<label>`.

Let's have a look at an example:

```html
<form role="search">
  <div>
    <input
 type="search"
 id="mySearch"
 name="q"
 placeholder="Search the site…"
 aria-label="Search through site content" />
    <button>Search</button>
  </div>
</form>
```

You can see how this is rendered below:

There is no visual difference from the previous example, but screen reader users have way more information available to them.

**Note:** See Signposts/Landmarks for more information about such accessibility features.

### Physical input element size

The physical size of the input box can be controlled using the `size` attribute. With it, you can specify the number of characters the input box can display at a time. In this example, for instance, the search box is 30 characters wide:

```html
<form>
  <div>
    <input
 type="search"
 id="mySearch"
 name="q"
 placeholder="Search the site…"
 size="30" />
    <button>Search</button>
  </div>
</form>
```

The result is this wider input box:

Validation
----------

`<input>` elements of type `search` have the same validation features available to them as regular `text` inputs. It is less likely that you'd want to use validation features in general for search boxes. In many cases, users should just be allowed to search for anything, but there are a few cases to consider, such as searches against data of a known format.

**Note:** HTML form validation is *not* a substitute for scripts that ensure that the entered data is in the proper format. It's far too easy for someone to make adjustments to the HTML that allow them to bypass the validation, or to remove it entirely. It's also possible for someone to bypass your HTML entirely and submit the data directly to your server. If your server-side code fails to validate the data it receives, disaster could strike when improperly-formatted data (or data which is too large, is of the wrong type, and so forth) is entered into your database.

### A note on styling

There are useful pseudo-classes available for styling valid/invalid form elements: `:valid` and `:invalid`. In this section, we'll use the following CSS, which will place a check (tick) next to inputs containing valid values, and a cross next to inputs containing invalid values.

```css
input:invalid ~ span::after {
  content: "✖";
  padding-left: 5px;
  position: absolute;
}

input:valid ~ span::after {
  content: "✓";
  padding-left: 5px;
  position: absolute;
}
```

The technique also requires a `<span>` element to be placed after the form element, which acts as a holder for the icons. This was necessary because some input types on some browsers don't display icons placed directly after them very well.

### Making input required

You can use the `required` attribute as an easy way of making entering a value required before form submission is allowed:

```html
<form>
  <div>
    <input
 type="search"
 id="mySearch"
 name="q"
 placeholder="Search the site…"
 required />
    <button>Search</button>
    <span class="validity"></span>
  </div>
</form>
```

```
input {
  margin-right: 10px;
}

input:invalid ~ span::after {
  content: "✖";
  padding-left: 5px;
  position: absolute;
}

input:valid ~ span::after {
  content: "✓";
  padding-left: 5px;
  position: absolute;
}
```

This renders like so:

In addition, if you try to submit the form with no search term entered into it, the browser will show a message. The following example is from Firefox:

![form field with attached message that says Please fill out this field](/en-US/docs/Web/HTML/Element/input/search/firefox-required-message.png)

Different messages will be shown when you try to submit the form with different types of invalid data contained inside the inputs; see the below examples.

### Input value length

You can specify a minimum length, in characters, for the entered value using the `minlength` attribute; similarly, use `maxlength` to set the maximum length of the entered value.

The example below requires that the entered value be 4–8 characters in length.

```html
<form>
  <div>
    <label for="mySearch">Search for user</label>
    <input
 type="search"
 id="mySearch"
 name="q"
 placeholder="User IDs are 4–8 characters in length"
 required
 size="30"
 minlength="4"
 maxlength="8" />
    <button>Search</button>
    <span class="validity"></span>
  </div>
</form>
```

```
input {
  margin-right: 10px;
}

input:invalid ~ span::after {
  content: "✖";
  padding-left: 5px;
  position: absolute;
}

input:valid ~ span::after {
  content: "✓";
  padding-left: 5px;
  position: absolute;
}
```

This renders like so:

If you try to submit the form with less than 4 characters, you'll be given an appropriate error message (which differs between browsers). If you try to go beyond 8 characters in length, the browser won't let you.

### Specifying a pattern

You can use the `pattern` attribute to specify a regular expression that the inputted value must follow to be considered valid (see Validating against a regular expression for a simple crash course).

Let's look at an example. Say we wanted to provide a product ID search form, and the IDs were all codes of two letters followed by four numbers. The following example covers it:

```html
<form>
  <div>
    <label for="mySearch">Search for product by ID:</label>
    <input
 type="search"
 id="mySearch"
 name="q"
 placeholder="two letters followed by four numbers"
 required
 size="30"
 pattern="[A-z]{2}[0-9]{4}" />
    <button>Search</button>
    <span class="validity"></span>
  </div>
</form>
```

```
input {
  margin-right: 10px;
}

input:invalid ~ span::after {
  content: "✖";
  padding-left: 5px;
  position: absolute;
}

input:valid ~ span::after {
  content: "✓";
  padding-left: 5px;
  position: absolute;
}
```

This renders like so:

Examples
--------

You can see a good example of a search form used in context at our website-aria-roles example (see it live).

Technical summary
-----------------

|  |  |
| --- | --- |
| **Value** |
 A string representing the value contained in
 the search field.
  |
| **Events** | `change` and
 `input` |
| **Supported Common Attributes** | `autocomplete`,
 `list`,
 `maxlength`,
 `minlength`,
 `pattern`,
 `placeholder`,
 `required`,
 `size`.
  |
| **IDL attributes** | `value` |
| **DOM interface** | `HTMLInputElement` |
| **Methods** | `select()`,
 `setRangeText()`,
 `setSelectionRange()`.
  |
| **Implicit ARIA Role** | with no `list` attribute: `searchbox` | with `list` attribute: `combobox` |

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

| Specification |
| --- |
| HTML Standard # text-(type=text)-state-and-search-state-(type=search) |

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

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

See also
--------

* HTML Forms
* `<input>` and the `HTMLInputElement` interface it's based upon
* `<input type="text">`
* Compatibility of CSS properties


<input type="radio"> - HTML: HyperText Markup Language

<input type="radio">
====================

`<input>` elements of type **`radio`** are generally used in **radio groups**—collections of radio buttons describing a set of related options.

Only one radio button in a given group can be selected at the same time. Radio buttons are typically rendered as small circles, which are filled or highlighted when selected.

Try it
------

They are called radio buttons because they look and operate in a similar manner to the push buttons on old-fashioned radios, such as the one shown below.

![Shows what radio buttons looked like in the olden days.](/en-US/docs/Web/HTML/Element/input/radio/old-radio.jpg)

**Note:** Checkboxes are similar to radio buttons, but with an important distinction: radio buttons are designed for selecting one value out of a set, whereas checkboxes let you turn individual values on and off. Where multiple controls exist, radio buttons allow one to be selected out of them all, whereas checkboxes allow multiple values to be selected.

Value
-----

The `value` attribute is a string containing the radio button's value. The value is never shown to the user by their user agent. Instead, it's used to identify which radio button in a group is selected.

### Defining a radio group

A radio group is defined by giving each of radio buttons in the group the same `name`. Once a radio group is established, selecting any radio button in that group automatically deselects any currently-selected radio button in the same group.

You can have as many radio groups on a page as you like, as long as each has its own unique `name`.

For example, if your form needs to ask the user for their preferred contact method, you might create three radio buttons, each with the `name` property set to `contact` but one with the value `email`, one with the value `phone`, and one with the value `mail`. The user never sees the `value` or the `name` (unless you expressly add code to display it).

The resulting HTML looks like this:

```html
<form>
  <fieldset>
    <legend>Please select your preferred contact method:</legend>
    <div>
      <input type="radio" id="contactChoice1" name="contact" value="email" />
      <label for="contactChoice1">Email</label>

      <input type="radio" id="contactChoice2" name="contact" value="phone" />
      <label for="contactChoice2">Phone</label>

      <input type="radio" id="contactChoice3" name="contact" value="mail" />
      <label for="contactChoice3">Mail</label>
    </div>
    <div>
      <button type="submit">Submit</button>
    </div>
  </fieldset>
</form>
```

Here you see the three radio buttons, each with the `name` set to `contact` and each with a unique `value` that uniquely identifies that individual radio button within the group. They each also have a unique `id`, which is used by the `<label>` element's `for` attribute to associate the labels with the radio buttons.

You can try out this example here:

### Data representation of a radio group

When the above form is submitted with a radio button selected, the form's data includes an entry in the form `contact=value`. For example, if the user clicks on the "Phone" radio button then submits the form, the form's data will include the line `contact=phone`.

If you omit the `value` attribute in the HTML, the submitted form data assigns the value `on` to the group. In this scenario, if the user clicked on the "Phone" option and submitted the form, the resulting form data would be `contact=on`, which isn't helpful. So don't forget to set your `value` attributes!

**Note:** If no radio button is selected when the form is submitted, the radio group is not included in the submitted form data at all, since there is no value to report.

It's fairly uncommon to actually want to allow the form to be submitted without any of the radio buttons in a group selected, so it is usually wise to have one default to the `checked` state. See Selecting a radio button by default below.

Let's add a bit of code to our example so we can examine the data generated by this form. The HTML is revised to add a `<pre>` block to output the form data into:

```html
<form>
  <fieldset>
    <legend>Please select your preferred contact method:</legend>
    <div>
      <input type="radio" id="contactChoice1" name="contact" value="email" />
      <label for="contactChoice1">Email</label>
      <input type="radio" id="contactChoice2" name="contact" value="phone" />
      <label for="contactChoice2">Phone</label>
      <input type="radio" id="contactChoice3" name="contact" value="mail" />
      <label for="contactChoice3">Mail</label>
    </div>
    <div>
      <button type="submit">Submit</button>
    </div>
  </fieldset>
</form>
<pre id="log"></pre>
```

Then we add some JavaScript to set up an event listener on the `submit` event, which is sent when the user clicks the "Submit" button:

```js
const form = document.querySelector("form");
const log = document.querySelector("#log");

form.addEventListener(
  "submit",
  (event) => {
    const data = new FormData(form);
    let output = "";
    for (const entry of data) {
      output = `${output}${entry[0]}=${entry[1]}\r`;
    }
    log.innerText = output;
    event.preventDefault();
  },
  false,
);
```

Try this example out and see how there's never more than one result for the `contact` group.

Additional attributes
---------------------

In addition to the common attributes shared by all `<input>` elements, `radio` inputs support the following attributes.

`checked`

A Boolean attribute which, if present, indicates that this radio button is the default selected one in the group.

Unlike other browsers, Firefox by default persists the dynamic checked state of an `<input>` across page loads. Use the `autocomplete` attribute to control this feature.

`value`

The `value` attribute is one which all `<input>`s share; however, it serves a special purpose for inputs of type `radio`: when a form is submitted, only radio buttons which are currently checked are submitted to the server, and the reported value is the value of the `value` attribute. If the `value` is not otherwise specified, it is the string `on` by default. This is demonstrated in the section Value above.

`required`

The `required` attribute is one which most `<input>`s share. If any radio button in a same-named group of radio buttons has the `required` attribute, a radio button in that group must be checked, although it doesn't have to be the one with the attribute applied.

Using radio inputs
------------------

We already covered the fundamentals of radio buttons above. Let's now look at the other common radio-button-related features and techniques you may need to know about.

### Selecting a radio button by default

To make a radio button selected by default, you include `checked` attribute, as shown in this revised version of the previous example:

```html
<form>
  <fieldset>
    <legend>Please select your preferred contact method:</legend>
    <div>
      <input
 type="radio"
 id="contactChoice1"
 name="contact"
 value="email"
 checked />
      <label for="contactChoice1">Email</label>

      <input type="radio" id="contactChoice2" name="contact" value="phone" />
      <label for="contactChoice2">Phone</label>

      <input type="radio" id="contactChoice3" name="contact" value="mail" />
      <label for="contactChoice3">Mail</label>
    </div>
    <div>
      <button type="submit">Submit</button>
    </div>
  </fieldset>
</form>
```

In this case, the first radio button is now selected by default.

**Note:** If you put the `checked` attribute on more than one radio button, later instances will override earlier ones; that is, the last `checked` radio button will be the one that is selected. This is because only one radio button in a group can ever be selected at once, and the user agent automatically deselects others each time a new one is marked as checked.

### Providing a bigger hit area for your radio buttons

In the above examples, you may have noticed that you can select a radio button by clicking on its associated `<label>` element, as well as on the radio button itself. This is a really useful feature of HTML form labels that makes it easier for users to click the option they want, especially on small-screen devices like smartphones.

Beyond accessibility, this is another good reason to properly set up `<label>` elements on your forms.

Validation
----------

Radio buttons don't participate in constraint validation; they have no real value to be constrained.

Styling radio inputs
--------------------

The following example shows a slightly more thorough version of the example we've seen throughout the article, with some additional styling, and with better semantics established through use of specialized elements. The HTML looks like this:

```html
<form>
  <fieldset>
    <legend>Please select your preferred contact method:</legend>
    <div>
      <input
 type="radio"
 id="contactChoice1"
 name="contact"
 value="email"
 checked />
      <label for="contactChoice1">Email</label>

      <input type="radio" id="contactChoice2" name="contact" value="phone" />
      <label for="contactChoice2">Phone</label>

      <input type="radio" id="contactChoice3" name="contact" value="mail" />
      <label for="contactChoice3">Mail</label>
    </div>
    <div>
      <button type="submit">Submit</button>
    </div>
  </fieldset>
</form>
```

The CSS involved in this example is a bit more significant:

```css
html {
  font-family: sans-serif;
}

div:first-of-type {
  display: flex;
  align-items: flex-start;
  margin-bottom: 5px;
}

label {
  margin-right: 15px;
  line-height: 32px;
}

input {
  appearance: none;

  border-radius: 50%;
  width: 16px;
  height: 16px;

  border: 2px solid #999;
  transition: 0.2s all linear;
  margin-right: 5px;

  position: relative;
  top: 4px;
}

input:checked {
  border: 6px solid black;
}

button,
legend {
  color: white;
  background-color: black;
  padding: 5px 10px;
  border-radius: 0;
  border: 0;
  font-size: 14px;
}

button:hover,
button:focus {
  color: #999;
}

button:active {
  background-color: white;
  color: black;
  outline: 1px solid black;
}
```

Most notable here is the use of the `appearance` property (with prefixes needed to support some browsers). By default, radio buttons (and checkboxes) are styled with the operating system's native styles for those controls. By specifying `appearance: none`, you can remove the native styling altogether, and create your own styles for them. Here we've used a `border` along with `border-radius` and a `transition` to create a nice animating radio selection. Notice also how the `:checked` pseudo-class is used to specify the styles for the radio button's appearance when selected.

**Note:** If you wish to use the `appearance` property, you should test it very carefully. Although it is supported in most modern browsers, its implementation varies widely. In older browsers, even the keyword `none` does not have the same effect across different browsers, and some do not support it at all. The differences are smaller in the newest browsers.

Notice that when clicking on a radio button, there's a nice, smooth fade out/in effect as the two buttons change state. In addition, the style and coloring of the legend and submit button are customized to have strong contrast. This might not be a look you'd want in a real web application, but it definitely shows off the possibilities.

Technical summary
-----------------

|  |  |
| --- | --- |
| **Value** |
 A string representing the value of the radio
 button.
  |
| **Events** | `change` and `input` |
| **Supported common attributes** | `checked`, `value` and
 `required` |
| **IDL attributes** | `checked` and `value` |
| **DOM interface** | `HTMLInputElement` |
| **Methods** | `select()` |
| **Implicit ARIA Role** | `radio` |

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

| Specification |
| --- |
| HTML Standard # radio-button-state-(type=radio) |

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

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

See also
--------

* `<input>` and the `HTMLInputElement` interface that implements it.
* `RadioNodeList`: the interface that describes a list of radio buttons
* Compatibility of CSS properties


<input type="file"> - HTML: HyperText Markup Language

<input type="file">
===================

`<input>` elements with **`type="file"`** let the user choose one or more files from their device storage. Once chosen, the files can be uploaded to a server using form submission, or manipulated using JavaScript code and the File API.

Try it
------

Value
-----

A file input's `value` attribute contains a string that represents the path to the selected file(s). If no file is selected yet, the value is an empty string (`""`). When the user selected multiple files, the `value` represents the first file in the list of files they selected. The other files can be identified using the input's `HTMLInputElement.files` property.

**Note:** The value is always the file's name prefixed with `C:\fakepath\`, which isn't the real path of the file. This is to prevent malicious software from guessing the user's file structure.

Additional attributes
---------------------

In addition to the common attributes shared by all `<input>` elements, inputs of type `file` also support the following attributes.

### accept

The `accept` attribute value is a string that defines the file types the file input should accept. This string is a comma-separated list of **unique file type specifiers**. Because a given file type may be identified in more than one manner, it's useful to provide a thorough set of type specifiers when you need files of a given format.

For instance, there are a number of ways Microsoft Word files can be identified, so a site that accepts Word files might use an `<input>` like this:

```html
<input
 type="file"
 id="docpicker"
 accept=".doc,.docx,.xml,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document" />
```

### capture

The `capture` attribute value is a string that specifies which camera to use for capture of image or video data, if the `accept` attribute indicates that the input should be of one of those types. A value of `user` indicates that the user-facing camera and/or microphone should be used. A value of `environment` specifies that the outward-facing camera and/or microphone should be used. If this attribute is missing, the user agent is free to decide on its own what to do. If the requested facing mode isn't available, the user agent may fall back to its preferred default mode.

**Note:** `capture` was previously a Boolean attribute which, if present, requested that the device's media capture device(s) such as camera or microphone be used instead of requesting a file input.

### multiple

When the `multiple` Boolean attribute is specified, the file input allows the user to select more than one file.

Non-standard attributes
-----------------------

In addition to the attributes listed above, the following non-standard attributes are available on some browsers. You should try to avoid using them when possible, since doing so will limit the ability of your code to function in browsers that don't implement them.

### `webkitdirectory`

The Boolean `webkitdirectory` attribute, if present, indicates that only directories should be available to be selected by the user in the file picker interface. See `HTMLInputElement.webkitdirectory` for additional details and examples.

Though originally implemented only for WebKit-based browsers, `webkitdirectory` is also usable in Microsoft Edge as well as Firefox 50 and later. However, even though it has relatively broad support, it is still not standard and should not be used unless you have no alternative.

Unique file type specifiers
---------------------------

A **unique file type specifier** is a string that describes a type of file that may be selected by the user in an `<input>` element of type `file`. Each unique file type specifier may take one of the following forms:

* A valid case-insensitive filename extension, starting with a period (".") character. For example: `.jpg`, `.pdf`, or `.doc`.
* A valid MIME type string, with no extensions.
* The string `audio/*` meaning "any audio file".
* The string `video/*` meaning "any video file".
* The string `image/*` meaning "any image file".

The `accept` attribute takes a string containing one or more of these unique file type specifiers as its value, separated by commas. For example, a file picker that needs content that can be presented as an image, including both standard image formats and PDF files, might look like this:

```html
<input type="file" accept="image/\*,.pdf" />
```

Using file inputs
-----------------

### A basic example

```html
<form method="post" enctype="multipart/form-data">
  <div>
    <label for="file">Choose file to upload</label>
    <input type="file" id="file" name="file" multiple />
  </div>
  <div>
    <button>Submit</button>
  </div>
</form>
```

```
div {
  margin-bottom: 10px;
}
```

This produces the following output:

**Note:** You can find this example on GitHub too — see the source code, and also see it running live.

Regardless of the user's device or operating system, the file input provides a button that opens up a file picker dialog that allows the user to choose a file.

Including the `multiple` attribute, as shown above, specifies that multiple files can be chosen at once. The user can choose multiple files from the file picker in any way that their chosen platform allows (e.g. by holding down `Shift` or `Control` and then clicking). If you only want the user to choose a single file per `<input>`, omit the `multiple` attribute.

### Getting information on selected files

The selected files' are returned by the element's `HTMLInputElement.files` property, which is a `FileList` object containing a list of `File` objects. The `FileList` behaves like an array, so you can check its `length` property to get the number of selected files.

Each `File` object contains the following information:

`name`

The file's name.

`lastModified`

A number specifying the date and time at which the file was last modified, in milliseconds since the UNIX epoch (January 1, 1970, at midnight).

`lastModifiedDate`
Deprecated

A `Date` object representing the date and time at which the file was last modified. *This is deprecated and should not be used. Use `lastModified` instead.*

`size`

The size of the file in bytes.

`type`

The file's MIME type.

`webkitRelativePath`
Non-standard

A string specifying the file's path relative to the base directory selected in a directory picker (that is, a `file` picker in which the `webkitdirectory` attribute is set). *This is non-standard and should be used with caution.*

**Note:** You can set as well as get the value of `HTMLInputElement.files` in all modern browsers; this was most recently added to Firefox, in version 57 (see Firefox bug 1384030).

### Limiting accepted file types

Often you won't want the user to be able to pick any arbitrary type of file; instead, you often want them to select files of a specific type or types. For example, if your file input lets users upload a profile picture, you probably want them to select web-compatible image formats, such as JPEG or PNG.

Acceptable file types can be specified with the `accept` attribute, which takes a comma-separated list of allowed file extensions or MIME types. Some examples:

* `accept="image/png"` or `accept=".png"` — Accepts PNG files.
* `accept="image/png, image/jpeg"` or `accept=".png, .jpg, .jpeg"` — Accept PNG or JPEG files.
* `accept="image/*"` — Accept any file with an `image/*` MIME type. (Many mobile devices also let the user take a picture with the camera when this is used.)
* `accept=".doc,.docx,.xml,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document"` — accept anything that smells like an MS Word document.

Let's look at a more complete example:

```html
<form method="post" enctype="multipart/form-data">
  <div>
    <label for="profile\_pic">Choose file to upload</label>
    <input
 type="file"
 id="profile\_pic"
 name="profile\_pic"
 accept=".jpg, .jpeg, .png" />
  </div>
  <div>
    <button>Submit</button>
  </div>
</form>
```

```
div {
  margin-bottom: 10px;
}
```

This produces a similar-looking output to the previous example:

**Note:** You can find this example on GitHub too — see the source code, and also see it running live.

It may look similar, but if you try selecting a file with this input, you'll see that the file picker only lets you select the file types specified in the `accept` value (the exact interface differs across browsers and operating systems).

The `accept` attribute doesn't validate the types of the selected files; it provides hints for browsers to guide users towards selecting the correct file types. It is still possible (in most cases) for users to toggle an option in the file chooser that makes it possible to override this and select any file they wish, and then choose incorrect file types.

Because of this, you should make sure that the `accept` attribute is backed up by appropriate server-side validation.

### Detecting cancellations

The `cancel` event is fired when the user does not change their selection, reselecting the previously selected files. The `cancel` event is also fired when the file picker dialog gets closed, or canceled, via the "cancel" button or the `escape` key.

For example, the following code will log to the console if the user closes the popup without selecting a file:

```js
const elem = document.createElement("input");
elem.type = "file";
elem.addEventListener("cancel", () => {
  console.log("Cancelled.");
});
elem.addEventListener("change", () => {
  if (elem.files.length == 1) {
    console.log("File selected: ", elem.files[0]);
  }
});
elem.click();
```

### Notes

1. You cannot set the value of a file picker from a script — doing something like the following has no effect:

```js
const input = document.querySelector("input[type=file]");
input.value = "foo";
```

2. When a file is chosen using an `<input type="file">`, the real path to the source file is not shown in the input's `value` attribute for obvious security reasons. Instead, the filename is shown, with `C:\fakepath\` prepended to it. There are some historical reasons for this quirk, but it is supported across all modern browsers, and in fact is defined in the spec.
Examples
--------

In this example, we'll present a slightly more advanced file chooser that takes advantage of the file information available in the `HTMLInputElement.files` property, as well as showing off a few clever tricks.

**Note:** You can see the complete source code for this example on GitHub — file-example.html (see it live also). We won't explain the CSS; the JavaScript is the main focus.

First of all, let's look at the HTML:

```html
<form method="post" enctype="multipart/form-data">
  <div>
    <label for="image\_uploads">Choose images to upload (PNG, JPG)</label>
    <input
 type="file"
 id="image\_uploads"
 name="image\_uploads"
 accept=".jpg, .jpeg, .png"
 multiple />
  </div>
  <div class="preview">
    <p>No files currently selected for upload</p>
  </div>
  <div>
    <button>Submit</button>
  </div>
</form>
```

```
html {
  font-family: sans-serif;
}

form {
  background: #ccc;
  margin: 0 auto;
  padding: 20px;
  border: 1px solid black;
}

form ol {
  padding-left: 0;
}

form li,
div > p {
  background: #eee;
  display: flex;
  justify-content: space-between;
  margin-bottom: 10px;
  list-style-type: none;
  border: 1px solid black;
}

form img {
  height: 64px;
  order: 1;
}

form p {
  line-height: 32px;
  padding-left: 10px;
}

form label,
form button {
  background-color: #7f9ccb;
  padding: 5px 10px;
  border-radius: 5px;
  border: 1px ridge black;
  font-size: 0.8rem;
  height: auto;
}

form label:hover,
form button:hover {
  background-color: #2d5ba3;
  color: white;
}

form label:active,
form button:active {
  background-color: #0d3f8f;
  color: white;
}
```

This is similar to what we've seen before — nothing special to comment on.

Next, let's walk through the JavaScript.

In the first lines of script, we get references to the form input itself, and the `<div>` element with the class of `.preview`. Next, we hide the `<input>` element — we do this because file inputs tend to be ugly, difficult to style, and inconsistent in their design across browsers. You can activate the `input` element by clicking its `<label>`, so it is better to visually hide the `input` and style the label like a button, so the user will know to interact with it if they want to upload files.

```js
const input = document.querySelector("input");
const preview = document.querySelector(".preview");

input.style.opacity = 0;
```

**Note:** `opacity` is used to hide the file input instead of `visibility: hidden` or `display: none`, because assistive technology interprets the latter two styles to mean the file input isn't interactive.

Next, we add an event listener to the input to listen for changes to its selected value (in this case, when files are selected). The event listener invokes our custom `updateImageDisplay()` function.

```js
input.addEventListener("change", updateImageDisplay);
```

Whenever the `updateImageDisplay()` function is invoked, we:

* Use a `while` loop to empty the previous contents of the preview `<div>`.
* Grab the `FileList` object that contains the information on all the selected files, and store it in a variable called `curFiles`.
* Check to see if no files were selected, by checking if `curFiles.length` is equal to 0. If so, print a message into the preview `<div>` stating that no files have been selected.
* If files *have* been selected, we loop through each one, printing information about it into the preview `<div>`. Things to note here:
* We use the custom `validFileType()` function to check whether the file is of the correct type (e.g. the image types specified in the `accept` attribute).
* If it is, we:
    + Print out its name and file size into a list item inside the previous `<div>` (obtained from `file.name` and `file.size`). The custom `returnFileSize()` function returns a nicely-formatted version of the size in bytes/KB/MB (by default the browser reports the size in absolute bytes).
    + Generate a thumbnail preview of the image by calling `URL.createObjectURL(file)`. Then, insert the image into the list item too by creating a new `<img>` and setting its `src` to the thumbnail.
* If the file type is invalid, we display a message inside a list item telling the user that they need to select a different file type.

```js
function updateImageDisplay() {
  while (preview.firstChild) {
    preview.removeChild(preview.firstChild);
  }

  const curFiles = input.files;
  if (curFiles.length === 0) {
    const para = document.createElement("p");
    para.textContent = "No files currently selected for upload";
    preview.appendChild(para);
  } else {
    const list = document.createElement("ol");
    preview.appendChild(list);

    for (const file of curFiles) {
      const listItem = document.createElement("li");
      const para = document.createElement("p");
      if (validFileType(file)) {
        para.textContent = `File name ${file.name}, file size ${returnFileSize(
 file.size,
 )}.`;
        const image = document.createElement("img");
        image.src = URL.createObjectURL(file);
        image.alt = image.title = file.name;

        listItem.appendChild(image);
        listItem.appendChild(para);
      } else {
        para.textContent = `File name ${file.name}: Not a valid file type. Update your selection.`;
        listItem.appendChild(para);
      }

      list.appendChild(listItem);
    }
  }
}
```

The custom `validFileType()` function takes a `File` object as a parameter, then uses `Array.prototype.includes()` to check if any value in the `fileTypes` matches the file's `type` property. If a match is found, the function returns `true`. If no match is found, it returns `false`.

```js
// https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image\_types
const fileTypes = [
  "image/apng",
  "image/bmp",
  "image/gif",
  "image/jpeg",
  "image/pjpeg",
  "image/png",
  "image/svg+xml",
  "image/tiff",
  "image/webp",
  "image/x-icon",
];

function validFileType(file) {
  return fileTypes.includes(file.type);
}
```

The `returnFileSize()` function takes a number (of bytes, taken from the current file's `size` property), and turns it into a nicely formatted size in bytes/KB/MB.

```js
function returnFileSize(number) {
  if (number < 1024) {
    return `${number} bytes`;
  } else if (number >= 1024 && number < 1048576) {
    return `${(number / 1024).toFixed(1)} KB`;
  } else if (number >= 1048576) {
    return `${(number / 1048576).toFixed(1)} MB`;
  }
}
```

```
const button = document.querySelector("form button");
button.addEventListener("click", (e) => {
  e.preventDefault();
  const para = document.createElement("p");
  para.append("Image uploaded!");
  preview.replaceChildren(para);
});
```

The example looks like this; have a play:

Technical summary
-----------------

|  |  |
| --- | --- |
| **Value** |
 A string representing the path to the selected
 file.
  |
| **Events** | `change`,
 `input` and
 `cancel` |
| **Supported common attributes** | `required` |
| **Additional Attributes** | `accept`,
 `capture`,
 `multiple` |
| **IDL attributes** | `files` and `value` |
| **DOM interface** | `HTMLInputElement` |
| **Methods** | `select()` |
| **Implicit ARIA Role** | `no corresponding role` |

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

| Specification |
| --- |
| HTML Standard # file-upload-state-(type=file) |

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

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

See also
--------

* Using files from web applications — contains a number of other useful examples related to `<input type="file">` and the File API.
* Compatibility of CSS properties


<input type="range"> - HTML: HyperText Markup Language

<input type="range">
====================

`<input>` elements of type **`range`** let the user specify a numeric value which must be no less than a given value, and no more than another given value. The precise value, however, is not considered important. This is typically represented using a slider or dial control rather than a text entry box like the number input type.

Because this kind of widget is imprecise, it should only be used if the control's exact value isn't important.

Try it
------

If the user's browser doesn't support type `range`, it will fall back and treat it as a `text` input.

### Validation

There is no pattern validation available; however, the following forms of automatic validation are performed:

* If the `value` is set to something which can't be converted into a valid floating-point number, validation fails because the input is suffering from a bad input.
* The value won't be less than `min`. The default is 0.
* The value won't be greater than `max`. The default is 100.
* The value will be a multiple of `step`. The default is 1.
### Value

The `value` attribute contains a string which contains a string representation of the selected number. The value is never an empty string (`""`). The default value is halfway between the specified minimum and maximum—unless the maximum is actually less than the minimum, in which case the default is set to the value of the `min` attribute. The algorithm for determining the default value is:

```js
defaultValue =
  rangeElem.max < rangeElem.min
    ? rangeElem.min
    : rangeElem.min + (rangeElem.max - rangeElem.min) / 2;
```

If an attempt is made to set the value lower than the minimum, it is set to the minimum. Similarly, an attempt to set the value higher than the maximum results in it being set to the maximum.

Additional attributes
---------------------

In addition to the attributes shared by all `<input>` elements, range inputs offer the following attributes.

### list

The value of the `list` attribute is the `id` of a `<datalist>` element located in the same document. The `<datalist>` provides a list of predefined values to suggest to the user for this input. Any values in the list that are not compatible with the `type` are not included in the suggested options. The values provided are suggestions, not requirements: users can select from this predefined list or provide a different value.

See the adding tick marks below for an example of how the options on a range are denoted in supported browsers.

### max

The greatest value in the range of permitted values. If the `value` entered into the element exceeds this, the element fails constraint validation. If the value of the `max` attribute isn't a number, then the element has no maximum value.

This value must be greater than or equal to the value of the `min` attribute. See the HTML `max` attribute.

### min

The lowest value in the range of permitted values. If the `value` of the element is less than this, the element fails constraint validation. If a value is specified for `min` that isn't a valid number, the input has no minimum value.

This value must be less than or equal to the value of the `max` attribute. See the HTML `min` attribute.

**Note:** If the `min` and `max` values are equal or the `max` value is lower than the `min` value the user will not be able to interact with the range.

### step

The `step` attribute is a number that specifies the granularity that the value must adhere to. Only values that match the specified stepping interval (`min` if specified, `value` otherwise, or an appropriate default value if neither of those is provided) are valid.

The `step` attribute can also be set to the `any` string value. This `step` value means that no stepping interval is implied and any value is allowed in the specified range (barring other constraints, such as `min` and `max`). See the Setting step to the `any` value example for how this works in supported browsers.

**Note:** When the value entered by a user doesn't adhere to the stepping configuration, the user agent may round off the value to the nearest valid value, preferring to round numbers up when there are two equally close options.

The default stepping value for `range` inputs is 1, allowing only integers to be entered, *unless* the stepping base is not an integer; for example, if you set `min` to -10 and `value` to 1.5, then a `step` of 1 will allow only values such as 1.5, 2.5, 3.5,… in the positive direction and -0.5, -1.5, -2.5,… in the negative direction. See the HTML `step` attribute.

Non-standard Attributes
-----------------------

### orient

Similar to the -moz-orient non-standard CSS property impacting the `<progress>` and `<meter>` elements, the `orient` attribute defines the orientation of the range slider. Values include `horizontal`, meaning the range is rendered horizontally, and `vertical`, where the range is rendered vertically.

**Note:** The following input attributes do not apply to the input range: `accept`, `alt`, `checked`, `dirname`, `formaction`, `formenctype`, `formmethod`, `formnovalidate`, `formtarget`, `height`, `maxlength`, `minlength`, `multiple`, `pattern`, `placeholder`, `readonly`, `required`, `size`, and `src`. Any of these attributes, if included, will be ignored.

Examples
--------

While the `number` type lets users enter a number with optional constraints forcing their value to be between a minimum and a maximum value, it does require that they enter a specific value. The `range` input type lets you ask the user for a value in cases where the user may not even care—or know—what the specific numeric value selected is.

A few examples of situations in which range inputs are commonly used:

* Audio controls such as volume and balance, or filter controls.
* Color configuration controls such as color channels, transparency, brightness, etc.
* Game configuration controls such as difficulty, visibility distance, world size, and so forth.
* Password length for a password manager's generated passwords.

As a rule, if the user is more likely to be interested in the percentage of the distance between minimum and maximum values than the actual number itself, a range input is a great candidate. For example, in the case of a home stereo volume control, users typically think "set volume at halfway to maximum" instead of "set volume to 0.5".

### Specifying the minimum and maximum

By default, the minimum is 0 and the maximum is 100. If that's not what you want, you can easily specify different bounds by changing the values of the `min` and/or `max` attributes. These can be any floating-point value.

For example, to ask the user for a value between -10 and 10, you can use:

```html
<input type="range" min="-10" max="10" />
```

### Setting the value's granularity

By default, the granularity is 1, meaning the value is always an integer. To control the granularity, you can change the `step` attribute. For example, If you need a value to be halfway between 5 and 10, you should set the value of `step` to 0.5:

#### Setting the step attribute

```html
<input type="range" min="5" max="10" step="0.5" />
```

#### Setting step to `any`

If you want to accept any value regardless of how many decimal places it extends to, you can specify a value of `any` for the `step` attribute:

##### HTML

```html
<input id="pi\_input" type="range" min="0" max="3.14" step="any" />
<p>Value: <output id="value"></output></p>
```

##### JavaScript

```js
const value = document.querySelector("#value");
const input = document.querySelector("#pi\_input");
value.textContent = input.value;
input.addEventListener("input", (event) => {
  value.textContent = event.target.value;
});
```

This example lets the user select any value between 0 and π without any restriction on the fractional part of the value selected. JavaScript is used to show how the value changes as the user interacts with the range.

### Adding tick marks

To add tick marks to a range control, include the `list` attribute, giving it the `id` of a `<datalist>` element which defines a series of tick marks on the control. Each point is represented using an `<option>` element with its `value` set to the range's value at which a mark should be drawn.

#### HTML

```html
<label for="temp">Choose a comfortable temperature:</label><br />
<input type="range" id="temp" name="temp" list="markers" />

<datalist id="markers">
  <option value="0"></option>
  <option value="25"></option>
  <option value="50"></option>
  <option value="75"></option>
  <option value="100"></option>
</datalist>
```

#### Result

### Using the same datalist for multiple range controls

To help you from repeating code you can reuse that same `<datalist>` for multiple `<input type="range">` elements, and other `<input>` types.

**Note:** If you also want to show the labels as in the example below then you would need a `datalist` for each range input.

#### HTML

```html
<p>
  <label for="temp1">Temperature for room 1:</label>
  <input type="range" id="temp1" name="temp1" list="values" />
</p>
<p>
  <label for="temp2">Temperature for room 2:</label>
  <input type="range" id="temp2" name="temp2" list="values" />
</p>

<p>
  <label for="temp3">Temperature for room 3:</label>
  <input type="range" id="temp3" name="temp3" list="values" />
</p>

<datalist id="values">
  <option value="0" label="0"></option>
  <option value="25" label="25"></option>
  <option value="50" label="50"></option>
  <option value="75" label="75"></option>
  <option value="100" label="100"></option>
</datalist>
```

#### Result

### Adding labels

You can label tick marks by giving the `<option>` elements `label` attributes. However, the label content will not be displayed by default. You can use CSS to show the labels and to position them correctly. Here's one way you could do this.

#### HTML

```html
<label for="tempB">Choose a comfortable temperature:</label><br />
<input type="range" id="tempB" name="temp" list="values" />

<datalist id="values">
  <option value="0" label="very cold!"></option>
  <option value="25" label="cool"></option>
  <option value="50" label="medium"></option>
  <option value="75" label="getting warm!"></option>
  <option value="100" label="hot!"></option>
</datalist>
```

#### CSS

```css
datalist {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  writing-mode: vertical-lr;
  width: 200px;
}

option {
  padding: 0;
}

input[type="range"] {
  width: 200px;
  margin: 0;
}
```

#### Result

### Creating vertical range controls

By default, browsers render range inputs as sliders with the knob sliding left and right.

To create a vertical range, wherein the knob slides up and down, set the CSS `appearance` property to `slider-vertical` and include the non-standard `orient` attribute for Firefox.

#### Horizontal range control

Consider this range control:

```html
<input type="range" id="volume" min="0" max="11" value="7" step="1" />
```

This control is horizontal (at least on most if not all major browsers; others might vary).

#### Using the appearance property

The `appearance` property has a non-standard value of `slider-vertical` that, well, makes sliders vertical.

We use the same HTML as in the previous examples:

```html
<input type="range" min="0" max="11" value="7" step="1" />
```

We target just the inputs with a type of range:

```css
input[type="range"] {
  appearance: slider-vertical;
}
```

#### Using the orient attribute

In Firefox only, there is a non-standard `orient` property.

Use similar HTML as in the previous examples, we add the attribute with a value of `vertical`:

```html
<input type="range" min="0" max="11" value="7" step="1" orient="vertical" />
```

#### writing-mode: bt-lr

The `writing-mode` property should generally not be used to alter text direction for internationalization or localization purposes, but can be used for special effects.

We use the same HTML as in the previous examples:

```html
<input type="range" min="0" max="11" value="7" step="1" />
```

We target just the inputs with a type of range, changing the writing mode from the default to `bt-lr`, or bottom-to-top and left-to-right:

```css
input[type="range"] {
  writing-mode: bt-lr;
}
```

#### Putting it all together

As each of the above examples works in different browsers, you can put all of them in a single example to make it work cross browser:

We keep the `orient` attribute with a value of `vertical` for Firefox:

```html
<input type="range" min="0" max="11" value="7" step="1" orient="vertical" />
```

We target just the `input`s with a `type` of `range` and `orient` set to `vertical`, changing the `writing-mode` from the default to `bt-lr`, or bottom-to-top and left-to-right, for pre-Blink versions of Edge, and add `appearance: slider-vertical` which is supported in Blink and Webkit browsers:

```css
input[type="range"][orient="vertical"] {
  writing-mode: bt-lr;
  appearance: slider-vertical;
}
```

Technical summary
-----------------

|  |  |
| --- | --- |
| **Value** |
 A string containing the string representation
 of the selected numeric value; use
 `valueAsNumber`
 to get the value as a number.
  |
| **Events** | `change` and
 `input` |
| **Supported common attributes** | `autocomplete`,
 `list`,
 `max`,
 `min`, and
 `step` |
| **IDL attributes** | `list`, `value`, and `valueAsNumber` |
| **DOM interface** | `HTMLInputElement` |
| **Methods** | `stepDown()`
 and `stepUp()` |
| **Implicit ARIA Role** | `slider` |

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

| Specification |
| --- |
| HTML Standard # range-state-(type=range) |

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

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

See also
--------

* HTML Forms
* `<input>` and the `HTMLInputElement` interface it's based upon
* `<input type="number">`
* `validityState.rangeOverflow` and `validityState.rangeUnderflow`
* Controlling multiple parameters with ConstantSourceNode
* Styling the range element
* Compatibility of CSS properties


manifest - HTML: HyperText Markup Language

manifest
========

**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 **`manifest`** attribute of the `<html>` element specifies a URL of an application cache manifest that is downloaded in the early stages of page load.

**Note:** manifest-based caching mechanism has been deprecated. Use service workers instead.

The `manifest` attribute only had an effect during early stages of page load, thus changing it via regular DOM interfaces had no effect. The deprecated `Window.applicationCache` interface was used instead. The attribute functionality has been superceded by the web app manifest, an external JSON file associated with the HTML file through a `<link>` with `rel="manifest"`.

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

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

See also
--------

* Service Worker API
* `manifest.json`
* Web app manifests
* Making PWAs installable


<script>: type attribute - HTML: HyperText Markup Language

<script>: type attribute
========================

The **`type`** attribute of the `<script>` element indicates the *type* of script represented by the element: a classic script, an import map, a JavaScript module, speculation rules, or a data block.

Value
-----

The value of this attribute indicates the type of data represented by the script, and will be one of the following:

**Attribute is not set (default), an empty string, or a JavaScript MIME type**

 Indicates that the script is a "classic script", containing JavaScript code.
 Authors are encouraged to omit the attribute if the script refers to JavaScript code rather than specify a MIME type.
 JavaScript MIME types are listed in the IANA media types specification.

`importmap`

 This value indicates that the body of the element contains an import map.
 The import map is a JSON object that developers can use to control how the browser resolves module specifiers when importing JavaScript modules.

`module`

 This value causes the code to be treated as a JavaScript module.
 The processing of the script contents is deferred.
 The `charset` and `defer` attributes have no effect.
 For information on using `module`, see our JavaScript modules guide.
 Unlike classic scripts, module scripts require the use of the CORS protocol for cross-origin fetching.

`speculationrules`
Experimental

 This value indicates that the body of the element contains speculation rules.
 Speculation rules take the form of a JSON object that determine what resources should be prefetched or prerendered by the browser. This is part of the Speculation Rules API.

**Any other value**

 The embedded content is treated as a data block, and won't be processed by the browser.
 Developers must use a valid MIME type that is not a JavaScript MIME type to denote data blocks.
 All of the other attributes will be ignored, including the `src` attribute.

**Note:** In earlier browsers, the type identified the scripting language of the embedded or imported (via the `src` attribute) code.

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

#### No specification found

No specification data found for `html.elements.script.type`.
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.


<script type="speculationrules"> - HTML: HyperText Markup Language

<script type="speculationrules">
================================

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

The **`speculationrules`** value of the `type` attribute of the `<script>` element indicates that the body of the element contains speculation rules.

Speculation rules take the form of a JSON structure that determine what resources should be prefetched or prerendered by the browser. This is part of the Speculation Rules API.

Syntax
------

```html
<script type="speculationrules">
 // JSON object defining rules
</script>
```

**Note:** The `src`, `async`, `nomodule`, `defer`, `crossorigin`, `integrity`, and `referrerpolicy` attributes must not be specified.

### Exceptions

`TypeError`

The speculation rules definition is not a valid JSON object.

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

A `<script type="speculationrules">` element must contain a valid JSON structure that defines speculation rules. The following examples show separate prefetch and prerender rules:

```html
<script type="speculationrules">
 {
 "prefetch": [
 {
 "source": "list",
 "urls": ["next.html", "next2.html"],
 "requires": ["anonymous-client-ip-when-cross-origin"],
 "referrer\_policy": "no-referrer"
 }
 ]
 }
</script>
```

```html
<script type="speculationrules">
 {
 "prerender": [
 {
 "source": "list",
 "urls": ["next3.html", "next4.html"]
 }
 ]
 }
</script>
```

### Speculation rules JSON representation

The JSON structure contains one or more fields at the top level, each one representing an action to define speculation rules for. At present the supported actions are:

`"prefetch"` Optional
Experimental

Rules for potential future navigations that should have their associated document response body downloaded, leading to significant performance improvements when those documents are navigated to. Note that none of the subresources referenced by the page are downloaded.

`"prerender"` Optional
Experimental

Rules for potential future navigations that should have their associated documents fully downloaded, rendered, and loaded into an invisible tab. This includes loading all subresources, running all JavaScript, and even loading subresources and performing data fetches started by JavaScript. When those documents are navigated to, navigations will be instant, leading to major performance improvements.

**Note:** Consult the Speculation Rules API main page for full details on how to use prefetch and prerender effectively.

Each action field contains an array, which in turn contains one or more objects. Each object contains a single rule defining a set of URLs and related parameters.

Specifically, each object can contain the following properties:

`"source"`

A string representing the source of the URLs to which the rule applies. Possible values are:

`"list"`

Denotes that the URLs will come from a specific list.

`"urls"`

An array of strings representing the list of URLs to apply the rule to. These can be absolute or relative URLs. Relative URLs will be parsed relative to the document base URL (if inline in a document) or relative to the external resource URL (if externally fetched).

`"requires"` Optional
Experimental

An array of strings representing capabilities of the browser parsing the rule, which must be available if the rule is to be applied to the specified URLs.

**Warning:** Prefetches will automatically fail in browsers that cannot meet a specified requirement, even if they support the Speculation Rules API.

Possible values are:

`"anonymous-client-ip-when-cross-origin"`

`"prefetch"`-only. Specifies that the rule matches only if the user agent can prevent the client IP address from being visible to the origin server if a cross-origin prefetch request is issued. Exactly how this works is dependent on browser implementation specifics. For example:

* Chrome's implementation hides the IP address using a Google-owned proxy, therefore by default it only works for Google-controlled referrers (since in that case, sending the URLs of the destination to Google is not an additional privacy leak). When used on a non-Google-owned site, rules that include this will only match for users that turn on "Enhanced preloading" in `chrome://settings/preloading`.
* Other Chromium-based browsers will have to provide their own solutions. Thorough testing in all target browsers is advised.
* A future Safari implementation may possibly use something along the lines of iCloud Private Relay.
* A future Firefox implementation might use something based on the Mozilla VPN product.

`"referrer_policy"` Optional
Experimental

A string representing a specific referrer policy string to use when requesting the URLs specified in the rule — see `Referrer-Policy` for possible values. The purpose of this is to allow the referring page to set a stricter policy specifically for the speculative request than the policy the page already has set (either by default, or by using `Referrer-Policy`). A laxer policy set in the speculation rules will not override a stricter policy set on the referring page.

**Note:** As speculation rules use a `<script>` element, they need to be explicitly allowed in the `Content-Security-Policy` `script-src` directive if the site includes it. This is done by adding the `"inline-speculation-rules"` value along with a hash- or nonce-source.

### Further examples

The earlier examples showed separate speculation rules defined for prefetch and prerender. It is possible to define both in a single set of rules:

```html
<script type="speculationrules">
 {
 "prefetch": [
 {
 "source": "list",
 "urls": ["next.html", "next2.html"],
 "requires": ["anonymous-client-ip-when-cross-origin"],
 "referrer\_policy": "no-referrer"
 }
 ],
 "prerender": [
 {
 "source": "list",
 "urls": ["next3.html", "next4.html"]
 }
 ]
 }
</script>
```

It is also allowable to include multiple sets of rules in a single HTML file:

```html
<script type="speculationrules">
 {
 "prefetch": [
 {
 "source": "list",
 "urls": ["next.html", "next2.html"],
 "requires": ["anonymous-client-ip-when-cross-origin"],
 "referrer\_policy": "no-referrer"
 }
 ]
 }
</script>
<script type="speculationrules">
 {
 "prerender": [
 {
 "source": "list",
 "urls": ["next3.html", "next4.html"]
 }
 ]
 }
</script>
```

And multiple rules in a single result set:

```js
<script type="speculationrules">
{
  "prerender": [
    {
      "source": "list",
      "urls": ["one.html"]
    },
    {
      "source": "list",
      "urls": ["two.html"]
    }
  ]
}
</script>
```

### Dynamic rule insertion

Below is an example that feature detects speculation rules and, if supported, dynamically adds a prerender speculation rule via JavaScript:

```js
if (
  HTMLScriptElement.supports &&
  HTMLScriptElement.supports("speculationrules")
) {
  const specScript = document.createElement("script");
  specScript.type = "speculationrules";
  const specRules = {
    prerender: [
      {
        source: "list",
        urls: ["/next.html"],
      },
    ],
  };
  specScript.textContent = JSON.stringify(specRules);
  console.log("added speculation rules to: next.html");
  document.body.append(specScript);
}
```

You can see this in action in this prerender demos page.

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

| Specification |
| --- |
| Speculation Rules # speculation-rules-script |

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

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

See also
--------

* Prerender pages in Chrome for instant page navigations on developer.chrome.com (2023)
* Speculative loading
* Speculation Rules API


<script type="importmap"> - HTML: HyperText Markup Language

<script type="importmap">
=========================

Baseline 2023
-------------

Newly availableSince March 2023, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.

* Learn more
* See full compatibility
* Report feedback
The **`importmap`** value of the `type` attribute of the `<script>` element indicates that the body of the element contains an import map.

 An import map is a JSON object that allows developers to control how the browser resolves module specifiers when importing JavaScript modules.
 It provides a mapping between the text used as the module specifier in an `import` statement or `import()` operator, and the corresponding value that will replace the text when resolving the specifier.
 The JSON object must conform to the Import map JSON representation format.

 An import map is used to resolve module specifiers in static and dynamic imports, and therefore must be declared and processed before any `<script>` elements that import modules using specifiers declared in the map.
 Note that the import map applies only to module specifiers in the `import` statement or `import()` operator for modules loaded into documents; it does not apply to the path specified in the `src` attribute of a `<script>` element or to modules loaded into workers or worklets.

For more information, see the Importing modules using import maps section in the JavaScript modules guide.

Syntax
------

```html
<script type="importmap">
 // JSON object defining import
</script>
```

The `src`, `async`, `nomodule`, `defer`, `crossorigin`, `integrity`, and `referrerpolicy` attributes must not be specified.

Only the first import map in the document with an inline definition is processed; any additional import maps and external import maps are ignored.

### Exceptions

`TypeError`

The import map definition is not a JSON object, the `importmap` key is defined but its value is not a JSON object, or the `scopes` key is defined but its value is not a JSON object.

Browsers generate console warnings for other cases where the import map JSON does not conform to the import map schema.

 An `error` event is fired at script elements with `type="importmap"` that are not processed.
 This might occur, for example, if module loading has already started when an import map is processed, or if multiple import maps are defined in the page.

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

 When importing a JavaScript module, both the `import` statement and `import()` operator have a "module specifier" that indicates the module to be imported.
 A browser must be able to resolve this specifier to an absolute URL in order to import the module.

For example, the following statements import elements from the module specifier `"./modules/shapes/square.js"`, which is a path relative to the base URL of the document, and the module specifier `"https://example.com/shapes/circle.js"`, which is an absolute URL.

```js
import { name as squareName, draw } from "./modules/shapes/square.js";
import { name as circleName } from "https://example.com/shapes/circle.js";
```

Import maps allow developers to specify (almost) any text they want in the module specifier; the map provides a corresponding value that will replace the text when the module specifier is resolved.

### Bare modules

The import map below defines an `imports` key that has a "module specifier map" with properties `square` and `circle`.

```html
<script type="importmap">
 {
 "imports": {
 "square": "./module/shapes/square.js",
 "circle": "https://example.com/shapes/circle.js"
 }
 }
</script>
```

With this import map we can import the same modules as above, but using "bare modules" in our module specifiers:

```js
import { name as squareName, draw } from "square";
import { name as circleName } from "circle";
```

### Mapping path prefixes

 A module specifier map key can also be used to remap a path prefix in a module specifier.
 Note that in this case the property and mapped path must both have a trailing forward slash (`/`).

```html
<script type="importmap">
 {
 "imports": {
 "shapes/": "./module/shapes/",
 "othershapes/": "https://example.com/modules/shapes/"
 }
 }
</script>
```

We could then import a circle module as shown.

```js
import { name as circleName } from "shapes/circle.js";
```

### Paths in the module specifier map key

 Module specifier keys do not have to be single word names ("bare names").
 They can also contain or end with path separators, or be absolute URLs, or be relative URL paths that start with `/`, `./`, or `../`.

```json
{
  "imports": {
    "modules/shapes/": "./module/src/shapes/",
    "modules/square": "./module/src/other/shapes/square.js",
    "https://example.com/modules/square.js": "./module/src/other/shapes/square.js",
    "../modules/shapes/": "/modules/shapes/"
  }
}
```

If there are several module specifier keys in a module specifier map that might match, then the most specific key will be selected (i.e. the one with the longer path/value).

 A module specifier of `./foo/../js/app.js` would be resolved to `./js/app.js` before matching.
 This means that a module specifier key of `./js/app.js` would match the module specifier even though they are not exactly the same.

### Scoped module specifier maps

 You can use the `scopes` key to provide mappings that are only used if the script importing the module contains a particular URL path.
 If the URL of the loading script matches the supplied path, the mapping associated with the scope will be used.
 This allows different versions of the module to be used depending on what code is doing the importing.

For example, the map below will only use the scoped map if the loading module has a URL that includes the path: "/modules/customshapes/".

```html
<script type="importmap">
 {
 "imports": {
 "square": "./module/shapes/square.js"
 },
 "scopes": {
 "/modules/customshapes/": {
 "square": "https://example.com/modules/shapes/square.js"
 }
 }
 }
</script>
```

 If multiple scopes match the referrer URL, then the most specific scope path is used (the scope key name with the longest name).
 The browser falls back to the next most specific scoped path if there is no matching specifier, and so on, eventually falling back to the module specifier map in the `imports` key.

Import map JSON representation
------------------------------

The following is a "formal" definition of the import map JSON representation.

The import map must be a valid JSON object that can define at most two optional keys: `imports` and `scopes`. Each key's value must be an object, which may be empty.

`imports` Optional

The value is a module specifier map, which provides the mappings between module specifier text that might appear in an `import` statement or `import()` operator, and the text that will replace it when the specifier is resolved.

This is the fallback map that is searched for matching module specifiers if no `scopes` path URLs match, or if module specifier maps in matching `scopes` paths do not contain a key that matches the module specifier.

`<module specifier map>`

A "module specifier map" is a valid JSON object where the *keys* are text that may be present in the module specifier when importing a module, and the corresponding *values* are the URLs or paths that will replace this text when the module specifier is resolved to an address.

The module specifier map JSON object has the following requirements:

* None of the keys may be empty.
* All of the values must be strings, defining either a valid absolute URL or a valid URL string that starts with `/`, `./`, or `../`.
* If a key ends with `/`, then the corresponding value must also end with `/`.
 A key with a trailing `/` can be used as a prefix for when mapping (or remapping) modules addresses.
* The object properties' ordering is irrelevant: if multiple keys can match the module specifier, the most specific key is used (in other words, a specifier "olive/branch/" would match before "olive/").

`scopes` Optional

Scopes define path-specific module specifier maps, allowing the choice of map to depend on the path of the code importing the module.

The scopes object is a valid JSON object where each property is a `<scope key>`, which is an URL path, with a corresponding value that is a `<module specifier map>`.

 If the URL of a script importing a module matches a `<scope key>` path, then the `<module specifier map>` value associated with the key is checked for matching specifiers first.
 If there are multiple matching scope keys, then the value associated with the most specific/nested scope paths are checked for matching module specifiers first.
 The fallback module specifier map in `imports` is used if there are no matching module specifier keys in any of the matching scoped module specifier maps.

Note that the scope does not change how an address is resolved; relative addresses are always resolved to the import map base URL.

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

| Specification |
| --- |
| HTML Standard # import-map |

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

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

See also
--------

* JavaScript modules > Importing modules using import maps
* The `type` attribute of HTML `<script>` elements
* `import` statement
* `import()` operator


How to - Progressive web apps

How to
======

How-to guides explain in detail how to accomplish a specific task related to PWAs.

* Associate files with your PWA
* Create a standalone app
* Customize your app's theme and background colors
* Define your app icons
* Display a badge on the app icon
* Expose common app actions as shortcuts
* Share data between apps
* Trigger installation from your PWA


Tutorials - Progressive web apps

Tutorials
=========

This page lists tutorials to help learn how to develop PWAs. Tutorials walk through the steps of creating an app, from start to finish, explaining how the different features of the app are implemented.

Creating your first PWA

This novice-level tutorial walks through the creation of a PWA to track menstrual cycles. Lessons include a walk through of the HTML, CSS, and JavaScript required to create a fully functional web app, setting up a testing environment, and complete explanations guiding the learner through upgrading the web app into a PWA; including developing and inspecting a manifest, adding a service worker, and using the service worker to delete stale caches.

Deep dive into PWA

This intermediate-level tutorial walks through the creation of a PWA that lists information about games submitted to the A-Frame category in the js13kGames 2017 competition. This tutorial includes all the basics for creating a PWA, with additional features, including notifications, push, and app performance.


Guides - Progressive web apps

Guides
======

This page lists guides to PWA technology. Guides give conceptual explanations of different aspects of PWAs. They're intended to help you understand what kinds of things are possible with PWAs, and to provide enough pointers to help you understand how to achieve them.

* Best practices for PWAs
* Caching
* Installing and uninstalling web apps
* Making PWAs installable
* Offline and background operation
* What is a progressive web app?


Progressive Web Apps reference - Progressive web apps

Progressive Web Apps reference
==============================

This reference describes the technologies, features, and APIs that Progressive Web Apps (PWAs) can use to offer a great user experience.

Web app manifest
----------------

Web app manifest members

Developers can use web app manifest members to describe a PWA, customize its appearance, and more deeply integrate it into the operating system.

Service Worker APIs
-------------------

### Communication with the app

The following APIs can be used by a service worker to communicate with its associated client PWA:

`Client.postMessage()`

Allows a service worker to send a message to its client PWA.

Broadcast Channel API

Allows a service worker and its client PWA to establish a basic two-way communication channel.

### Offline operation

The following APIs can be used by a service worker to make your app work offline:

`Cache`

A persistent storage mechanism for HTTP responses used to store assets that can be reused when the app is offline.

`Clients`

An interface used to provide access to the documents that are controlled by the service worker.

`FetchEvent`

An event, dispatched in the service worker with every HTTP request made by the client PWA. The event can be used to either send the request to the server as normal and save the response for future use, or intercept the request and immediately respond with a response cached previously.

### Background operation

The following APIs can be used by a service worker to perform tasks in the background, even when your app is not running:

Background Synchronization API

A way to defer tasks to run in a service worker once there is a stable network connection.

Web Periodic Background Synchronization API

A way to register tasks to be run in a service worker at periodic intervals with network connectivity.

Background Fetch API

A method for a service worker to manage downloads that may take a significant amount of time, such as video or audio files.

Other web APIs
--------------

IndexedDB

A client-side storage API for significant amounts of structured data, including files.

Badging API

A method of setting a badge on the application icon, providing a low-distraction notification.

Notifications API

A way to send notifications that are displayed at the operating system level.

Web Share API

A mechanism for sharing text, links, files, and other content to other apps selected by the user on their device.

Window Controls Overlay API

An API for PWAs installed on desktop operating systems that enables hiding the default window title bar, enabling displaying the app over the full surface area of the app window.


Best practices for PWAs - Progressive web apps

Best practices for PWAs
=======================

Progressive Web Apps (PWAs) can be installed on devices and used as traditional websites in web browsers. This means that PWAs need to be able to adapt to different environments and to different user expectations.

This article provides a list of best practices to help you make sure your PWA is as good as it can be.

Adapt to all browsers
---------------------

Your PWA is based on Web technologies. This means that, on top of being installable on devices, PWAs can run in web browsers too. To ensure compatibility, it's essential to test your app across various browsers and operating systems.

Consider the diverse range of browsers your users may use and cater to a wide spectrum of potential users. Using feature detection allows you to deliver a usable experience to the broadest audience.

Feature detection also helps with Progressive Enhancement, a design philosophy that makes it possible to deliver a great experience to as many users as possible.

With Progressive Enhancement, you focus on making the core functionalities of your app work universally first by using the simplest technology, then enhancing the experience for supporting devices.

For example, handling form submissions with the HTML `<form>` element means that the form will work on all browsers, including those that don't support JavaScript. You can then progressively enhance the form by adding client-side validation and JavaScript-based submission handling for a better experience on compatible devices.

Adapt to all devices
--------------------

Similar to how testing your app across various browsers is important, testing across devices ensures your app is accessible to the broadest audience.

Responsive design is crucial for PWAs to ensure the content is accessible on any screen size. Users should be able to access all features and content regardless of their device's screen size. By rearranging content at different viewport sizes, you can prioritize important data and actions.

Ensure users can interact with your application no matter how they access your content. Support keyboard and mouse, as well as touch or stylus input methods. Make sure all your application features can be accessed through any input method.

Finally, use semantic HTML elements rather than recreating your own buttons or form elements as semantic HTML elements support all user input methods right out of the box.

Provide an offline experience
-----------------------------

Users of installed apps expect them to always work; even when connected to a slow or unreliable network or when their device is completely offline.

### Custom offline page

At the very least, your PWA should provide a custom offline page that informs the user that they are offline instead of showing the generic browser error page. A custom offline page provides a more consistent experience across browsers and devices and keeps the user engaged with your app.

You can provide a custom offline page by using a service worker to intercept network requests and respond with the custom offline page when the user is offline.

### Offline operation

To go further and provide an app-like experience, your PWA should function when the user is offline. This means that the user can continue using some, and preferably all, of your app's functionality even when they are offline.

Consider the following scenario: the user composes a long email and presses "Send", not realizing they have lost network connectivity. Because your app works offline, the email will be saved locally and sent automatically when the device is back online.

Learn more about offline and background operations.

Support deep links
------------------

Deep links are hyperlinks that point to specific pages within your app's domain. For example, your app's home page might be available at `https://example.com/`, but you can also link to a specific product page at `https://example.com/products/123`.

The ability to refer to any resource by a unique URL is one of the most powerful features of the web. Because they're built on web technologies, PWAs can, and should, take advantage of this feature.

Making different sections of your app available via unique URLs allows users to bookmark, navigate directly to, and share specific content within your app. It also allows search engines to index your app's content and make it discoverable through web searches.

Make it fast
------------

Users have different expectations for installed apps than they do for websites. Users anticipate websites to need time for loading and navigation, particularly on poor network connections. However, they expect installed apps to be always fast and responsive.

The speed at which your app loads and performs its core functions plays a key role in user engagement and retention. The longer it takes for your app to respond, the more users will abandon it.

There are tools, APIs, and best practices that help measure and improve performance. To learn more, see web performance.

Make it accessible
------------------

Accessibility is crucial to ensure everyone can use your app, regardless of an individual's abilities or the device they use to access your app. Accessibility ensures that as many people can use your app as possible. Accessibility is also required by law. Furthermore, accessibility often leads to better user experience for everyone, not just those with permanent or temporary disabilities.

Learn how to make your app accessible in accessibility.

Provide an app-like experience
------------------------------

### Integrate with the operating system

Users expect installed PWAs to behave like any installed platform-specific app. To provide the app-like experience that users expect, integrate your app with the operating system in some way. For example:

* Use the Notifications API to send notifications to the user's device.
* Handle files with the `file_handlers` web app manifest member.
* Display badges on the app icon.
* Enable data sharing between apps.

Many of the web app manifest members can be used to customize the way your app is displayed on the user's device and integrate more deeply within the operating system.

### App look and feel

Users install apps to get a more focused experience than what they get from websites and achieve tasks more efficiently. They expect apps to be more streamlined, with less clutter, and to focus on the most important tasks.

Make sure your PWA provides an app-like experience by considering the following guidelines:

* Use a standalone display mode to give your app its own dedicated window.
* Define your app icon.
* Detect the user's preferred theme with the `prefers-color-scheme` media feature and adapt your app's theme accordingly.
* Customize your app's theme and background colors to provide a more polished experience that feels more like a platform-specific app.
* De-clutter the content and focus on the most important tasks that your app lets users achieve. This may mean removing big headers and footers that are traditionally found on websites and replacing them with a menu metaphor instead.
* Use the `system-ui` `font-family` to make your content feel more platform-native and load faster without requiring users to download a custom font.
See also
--------

* What makes a good Progressive Web App on web.dev (2022).
* Best practices for PWAs on learn.microsoft.com (2023).