Test your skills: Advanced styling - Learn web development

Test your skills: Advanced styling
==================================

The aim of this skill test is to assess whether you've understood our Advanced form styling and UI pseudo-classes articles.

**Note:** You can try solutions in the interactive editors on this page or in an online editor such as CodePen, JSFiddle, or Glitch.

If you get stuck, you can reach out to us in one of our communication channels.

Advanced form styling 1
-----------------------

In our first advanced styling tasks, we want you to handle making a search input as consistent as possible across browsers — a trickier task than with standard text inputs, even on modern browsers.

We've already provided you with a basic reset to build upon.

1. First of all, try giving the search box a consistent width, height, padding, and border color across browsers.
2. You'll find that some browsers will not behave in terms of the form element's height. This is due to native OS styling being used in some cases. How can you remove this native styling?
3. Once you've removed the native styling, you'll need to add back one of the features it was providing, to keep the same look and feel we originally had. How do you do this?
4. One thing that is inconsistent across browsers (particularly looking at Safari here) is the position of the standard blue focus outline. How can you remove this?
5. There is a major problem with just getting rid of the blue focus outline. What is it? Can you add some kind of styling back in so that users can tell when the search box is being hovered or focused?
6. Another thing that commonly denotes a search box is a magnifying glass icon. We've made one available in the same directory as our HTML files — see search-24px.png — plus a `<div>` element after the search input to help you attach it, should you need it. Can you figure out a sensible way to attach it, and can you use some CSS to get it to sit to the right of the search box, and be lined up vertically as well?

Try updating the live code below to recreate the finished example:

Download the starting point for this task to work in your own editor or in an online editor.

Advanced form styling 2
-----------------------

In our next task we provide you with a set of three radio buttons. We want you to give them custom styling.

We've already provided you with a basic reset to build upon.

1. First of all, get rid of their default styling.
2. Next, give the radio buttons a reasonable base style — the style they have when the page first loads. This can be anything you like, but you probably want to set a width and height (of somewhere between about 18 and 24 pixels), and a subtle border and/or background color.
3. Now give the radio buttons a different style for when they are selected.
4. Align the radio buttons nicely with the labels.

Try updating the live code below to recreate the finished example:

Download the starting point for this task to work in your own editor or in an online editor.

Advanced form styling 3
-----------------------

In our final task for this assessment series, we provide you with a feedback form that is already nicely-styled — you've already seen something similar if you've worked through our UI pseudo-classes article, and now we want you to come up with your own solution.

What we'd like you to do is make use of some advanced pseudo-classes to provide some useful indicators of validity.

1. First of all, we want you to provide some specific styling to visually indicate which inputs have to be filled in — they cannot be left empty.
2. Second, we want you to provide a useful visual indicator of whether the data entered inside each input is valid or not.

Download the starting point for this task to work in your own editor or in an online editor.


HTML forms in legacy browsers - Learn web development

HTML forms in legacy browsers
=============================

All web developers learn very quickly (and sometimes painfully) that the Web is a very rough place for them. Our worst curse is legacy browsers. Okay, let's admit it, when we said "legacy browser" we all have in mind "Internet Explorer", but they are far from the only ones. In the mobile world, when neither the browser nor the OS can be updated such as on older Android phones or iPhones, the stock browsers that don't update are also legacy browsers.

Dealing with this wilderness is part of the job. Fortunately, there are a few tricks to know that can help you to solve most of the problems caused by legacy browsers. If a browser doesn't support an HTML `<input>` type, it doesn't fail: it just uses the default value of `type=text`.

Learn about the issues
----------------------

To understand common patterns, it helps to read documentation. If you are reading this on MDN, you are at the right place to start. Just check the support of the elements (or DOM interfaces) you want to use. MDN has compatibility tables available for most elements, properties and APIs that can be used in a web page.

Because HTML forms involves complex interaction, there is one important rule: keep it simple, also known as the "KISS principal". There are so many cases where we want forms that are "nicer" or "with advanced functionality", but building efficient HTML Forms is not a question of design or technology. Rather, it's about simplicity, intuitiveness, and ease of user interaction. The tutorial, forms usability on UX For The Masses, explains it well.

### Graceful degradation is web developer's best friend

Graceful degradation and progressive enhancement are development patterns that allow you to build great stuff by supporting a wide range of browsers at the same time. When you build something for a modern browser, and you want to be sure it will work, one way or another, on legacy browsers, you are performing graceful degradation.

Let's see some examples related to HTML forms.

#### HTML input types

All HTML input types are useable in all browsers, even ancient ones, because the way they degrade is highly predictable. If a browser does not know the value of the `type` attribute of an `<input>` element, it will fall back as if the value were `text`.

```html
<label for="myColor">
  Pick a color
  <input type="color" id="myColor" name="color" />
</label>
```

| Supported | Not supported |
| --- | --- |
| Screen shot of the color input on Chrome for Mac OSX | Screen shot of the color input on Firefox for Mac OSX |

#### Form buttons

There are two ways to define buttons within HTML forms:

* The `<input>` element with its attribute `type` set to the values `button`, `submit`, `reset` or `image`
* The `<button>` element

##### `<input>`

The `<input>` element can make things a little difficult if you want to apply some CSS by using the element selector:

```html
<input type="button" value="click me" />
```

If we remove the border on all inputs, can we restore the default appearance on input buttons only?

```css
input {
  /\* This rule turns off the default rendering for the input types that have a border,
 including buttons defined with an input element \*/
  border: 1px solid #ccc;
}
input[type="button"] {
  /\* This does NOT restore the default rendering \*/
  border: none;
}
input[type="button"] {
  /\* These don't either! Actually there is no standard way to do it in any browser \*/
  border: auto;
  border: initial;
}
input[type="button"] {
  /\* This will come the closest to restoring default rendering. \*/
  border: revert;
}
```

See the global CSS `revert` value for more information.

##### `<button>`

The `<button>` element suffered from two issues that are now resolved:

* A bug in old versions of Internet Explorer sent the HTML content available between the starting and ending tag of the `<button>` element instead of the content of the `value` attribute when clicked. This was only an issue if that value needed to be sent, such as when data processing depends on which button a user clicked.
* Some very old browsers did not use `submit` as the default value for the `type` attribute. While resolved in all modern browsers, it is still recommended to always set the `type` attribute on `<button>` elements.

```html
<!-- Clicking this button sent "<em>Do A</em>" instead of "A" in some cases -->
<button type="submit" name="IWantTo" value="A">
  <em>Do A</em>
</button>
```

Choosing one solution or the other is up to you based on your project's constraints.

### Let go of CSS

One of the big issues with HTML Forms is styling form widgets with CSS. Form controls appearance is browser and operating system specific. For example, the input of color type looks different in Safari, Chrome and Firefox browser, but the color picker widget is the same in all browsers on a device as it opens up the operating system's native color picker.

It's generally a good idea to not alter the default appearance of form control because altering one CSS property value may alter some input types but not others. For example, if you declare `input { font-size: 2rem; }`, it will impact `number`, `date`, and `text`, but not `color` or `range`. If you alter a property, that may impact the appearance of the widget in unexpected ways. For example, `[value] { background-color: #ccc; }` may have been used to target every `<input>` with a `value` attribute, but changing the background-color or border radius on a `<meter>` will lead to likely unexpected results that differ across browsers. You can declare `appearance: none;` to remove the browser styles, but that generally defeats the purpose: as you lose all styling, removing the default look and feel your visitors are used to.

To summarize, when it comes to styling form control widgets, the side effects of styling them with CSS can be unpredictable. So don't. As you can see from the complexity of the Property compatibility table for form widgets article, it's very difficult. Even if it's still possible to do a few adjustments on text elements (such as sizing or font color), there are always side effects. The best approach remains to not style HTML Form widgets at all. But you can still apply styles to all the surrounding items. And, if you must alter the default styles of your form widgets, define a style guide to ensure consistency among all your form controls so user experience is not destroyed. You can also investigate some hard techniques such as rebuilding widgets with JavaScript. But in that case, do not hesitate to charge your client for such foolishness.

Feature detection and polyfills
-------------------------------

CSS and JavaScript are awesome technologies, but it's important to ensure you don't break legacy browsers. Before using features that aren't fully supported in the browsers your targeting, you should feature detect:

### CSS feature detection

Before styling a replaced form control widget, you can check to see if the browser supports the features you plan on using `@supports`:

```css
@supports (appearance: none) {
  input[type="search"] {
    appearance: none;
    /\* restyle the search input \*/
  }
}
```

The `appearance` property can be used to display an element using platform-native styling, or, as is done with the value of `none`, remove default platform-native based styling.

### Unobtrusive JavaScript

One of the biggest problems is the availability of APIs. For that reason, it's considered best practice to work with "unobtrusive" JavaScript. It's a development pattern that defines two requirements:

* A strict separation between structure and behaviors.
* If the code breaks, the content and the basic functionalities must remain accessible and usable.

The principles of unobtrusive JavaScript (originally written by Peter-Paul Koch for Dev.Opera.com) describes these ideas very well.

### Pay attention to performance

Even though some polyfills are very aware of performance, loading additional scripts can affect the performance of your application. This is especially critical with legacy browsers; many of them have a very slow JavaScript engine that can make the execution of all your polyfills painful for the user. Performance is a subject on its own, but legacy browsers are very sensitive to it: basically, they are slow and the more polyfills they need, the more JavaScript they have to process. So they are doubly burdened compared to modern browsers. Test your code with legacy browsers to see how they actually perform. Sometimes, dropping some functionality leads to a better user experience than having exactly the same functionality in all browsers. As a last reminder, just always think about the end users.

Conclusion
----------

As you can see, considering browser and operating system default form control appearance is important. There are many techniques to handle these issue; however mastering all of them is beyond the scope of this article. The basic premise is to consider whether altering the default implementation is worth the work before embarking on the challenge.

If you read all the articles of this HTML Forms guide, you should now be at ease with using forms. If you discover new techniques or hints, please help improve the guide.

See also
--------

### Learning path

* Your first HTML form
* How to structure an HTML form
* The native form widgets
* HTML5 input types
* Additional form controls
* UI pseudo-classes
* Styling HTML forms
* Form data validation
* Sending form data
### Advanced Topics

* Sending forms through JavaScript
* How to build custom form widgets
* **HTML forms in legacy browsers**
* Advanced styling for HTML forms
* Property compatibility table for form widgets


How to structure a web form - Learn web development

How to structure a web form
===========================

* Previous
* Overview: Forms
* Next

With the basics out of the way, we'll now look in more detail at the elements used to provide structure and meaning to the different parts of a form.

|  |  |
| --- | --- |
| Prerequisites: | A basic understanding of HTML. |
| Objective: | To understand how to structure HTML forms and give them semantics so they are usable and accessible. |

The flexibility of forms makes them one of the most complex structures in HTML; you can build any kind of basic form using dedicated form elements and attributes. Using the correct structure when building an HTML form will help ensure that the form is both usable and accessible.

The <form> element
------------------

The `<form>` element formally defines a form and attributes that determine the form's behavior. Each time you want to create an HTML form, you must start it by using this element, nesting all the contents inside. Many assistive technologies and browser plugins can discover `<form>` elements and implement special hooks to make them easier to use.

We already met this in the previous article.

**Warning:** It's strictly forbidden to nest a form inside another form. Nesting can cause forms to behave unpredictably, so it is a bad idea.

It's always possible to use a form control outside of a `<form>` element. If you do so, by default that control has nothing to do with any form unless you associate it with a form using its `form` attribute. This was introduced to let you explicitly bind a control with a form even if it is not nested inside it.

Let's move forward and cover the structural elements you'll find nested in a form.

The <fieldset> and <legend> elements
------------------------------------

The `<fieldset>` element is a convenient way to create groups of widgets that share the same purpose, for styling and semantic purposes. You can label a `<fieldset>` by including a `<legend>` element just below the opening `<fieldset>` tag. The text content of the `<legend>` formally describes the purpose of the `<fieldset>` it is included inside.

Many assistive technologies will use the `<legend>` element as if it is a part of the label of each control inside the corresponding `<fieldset>` element. For example, some screen readers such as Jaws and NVDA will speak the legend's content before speaking the label of each control.

Here is a little example:

```html
<form>
  <fieldset>
    <legend>Fruit juice size</legend>
    <p>
      <input type="radio" name="size" id="size\_1" value="small" />
      <label for="size\_1">Small</label>
    </p>
    <p>
      <input type="radio" name="size" id="size\_2" value="medium" />
      <label for="size\_2">Medium</label>
    </p>
    <p>
      <input type="radio" name="size" id="size\_3" value="large" />
      <label for="size\_3">Large</label>
    </p>
  </fieldset>
</form>
```

**Note:** You can find this example in fieldset-legend.html (see it live also).

When reading the above form, a screen reader will speak "Fruit juice size small" for the first widget, "Fruit juice size medium" for the second, and "Fruit juice size large" for the third.

The use case in this example is one of the most important. Each time you have a set of radio buttons, you should nest them inside a `<fieldset>` element. There are other use cases, and in general the `<fieldset>` element can also be used to section a form. Ideally, long forms should be spread across multiple pages, but if a form is getting long and must be on a single page, putting the different related sections inside different fieldsets improves usability.

Because of its influence over assistive technology, the `<fieldset>` element is one of the key elements for building accessible forms; however, it is your responsibility not to abuse it. If possible, each time you build a form, try to listen to how a screen reader interprets it. If it sounds odd, try to improve the form structure.

The <label> element
-------------------

As we saw in the previous article, The `<label>` element is the formal way to define a label for an HTML form widget. This is the most important element if you want to build accessible forms — when implemented properly, screen readers will speak a form element's label along with any related instructions, as well as it being useful for sighted users. Take this example, which we saw in the previous article:

```html
<label for="name">Name:</label> <input type="text" id="name" name="user\_name" />
```

With the `<label>` associated correctly with the `<input>` via its `for` attribute (which contains the `<input>` element's `id` attribute), a screen reader will read out something like "Name, edit text".

There is another way to associate a form control with a label — nest the form control within the `<label>`, implicitly associating it.

```html
<label for="name">
  Name: <input type="text" id="name" name="user\_name" />
</label>
```

Even in such cases however, it is considered best practice to set the `for` attribute to ensure all assistive technologies understand the relationship between label and widget.

If there is no label, or if the form control is neither implicitly nor explicitly associated with a label, a screen reader will read out something like "Edit text blank", which isn't very helpful at all.

### Labels are clickable, too!

Another advantage of properly set up labels is that you can click or tap the label to activate the corresponding widget. This is useful for controls like text inputs, where you can click the label as well as the input to focus it, but it is especially useful for radio buttons and checkboxes — the hit area of such a control can be very small, so it is useful to make it as easy to activate as possible.

For example, clicking on the "I like cherry" label text in the example below will toggle the selected state of the *taste\_cherry* checkbox:

```html
<form>
  <p>
    <input type="checkbox" id="taste\_1" name="taste\_cherry" value="cherry" />
    <label for="taste\_1">I like cherry</label>
  </p>
  <p>
    <input type="checkbox" id="taste\_2" name="taste\_banana" value="banana" />
    <label for="taste\_2">I like banana</label>
  </p>
</form>
```

**Note:** You can find this example in checkbox-label.html (see it live also).

### Multiple labels

Strictly speaking, you can put multiple labels on a single widget, but this is not a good idea as some assistive technologies can have trouble handling them. In the case of multiple labels, you should nest a widget and its labels inside a single `<label>` element.

Let's consider this example:

```html
<p>Required fields are followed by <span aria-label="required">*</span>.</p>

<!-- So this: -->
<!--div>
 <label for="username">Name:</label>
 <input id="username" type="text" name="username" required>
 <label for="username"><span aria-label="required">\*</label>
</div-->

<!-- would be better done like this: -->
<!--div>
 <label for="username">
 <span>Name:</span>
 <input id="username" type="text" name="username" required>
 <span aria-label="required">\*</span>
 </label>
</div-->

<!-- But this is probably best: -->
<div>
  <label for="username">Name: <span aria-label="required">*</span></label>
  <input id="username" type="text" name="username" required />
</div>
```

The paragraph at the top states a rule for required elements. The rule must be included *before* it is used so that sighted users and users of assistive technologies such as screen readers can learn what it means before they encounter a required element. While this helps inform users what an asterisk means, it can not be relied upon. A screen reader will speak an asterisk as "*star*" when encountered. When hovered by a sighted mouse user, "*required*" should appear, which is achieved by use of the `title` attribute. Titles being read aloud depends on the screen reader's settings, so it is more reliable to also include the `aria-label` attribute, which is always read by screen readers.

The above variants increase in effectiveness as you go through them:

* In the first example, the label is not read out at all with the input — you just get "edit text blank", plus the actual labels are read out separately. The multiple `<label>` elements confuse the screen reader.
* In the second example, things are a bit clearer — the label read out along with the input is "name star name edit text required", and the labels are still read out separately. Things are still a bit confusing, but it's a bit better this time because the `<input>` has a label associated with it.
* The third example is best — the actual label is read out all together, and the label read out with the input is "name required edit text".

**Note:** You might get slightly different results, depending on your screen reader. This was tested in VoiceOver (and NVDA behaves similarly). We'd love to hear about your experiences too.

**Note:** You can find this example on GitHub as required-labels.html (see it live also). Don't test the example with 2 or 3 of the versions uncommented — screen readers will definitely get confused if you have multiple labels AND multiple inputs with the same ID!

Common HTML structures used with forms
--------------------------------------

Beyond the structures specific to web forms, it's good to remember that form markup is just HTML. This means that you can use all the power of HTML to structure a web form.

As you can see in the examples, it's common practice to wrap a label and its widget with a `<li>` element within a `<ul>` or `<ol>` list. `<p>` and `<div>` elements are also commonly used. Lists are recommended for structuring multiple checkboxes or radio buttons.

In addition to the `<fieldset>` element, it's also common practice to use HTML titles (e.g. h1, h2) and sectioning (e.g. `<section>`) to structure complex forms.

Above all, it is up to you to find a comfortable coding style that results in accessible, usable forms. Each separate section of functionality should be contained in a separate `<section>` element, with `<fieldset>` elements to contain radio buttons.

### Active learning: building a form structure

Let's put these ideas into practice and build a slightly more involved form — a payment form. This form will contain a number of control types that you may not yet understand. Don't worry about this for now; you'll find out how they work in the next article (Basic native form controls). For now, read the descriptions carefully as you follow the below instructions, and start to form an appreciation of which wrapper elements we are using to structure the form, and why.

1. To start with, make a local copy of our blank template file in a new directory on your computer.
2. Next, create your form by adding a `<form>` element:

```html
<form>
```

3. Inside the `<form>` element, add a heading and paragraph to inform users how required fields are marked:

```html
<h1>Payment form</h1>
<p>
  Required fields are followed by
  <strong><span aria-label="required">*</span></strong>.
</p>
```

4. Next, we'll add a larger section of code into the form, below our previous entry. Here you'll see that we are wrapping the contact information fields inside a distinct `<section>` element. Moreover, we have a set of three radio buttons, each of which we are putting inside its own list (`<li>`) element. We also have two standard text `<input>`s and their associated `<label>` elements, each contained inside a `<p>`, and a password input for entering a password. Add this code to your form:

```html
<section>
  <h2>Contact information</h2>
  <fieldset>
    <legend>Title</legend>
    <ul>
      <li>
        <label for="title\_1">
          <input type="radio" id="title\_1" name="title" value="A" />
          Ace
        </label>
      </li>
      <li>
        <label for="title\_2">
          <input type="radio" id="title\_2" name="title" value="K" />
          King
        </label>
      </li>
      <li>
        <label for="title\_3">
          <input type="radio" id="title\_3" name="title" value="Q" />
          Queen
        </label>
      </li>
    </ul>
  </fieldset>
  <p>
    <label for="name">
      <span>Name: </span>
      <strong><span aria-label="required">*</span></strong>
    </label>
    <input type="text" id="name" name="username" required />
  </p>
  <p>
    <label for="mail">
      <span>Email: </span>
      <strong><span aria-label="required">*</span></strong>
    </label>
    <input type="email" id="mail" name="usermail" required />
  </p>
  <p>
    <label for="pwd">
      <span>Password: </span>
      <strong><span aria-label="required">*</span></strong>
    </label>
    <input type="password" id="pwd" name="password" required />
  </p>
</section>
```

5. The second `<section>` of our form is the payment information.
 We have three distinct controls along with their labels, each contained inside a `<p>`.
 The first is a drop-down menu (`<select>`) for selecting credit card type.
 The second is an `<input>` element of type `tel`, for entering a credit card number; while we could have used the `number` type, we don't want the number's spinner UI.
 The last one is an `<input>` element of type `text`, for entering the expiration date of the card; this includes a *placeholder* attribute indicating the correct format, and a *pattern* that tests that the entered date has the correct format.
 These newer input types are reintroduced in The HTML5 input types.
 Enter the following below the previous section:

```html
<section>
  <h2>Payment information</h2>
  <p>
    <label for="card">
      <span>Card type:</span>
    </label>
    <select id="card" name="usercard">
      <option value="visa">Visa</option>
      <option value="mc">Mastercard</option>
      <option value="amex">American Express</option>
    </select>
  </p>
  <p>
    <label for="number">
      <span>Card number:</span>
      <strong><span aria-label="required">*</span></strong>
    </label>
    <input type="tel" id="number" name="cardnumber" required />
  </p>
  <p>
    <label for="expiration">
      <span>Expiration date:</span>
      <strong><span aria-label="required">*</span></strong>
    </label>
    <input
 type="text"
 id="expiration"
 required
 placeholder="MM/YY"
 pattern="^(0[1-9]|1[0-2])\/([0-9]{2})$" />
  </p>
</section>
```

6. The last section we'll add is a lot simpler, containing only a `<button>` of type `submit`, for submitting the form data. Add this to the bottom of your form now:

```html
<section>
  <p>
    <button type="submit">Validate the payment</button>
  </p>
</section>
```

7. Finally, complete your form by adding the outer `<form>` closing tag:

```html
</form>
```

```
h1 {
  margin-top: 0;
}

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

form {
  margin: 0 auto;
  width: 400px;
  padding: 1em;
  border: 1px solid #ccc;
  border-radius: 1em;
}

div + div {
  margin-top: 1em;
}

label span {
  display: inline-block;
  text-align: right;
}

input,
textarea {
  font: 1em sans-serif;
  width: 250px;
  box-sizing: border-box;
  border: 1px solid #999;
}

input[type="checkbox"],
input[type="radio"] {
  width: auto;
  border: none;
}

input:focus,
textarea:focus {
  border-color: #000;
}

textarea {
  vertical-align: top;
  height: 5em;
  resize: vertical;
}

fieldset {
  width: 250px;
  box-sizing: border-box;
  border: 1px solid #999;
}

button {
  margin: 20px 0 0 0;
}

label {
  position: relative;
  display: inline-block;
}

p label {
  width: 100%;
}

label em {
  position: absolute;
  right: 5px;
  top: 20px;
}
```

We applied some extra CSS to the finished form below. If you'd like to make changes to the appearance of your form, you can copy styles from the example or visit Styling web forms.

Test your skills!
-----------------

You've reached the end of this article, but can you remember the most important information? You can find a further test to verify that you've retained this information before you move on — see Test your skills: Form structure.

Summary
-------

You now have all the knowledge you'll need to properly structure your web forms. We will cover many of the features introduced here in the next few articles, with the next article looking in more detail at using all the different types of form widgets you'll want to use to collect information from your users.

See also
--------

* A List Apart: *Sensible Forms: A Form Usability Checklist*
* Previous
* Overview: Forms
* Next
### Advanced Topics

* How to build custom form controls
* Sending forms through JavaScript
* Property compatibility table for form widgets


Other form controls - Learn web development

Other form controls
===================

* Previous
* Overview: Forms
* Next

We now look at the functionality of non-`<input>` form elements in detail, from other control types such as drop-down lists and multi-line text fields, to other useful form features such as the `<output>` element (which we saw in action in the previous article), and progress bars.

|  |  |
| --- | --- |
| Prerequisites: |
 A basic
 understanding of HTML.
  |
| Objective: |
 To understand the non-`<input>` form features, and how
 to implement them using HTML.
  |

Multi-line text fields
----------------------

A multi-line text field is specified using a `<textarea>` element, rather than using the `<input>` element.

```html
<textarea cols="30" rows="8"></textarea>
```

This renders like so:

The main difference between a `<textarea>` and a regular single-line text field is that users are allowed to include hard line breaks (i.e. pressing return) that will be included when the data is submitted.

`<textarea>` also takes a closing tag; any default text you want it to contain should be put between the opening and closing tags. In contrast, the `<input>` is a void element with no closing tag — any default value is put inside the `value` attribute.

Note that even though you can put anything inside a `<textarea>` element (including other HTML elements, CSS, and JavaScript), because of its nature, it is all rendered as if it was plain text content. (Using `contenteditable` on non-form controls provides an API for capturing HTML/"rich" content instead of plain text).

Visually, the text entered wraps and the form control is by default resizable. Modern browsers provide a drag handle that you can drag to increase/decrease the size of the text area.

The following screenshots show default, focused, and disabled `<textarea>` elements in Firefox 71 and Safari 13 on macOS and in Edge 18, Yandex 14, Firefox 71, and Chrome 79 on Windows 10.

![The default, focused, and disabled 'textarea' element in Firefox 71 and Safari 13 on Mac OSX and Edge 18, Yandex 14, Firefox and Chrome on Windows 10.](/en-US/docs/Learn/Forms/Other_form_controls/textarea_basic.png)

**Note:** You can find a slightly more interesting example of text area usage in the example we put together in the first article of the series (see the source code also).

### Controlling multi-line rendering

`<textarea>` accepts three attributes to control its rendering across several lines:

`cols`

Specifies the visible width (columns) of the text control, measured in average character widths. This is effectively the starting width, as it can be changed by resizing the `<textarea>`, and overridden using CSS. The default value if none is specified is 20.

`rows`

Specifies the number of visible text rows for the control. This is effectively the starting height, as it can be changed by resizing the `<textarea>`, and overridden using CSS. The default value if none is specified is 2.

`wrap`

Specifies how the control wraps text. The values are `soft` (the default value), which means the text submitted is not wrapped but the text rendered by the browser is wrapped; `hard` (the `cols` attribute must be specified when using this value), which means both the submitted and rendered texts are wrapped, and `off`, which stops wrapping.

### Controlling textarea resizability

The ability to resize a `<textarea>` is controlled with the CSS `resize` property. Its possible values are:

* `both`: The default — allows resizing horizontally and vertically.
* `horizontal`: Allows resizing only horizontally.
* `vertical`: Allows resizing only vertically.
* `none`: Allows no resizing.
* `block` and `inline`: Experimental values that allow resizing in the `block` or `inline` direction only (this varies depending on the directionality of your text; read Handling different text directions if you want to find out more.)

Play with the interactive example at the top of the `resize` reference page for a demonstration of how these work.

Drop-down controls
------------------

Drop-down controls are a simple way to let users select from many options without taking up much space in the user interface. HTML has two types of drop-down controls: the **select box** and the **autocomplete box**. The interaction is the same in both the types of drop-down controls — after the control is activated, the browser displays a list of values the user can select from.

**Note:** You can find examples of all the drop-down box types on GitHub at drop-down-content.html (see it live also).

### Select box

A simple select box is created with a `<select>` element with one or more `<option>` elements as its children, each of which specifies one of its possible values.

#### Basic example

```html
<select id="simple" name="simple">
  <option>Banana</option>
  <option selected>Cherry</option>
  <option>Lemon</option>
</select>
```

If required, the default value for the select box can be set using the `selected` attribute on the desired `<option>` element — this option is then preselected when the page loads.

#### Using optgroup

The `<option>` elements can be nested inside `<optgroup>` elements to create visually associated groups of values:

```html
<select id="groups" name="groups">
  <optgroup label="fruits">
    <option>Banana</option>
    <option selected>Cherry</option>
    <option>Lemon</option>
  </optgroup>
  <optgroup label="vegetables">
    <option>Carrot</option>
    <option>Eggplant</option>
    <option>Potato</option>
  </optgroup>
</select>
```

On the `<optgroup>` element, the value of the `label` attribute is displayed before the values of the nested options. The browser usually sets them visually apart from the options (i.e. by being bolded and at a different nesting level) so they are less likely to be confused for actual options.

#### Using the value attribute

If an `<option>` element has an explicit `value` attribute set on it, that value is sent when the form is submitted with that option selected. If the `value` attribute is omitted, as with the examples above, the content of the `<option>` element is used as the value. So `value` attributes are not needed, but you might find a reason to want to send a shortened or different value to the server than what is visually shown in the select box.

For example:

```html
<select id="simple" name="simple">
  <option value="banana">Big, beautiful yellow banana</option>
  <option value="cherry">Succulent, juicy cherry</option>
  <option value="lemon">Sharp, powerful lemon</option>
</select>
```

By default, the height of the select box is enough to display a single value. The optional `size` attribute provides control over how many options are visible when the select does not have focus.

### Multiple choice select box

By default, a select box lets a user select only one value. By adding the `multiple` attribute to the `<select>` element, you can allow users to select several values. Users can select multiple values by using the default mechanism provided by the operating system (e.g., on the desktop, multiple values can be clicked while holding down `Cmd`/`Ctrl` keys).

```html
<select id="multi" name="multi" multiple size="2">
  <optgroup label="fruits">
    <option>Banana</option>
    <option selected>Cherry</option>
    <option>Lemon</option>
  </optgroup>
  <optgroup label="vegetables">
    <option>Carrot</option>
    <option>Eggplant</option>
    <option>Potato</option>
  </optgroup>
</select>
```

**Note:** In the case of multiple choice select boxes, you'll notice that the select box no longer displays the values as drop-down content — instead, all values are displayed at once in a list, with the optional `size` attribute determining the height of the widget.

**Note:** All browsers that support the `<select>` element also support the `multiple` attribute.

### Autocomplete box

You can provide suggested, automatically-completed values for form widgets using the `<datalist>` element with child `<option>` elements to specify the values to display. The `<datalist>` needs to be given an `id`.

The data list is then bound to an `<input>` element (e.g. a `text` or `email` input type) using the `list` attribute, the value of which is the `id` of the data list to bind.

Once a data list is affiliated with a form widget, its options are used to auto-complete text entered by the user; typically, this is presented to the user as a drop-down box listing possible matches for what they've typed into the input.

#### Basic example

Let's look at an example.

```html
<label for="myFruit">What's your favorite fruit?</label>
<input type="text" name="myFruit" id="myFruit" list="mySuggestion" />
<datalist id="mySuggestion">
  <option>Apple</option>
  <option>Banana</option>
  <option>Blackberry</option>
  <option>Blueberry</option>
  <option>Lemon</option>
  <option>Lychee</option>
  <option>Peach</option>
  <option>Pear</option>
</datalist>
```

#### Datalist support and fallbacks

Almost all browsers support datalist, but if you are still supporting older browsers such as IE versions below 10, there is a trick to provide a fallback:

```html
<label for="myFruit">What is your favorite fruit? (With fallback)</label>
<input type="text" id="myFruit" name="fruit" list="fruitList" />

<datalist id="fruitList">
  <label for="suggestion">or pick a fruit</label>
  <select id="suggestion" name="altFruit">
    <option>Apple</option>
    <option>Banana</option>
    <option>Blackberry</option>
    <option>Blueberry</option>
    <option>Lemon</option>
    <option>Lychee</option>
    <option>Peach</option>
    <option>Pear</option>
  </select>
</datalist>
```

Browsers that support the `<datalist>` element will ignore all the elements that are not `<option>` elements, with the datalist working as expected. Old browsers that don't support the `<datalist>` element will display the label and the select box.

The following screenshot shows the datalist fallback as rendered in Safari 6:

![Screenshot of the datalist element fallback with Safari on Mac OS](/en-US/docs/Learn/Forms/Other_form_controls/datalist-safari.png)

If you use this fallback, ensure the data for both the `<input>` and the `<select>` are collected server-side.

#### Less obvious datalist uses

According to the HTML specification, the `list` attribute and the `<datalist>` element can be used with any kind of widget requiring a user input. This leads to some uses of it that might seem a little non-obvious.

For example, in browsers that support ``<datalist>`` on `range` input types, a small tick mark will be displayed above the range for each datalist ``<option>`` value. You can see an implementation example of this on the `<input type="range">` reference page.

And browsers that support `<datalist>`s and `<input type="color">` should display a customized palette of colors as the default, while still making the full color palette available.

In this case, different browsers behave differently from case to case, so consider such uses as progressive enhancement, and ensure they degrade gracefully.

Other form features
-------------------

There are a few other form features that are not as obvious as the ones we have already mentioned, but still useful in some situations, so we thought it would be worth giving them a brief mention.

**Note:** You can find the examples from this section on GitHub as other-examples.html (see it live also).

### Meters and progress bars

Meters and progress bars are visual representations of numeric values. Support for `<progress>` and `<meter>` is available in all modern browsers.

#### Meter

A meter bar represents a fixed value in a range delimited by `max` and `min` values. This value is visually rendered as a bar, and to know how this bar looks, we compare the value to some other set values:

* The `low` and `high` values divide the range into the following three parts:
    + The lower part of the range is between the `min` and `low` values, inclusive.
    + The medium part of the range is between the `low` and `high` values, exclusive.
    + The higher part of the range is between the `high` and `max` values, inclusive.
* The `optimum` value defines the optimum value for the `<meter>` element. In conjunction with the `low` and `high` value, it defines which part of the range is preferred:
    + If the `optimum` value is in the lower part of the range, the lower range is considered to be the preferred part, the medium range is considered to be the average part, and the higher range is considered to be the worst part.
    + If the `optimum` value is in the medium part of the range, the lower range is considered to be an average part, the medium range is considered to be the preferred part, and the higher range is considered to be average as well.
    + If the `optimum` value is in the higher part of the range, the lower range is considered to be the worst part, the medium range is considered to be the average part and the higher range is considered to be the preferred part.

All browsers that implement the `<meter>` element use those values to change the color of the meter bar:

* If the current value is in the preferred part of the range, the bar is green.
* If the current value is in the average part of the range, the bar is yellow.
* If the current value is in the worst part of the range, the bar is red.

Such a bar is created by using the `<meter>` element. This is for implementing any kind of meter; for example, a bar showing the total space used on a disk, which turns red when it starts to get full.

```html
<meter min="0" max="100" value="75" low="33" high="66" optimum="0">75</meter>
```

The content inside the `<meter>` element is a fallback for browsers that don't support the element and for assistive technologies to vocalize it.

#### Progress

A progress bar represents a value that changes over time up to a maximum value specified by the `max` attribute. Such a bar is created using a `<progress>` element.

```html
<progress max="100" value="75">75/100</progress>
```

This is for implementing anything requiring progress reporting, such as the percentage of total files downloaded, or the number of questions filled in on a questionnaire.

The content inside the `<progress>` element is a fallback for browsers that don't support the element and for screen readers to vocalize it.

Test your skills!
-----------------

You've reached the end of this article, but can you remember the most important information? You can find some further tests to verify that you've retained this information before you move on — see Test your skills: Other controls.

Summary
-------

As you'll have seen in the last few articles, there are many types of form control. You don't need to remember all of these details at once, and can return to these articles as often as you like to check up on details.

Now that you have a grasp of the HTML behind the different available form controls, we'll take a look at Styling them.

* Previous
* Overview: Forms
* Next
### Advanced Topics

* How to build custom form controls
* Sending forms through JavaScript
* Property compatibility table for form widgets


Test your skills: Basic controls - Learn web development

Test your skills: Basic controls
================================

The aim of this skill test is to assess whether you've understood our Basic native form controls article.

**Note:** You can try solutions in the interactive editors on this page or in an online editor such as CodePen, JSFiddle, or Glitch.

If you get stuck, you can reach out to us in one of our communication channels.

Basic controls 1
----------------

This task starts you off nice and gently by asking you to create two `<input>` elements, for a user's ID and password, along with a submit button.

1. Create appropriate inputs for user ID and password.
2. You should also associate them with their text labels semantically.
3. Create a submit button inside the remaining list item, with button text of "Log in".

Try updating the live code below to recreate the finished example:

Download the starting point for this task to work in your own editor or in an online editor.

Basic controls 2
----------------

The next task requires you to create working sets of checkboxes and radio buttons, from the provided text labels.

1. Turn the first `<fieldset>`'s contents into a set of radio buttons — you should only be able to select one pony character at once.
2. Make it so that the first radio button is selected upon page load.
3. Turn the second `<fieldset>`'s content into a set of checkboxes.
4. Add a couple more hotdog choices of your own.

Try updating the live code below to recreate the finished example:

Download the starting point for this task to work in your own editor or in an online editor.

Basic controls 3
----------------

The final task in this set requires you to create a file picker.

1. Create a basic file picker.
2. Allow the user to pick multiple files at once.
3. Allow the file picker to accept JPG and PNG images only.

Try updating the live code below to recreate the finished example:

Download the starting point for this task to work in your own editor or in an online editor.


Test your skills: Form structure - Learn web development

Test your skills: Form structure
================================

The aim of this skill test is to assess whether you've understood our How to structure a web form article.

**Note:** You can try solutions in the interactive editors on this page or in an online editor such as CodePen, JSFiddle, or Glitch.

If you get stuck, you can reach out to us in one of our communication channels.

Form structure 1
----------------

In this task we want you to structure the provided form features:

1. Separate out the first two and second two form fields into two distinct containers, each with a descriptive legend (use "Personal details" for the first two, and "Comment information" for the second two).
2. Mark up each text label with an appropriate element so that it is semantically associated with its respective form field.
3. Add a suitable set of structural elements around the label/field pairs to separate them out.

Download the starting point for this task to work in your own editor or in an online editor.


Sending form data - Learn web development

Sending form data
=================

* Previous
* Overview: Forms

Once the form data has been validated on the client-side, it is okay to submit the form. And, since we covered validation in the previous article, we're ready to submit! This article looks at what happens when a user submits a form — where does the data go, and how do we handle it when it gets there? We also look at some of the security concerns associated with sending form data.

|  |  |
| --- | --- |
| Prerequisites: |
 An
 understanding of HTML, and basic knowledge of
 HTTP and
 server-side programming.
  |
| Objective: |
 To understand what happens when form data is submitted, including
 getting a basic idea of how data is processed on the server.
  |

First, we'll discuss what happens to the data when a form is submitted.

Client/server architecture
--------------------------

At its most basic, the web uses a client/server architecture that can be summarized as follows: a client (usually a web browser) sends a request to a server (most of the time a web server like Apache, Nginx, IIS, Tomcat, etc.), using the HTTP protocol. The server answers the request using the same protocol.

![A basic schema of the Web client/server architecture](/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data/client-server.png)

An HTML form on a web page is nothing more than a convenient user-friendly way to configure an HTTP request to send data to a server. This enables the user to provide information to be delivered in the HTTP request.

**Note:** To get a better idea of how client-server architectures work, read our Server-side website programming first steps module.

On the client side: defining how to send the data
-------------------------------------------------

The `<form>` element defines how the data will be sent. All of its attributes are designed to let you configure the request to be sent when a user hits a submit button. The two most important attributes are `action` and `method`.

### The action attribute

The `action` attribute defines where the data gets sent. Its value must be a valid relative or absolute URL. If this attribute isn't provided, the data will be sent to the URL of the page containing the form — the current page.

In this example, the data is sent to an absolute URL — `https://example.com`:

```html
<form action="https://example.com">…</form>
```

Here, we use a relative URL — the data is sent to a different URL on the same origin:

```html
<form action="/somewhere\_else">…</form>
```

When specified with no attributes, as below, the `<form>` data is sent to the same page that the form is present on:

```html
<form>…</form>
```

**Note:** It's possible to specify a URL that uses the HTTPS (secure HTTP) protocol. When you do this, the data is encrypted along with the rest of the request, even if the form itself is hosted on an insecure page accessed using HTTP. On the other hand, if the form is hosted on a secure page but you specify an insecure HTTP URL with the `action` attribute, all browsers display a security warning to the user each time they try to send data because the data will not be encrypted.

The names and values of the non-file form controls are sent to the server as `name=value` pairs joined with ampersands. The `action` value should be a file on the server that can handle the incoming data, including ensuring server-side validation. The server then responds, generally handling the data and loading the URL defined by the `action` attribute, causing a new page load (or a refresh of the existing page, if the `action` points to the same page).

How the data is sent depends on the `method` attribute.

### The method attribute

The `method` attribute defines how data is sent. The HTTP protocol provides several ways to perform a request; HTML form data can be transmitted via a number of different methods, the most common being the `GET` method and the `POST` method

To understand the difference between those two methods, let's step back and examine how HTTP works. Each time you want to reach a resource on the Web, the browser sends a request to a URL. An HTTP request consists of two parts: a header that contains a set of global metadata about the browser's capabilities, and a body that can contain information necessary for the server to process the specific request.

#### The GET method

The `GET` method is the method used by the browser to ask the server to send back a given resource: "Hey server, I want to get this resource." In this case, the browser sends an empty body. Because the body is empty, if a form is sent using this method the data sent to the server is appended to the URL.

Consider the following form:

```html
<form action="http://www.foo.com" method="GET">
  <div>
    <label for="say">What greeting do you want to say?</label>
    <input name="say" id="say" value="Hi" />
  </div>
  <div>
    <label for="to">Who do you want to say it to?</label>
    <input name="to" id="to" value="Mom" />
  </div>
  <div>
    <button>Send my greetings</button>
  </div>
</form>
```

Since the `GET` method has been used, you'll see the URL `www.foo.com/?say=Hi&to=Mom` appear in the browser address bar when you submit the form.

![The changed url with query parameters after submitting the form with GET method with a "server not found" browser error page](/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data/url-parameters.png)

The data is appended to the URL as a series of name/value pairs. After the URL web address has ended, we include a question mark (`?`) followed by the name/value pairs, each one separated by an ampersand (`&`). In this case, we are passing two pieces of data to the server:

* `say`, which has a value of `Hi`
* `to`, which has a value of `Mom`

The HTTP request looks like this:

```http
GET /?say=Hi&to=Mom HTTP/2.0
Host: foo.com
```

**Note:** You can find this example on GitHub — see get-method.html (see it live also).

#### The POST method

The `POST` method is a little different. It's the method the browser uses to talk to the server when asking for a response that takes into account the data provided in the body of the HTTP request: "Hey server, take a look at this data and send me back an appropriate result." If a form is sent using this method, the data is appended to the body of the HTTP request.

Let's look at an example — this is the same form we looked at in the `GET` section above, but with the `method` attribute set to `POST`.

```html
<form action="http://www.foo.com" method="POST">
  <div>
    <label for="say">What greeting do you want to say?</label>
    <input name="say" id="say" value="Hi" />
  </div>
  <div>
    <label for="to">Who do you want to say it to?</label>
    <input name="to" id="to" value="Mom" />
  </div>
  <div>
    <button>Send my greetings</button>
  </div>
</form>
```

When the form is submitted using the `POST` method, you get no data appended to the URL, and the HTTP request looks like so, with the data included in the request body instead:

```http
POST / HTTP/2.0
Host: foo.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 13

say=Hi&to=Mom
```

The `Content-Length` header indicates the size of the body, and the `Content-Type` header indicates the type of resource sent to the server. We'll discuss these headers later on.

**Note:** You can find this example on GitHub — see post-method.html (see it live also).

### Viewing HTTP requests

HTTP requests are never displayed to the user (if you want to see them, you need to use tools such as the Firefox Network Monitor or the Chrome Developer Tools). As an example, your form data will be shown as follows in the Chrome Network tab. After submitting the form:

1. Open the developer tools.
2. Select "Network"
3. Select "All"
4. Select "foo.com" in the "Name" tab
5. Select "Headers"

You can then get the form data, as shown in the image below.

![HTTP requests and response data in network monitoring tab in browser's developer tools](/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data/network-monitor.png)

The only thing displayed to the user is the URL called. As we mentioned above, with a `GET` request the user will see the data in their URL bar, but with a `POST` request they won't. This can be very important for two reasons:

1. If you need to send a password (or any other sensitive piece of data), never use the `GET` method or you risk displaying it in the URL bar, which would be very insecure.
2. If you need to send a large amount of data, the `POST` method is preferred because some browsers limit the sizes of URLs. In addition, many servers limit the length of URLs they accept.
On the server side: retrieving the data
---------------------------------------

Whichever HTTP method you choose, the server receives a string that will be parsed in order to get the data as a list of key/value pairs. The way you access this list depends on the development platform you use and on any specific frameworks you may be using with it.

### Example: Raw PHP

PHP offers some global objects to access the data. Assuming you've used the `POST` method, the following example just takes the data and displays it to the user. Of course, what you do with the data is up to you. You might display it, store it in a database, send it by email, or process it in some other way.

```php
<?php
 // The global $\_POST variable allows you to access the data sent with the POST method by name
 // To access the data sent with the GET method, you can use $\_GET
 $say = htmlspecialchars($\_POST['say']);
 $to = htmlspecialchars($\_POST['to']);

 echo $say, ' ', $to;
?>
```

This example displays a page with the data we sent. You can see this in action in our example php-example.html file — which contains the same example form as we saw before, with a `method` of `POST` and an `action` of `php-example.php`. When it is submitted, it sends the form data to php-example.php, which contains the PHP code seen in the above block. When this code is executed, the output in the browser is `Hi Mom`.

![Otherwise blank web page with "hi mom", the data received in response after submitting form data to a php file with POST method](/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data/php-result.png)

**Note:** This example won't work when you load it into a browser locally — browsers cannot interpret PHP code, so when the form is submitted the browser will just offer to download the PHP file for you. To get it to work, you need to run the example through a PHP server of some kind. Good options for local PHP testing are MAMP (Mac and Windows) and AMPPS (Mac, Windows, Linux).

Note also that if you are using MAMP but don't have MAMP Pro installed (or if the MAMP Pro demo time trial has expired), you might have trouble getting it working. To get it working again, we have found that you can load up the MAMP app, then choose the menu options *MAMP* > *Preferences* > *PHP*, and set "Standard Version:" to "7.2.x" (x will differ depending on what version you have installed).

### Example: Python

This example shows how you would use Python to do the same thing — display the submitted data on a web page. This uses the Flask framework for rendering the templates, handling the form data submission, etc. (see python-example.py).

```python
from flask import Flask, render_template, request

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def form():
    return render_template('form.html')

@app.route('/hello', methods=['GET', 'POST'])
def hello():
    return render_template('greeting.html', say=request.form['say'], to=request.form['to'])

if __name__ == "\_\_main\_\_":
    app.run()
```

The two templates referenced in the above code are as follows (these need to be in a subdirectory called `templates` in the same directory as the `python-example.py` file, if you try to run the example yourself):

* form.html: The same form as we saw above in The POST method section but with the `action` set to `{{ url_for('hello') }}`. This is a Jinja template, which is basically HTML but can contain calls to the Python code that is running the web server contained in curly braces. `url_for('hello')` is basically saying "redirect to `/hello` when the form is submitted".
* greeting.html: This template just contains a line that renders the two bits of data passed to it when it is rendered. This is done via the `hello()` function seen above, which runs when the `/hello` URL is navigated to.

**Note:** Again, this code won't work if you just try to load it into a browser directly. Python works a bit differently from PHP — to run this code locally you'll need to install Python/PIP, then install Flask using `pip3 install flask`. At this point, you should be able to run the example using `python3 python-example.py`, then navigate to `localhost:5042` in your browser.

### Other languages and frameworks

There are many other server-side technologies you can use for form handling, including Perl, Java, .Net, Ruby, etc. Just pick the one you like best. That said, it's worth noting that it's very uncommon to use these technologies directly because this can be tricky. It's more common to use one of the many high quality frameworks that make handling forms easier, such as:

* Python
    + Django
    + Flask
    + web2py (easiest to get started with)
    + py4web (written by the same develops as web2py, has a more Django-like setup)
* Node.js
    + Express
    + Next.js (for React apps)
    + Nuxt (for Vue apps)
    + Remix
* PHP
    + Laravel
    + Laminas (formerly Zend Framework)
    + Symfony
* Ruby
    + Ruby On Rails
* Java
    + Spring Boot

It's worth noting that even using these frameworks, working with forms isn't necessarily *easy*. But it's much easier than trying to write all the functionality yourself from scratch, and will save you a lot of time.

**Note:** It is beyond the scope of this article to teach you any server-side languages or frameworks. The links above will give you some help, should you wish to learn them.

A special case: sending files
-----------------------------

Sending files with HTML forms is a special case. Files are binary data — or considered as such — whereas all other data is text data. Because HTTP is a text protocol, there are special requirements for handling binary data.

### The enctype attribute

This attribute lets you specify the value of the `Content-Type` HTTP header included in the request generated when the form is submitted. This header is very important because it tells the server what kind of data is being sent. By default, its value is `application/x-www-form-urlencoded`. In human terms, this means: "This is form data that has been encoded into URL parameters."

If you want to send files, you need to take three extra steps:

* Set the `method` attribute to `POST` because file content can't be put inside URL parameters.
* Set the value of `enctype` to `multipart/form-data` because the data will be split into multiple parts, one for each file plus one for the text data included in the form body (if the text is also entered into the form).
* Include one or more `<input type="file">` controls to allow your users to select the file(s) that will be uploaded.

For example:

```html
<form method="post" action="https://www.foo.com" enctype="multipart/form-data">
  <div>
    <label for="file">Choose a file</label>
    <input type="file" id="file" name="myFile" />
  </div>
  <div>
    <button>Send the file</button>
  </div>
</form>
```

**Note:** Servers can be configured with a size limit for files and HTTP requests in order to prevent abuse.

Security issues
---------------

Each time you send data to a server, you need to consider security. HTML forms are by far the most common server attack vectors (places where attacks can occur). The problems never come from the HTML forms themselves — they come from how the server handles data.

The Website security article of our server-side learning topic discusses several common attacks and potential defenses against them in detail. You should go and check that article out, to get an idea of what's possible.

### Be paranoid: Never trust your users

So, how do you fight these threats? This is a topic far beyond this guide, but there are a few rules to keep in mind. The most important rule is: never ever trust your users, including yourself; even a trusted user could have been hijacked.

All data that comes to your server must be checked and sanitized. Always. No exception.

* **Escape potentially dangerous characters**. The specific characters you should be cautious with vary depending on the context in which the data is used and the server platform you employ, but all server-side languages have functions for this. Things to watch out for are character sequences that look like executable code (such as JavaScript or SQL commands).
* **Limit the incoming amount of data to allow only what's necessary**.
* **Sandbox uploaded files**. Store them on a different server and allow access to the file only through a different subdomain or even better through a completely different domain.

You should be able to avoid many/most problems if you follow these three rules, but it's always a good idea to get a security review performed by a competent third party. Don't assume that you've seen all the possible problems.

Summary
-------

As we'd alluded to above, sending form data is easy, but securing an application can be tricky. Just remember that a front-end developer is not the one who should define the security model of the data. It's possible to perform client-side form validation, but the server can't trust this validation because it has no way to truly know what has really happened on the client-side.

If you've worked your way through these tutorials in order, you now know how to markup and style a form, do client-side validation, and have some idea about submitting a form.

See also
--------

If you want to learn more about securing a web application, you can dig into these resources:

* Server-side website programming first steps
* The Open Web Application Security Project (OWASP)
* Web Security by Mozilla
* Previous
* Overview: Forms
### Advanced Topics

* How to build custom form controls
* Sending forms through JavaScript
* Property compatibility table for form widgets


The HTML5 input types - Learn web development

The HTML5 input types
=====================

* Previous
* Overview: Forms
* Next

In the previous article we looked at the `<input>` element, covering the original values of the `type` attribute available since the early days of HTML. Now we'll look at the functionality of newer form controls in detail, including some new input types, which were added in HTML5 to allow the collection of specific types of data.

|  |  |
| --- | --- |
| Prerequisites: |
 A basic
 understanding of HTML.
  |
| Objective: |
 To understand the newer input type values available to create native
 form controls, and how to implement them using HTML.
  |

**Note:** Most of the features discussed in this article have wide support across browsers. We'll note any exceptions. If you want more detail on browser support, you should consult our HTML forms element reference, and in particular our extensive <input> types reference.

Because HTML form control appearance may be quite different from a designer's specifications, web developers sometimes build their own custom form controls. We cover this in an advanced tutorial: How to build custom form widgets.

Email address field
-------------------

This type of field is set using the value `email` for the `type` attribute:

```html
<input type="email" id="email" name="email" />
```

When this `type` is used, the user is required to type a valid email address into the field. Any other content causes the browser to display an error when the form is submitted. You can see this in action in the below screenshot.

![An invalid email input showing the message "Please enter an email address."](/en-US/docs/Learn/Forms/HTML5_input_types/email_address_invalid.png)

You can also use the `multiple` attribute in combination with the `email` input type to allow several email addresses to be entered in the same input (separated by commas):

```html
<input type="email" id="email" name="email" multiple />
```

On some devices — notably, touch devices with dynamic keyboards like smartphones — a different virtual keypad might be presented that is more suitable for entering email addresses, including the `@` key. See the Firefox for Android keyboard screenshot below for an example:

![Firefox for Android email keyboard, with the at sign displayed by default.](/en-US/docs/Learn/Forms/HTML5_input_types/fx-android-email-type-keyboard.jpg)

**Note:** You can find examples of the basic text input types at basic input examples (see the source code also).

This is another good reason for using these newer input types, improving the user experience for users of these devices.

### Client-side validation

As you can see above, `email` — along with other newer `input` types — provides built-in *client-side* error validation, performed by the browser before the data gets sent to the server. It *is* a helpful aid to guide users to fill out a form accurately, and it can save time: it is useful to know that your data is not correct immediately, rather than having to wait for a round trip to the server.

But it *should not be considered* an exhaustive security measure! Your apps should always perform security checks on any form-submitted data on the *server-side* as well as the client-side, because client-side validation is too easy to turn off, so malicious users can still easily send bad data through to your server. Read Website security for an idea of what *could* happen; implementing server-side validation is somewhat beyond the scope of this module, but you should bear it in mind.

Note that `a@b` is a valid email address according to the default provided constraints. This is because the `email` input type allows intranet email addresses by default. To implement different validation behavior, you can use the `pattern` attribute, and you can also customize the error messages; we'll talk about how to use these features in the Client-side form validation article later on.

**Note:** If the data entered is not an email address, the `:invalid` pseudo-class will match, and the `validityState.typeMismatch` property will return `true`.

Search field
------------

Search fields are intended to be used to create search boxes on pages and apps. This type of field is set by using the value `search` for the `type` attribute:

```html
<input type="search" id="search" name="search" />
```

The main difference between a `text` field and a `search` field is how the browser styles its appearance. Often, `search` fields are rendered with rounded corners; they also sometimes display an "Ⓧ", which clears the field of any value when clicked. Additionally, on devices with dynamic keyboards, the keyboard's enter key may read "**search**", or display a magnifying glass icon.

The below screenshots show a non-empty search field in Firefox 71, Safari 13, and Chrome 79 on macOS, and Edge 18 and Chrome 79 on Windows 10. Note that the clear icon only appears if the field has a value, and, apart from Safari, it is only displayed when the field is focused.

![Screenshots of search fields on several platforms.](/en-US/docs/Learn/Forms/HTML5_input_types/search_focus.png)

Another worth-noting feature is that the values of a `search` field can be automatically saved and re-used to offer auto-completion across multiple pages of the same website; this tends to happen automatically in most modern browsers.

Phone number field
------------------

A special field for filling in phone numbers can be created using `tel` as the value of the `type` attribute:

```html
<input type="tel" id="tel" name="tel" />
```

When accessed via a touch device with a dynamic keyboard, most devices will display a numeric keypad when `type="tel"` is encountered, meaning this type is useful whenever a numeric keypad is useful, and doesn't just have to be used for telephone numbers.

The following Firefox for Android keyboard screenshot provides an example:

![Firefox for Android email keyboard, with ampersand displayed by default.](/en-US/docs/Learn/Forms/HTML5_input_types/fx-android-tel-type-keyboard.jpg)

Due to the wide variety of phone number formats around the world, this type of field does not enforce any constraints on the value entered by a user (this means it may include letters, etc.).

As we mentioned earlier, the `pattern` attribute can be used to enforce constraints, which you'll learn about in Client-side form validation.

URL field
---------

A special type of field for entering URLs can be created using the value `url` for the `type` attribute:

```html
<input type="url" id="url" name="url" />
```

It adds special validation constraints to the field. The browser will report an error if no protocol (such as `http:`) is entered, or if the URL is otherwise malformed. On devices with dynamic keyboards, the default keyboard will often display some or all of the colon, period, and forward slash as default keys.

See below for an example (taken on Firefox for Android):

![Firefox for Android email keyboard, with ampersand displayed by default.](/en-US/docs/Learn/Forms/HTML5_input_types/fx-android-url-type-keyboard.jpg)

**Note:** Just because the URL is well-formed doesn't necessarily mean that it refers to a location that actually exists!

Numeric field
-------------

Controls for entering numbers can be created with an `<input>` `type` of `number`. This control looks like a text field but allows only floating-point numbers, and usually provides buttons in the form of a spinner to increase and decrease the value of the control. On devices with dynamic keyboards, the numeric keyboard is generally displayed.

The following screenshot (from Firefox for Android) provides an example:

![Firefox for Android email keyboard, with ampersand displayed by default.](/en-US/docs/Learn/Forms/HTML5_input_types/fx-android-number-type-keyboard.jpg)

With the `number` input type, you can constrain the minimum and maximum values allowed by setting the `min` and `max` attributes.

You can also use the `step` attribute to set the increment increase and decrease caused by pressing the spinner buttons. By default, the number input type only validates if the number is an integer. To allow float numbers, specify `step="any"`. If omitted, the `step` value defaults to `1`, meaning only whole numbers are valid.

Let's look at some examples. The first one below creates a number control whose value is restricted to any value between `1` and `10`, and whose increase and decrease buttons change its value by `2`.

```html
<input type="number" name="age" id="age" min="1" max="10" step="2" />
```

The second one creates a number control whose value is restricted to any value between `0` and `1` inclusive, and whose increase and decrease buttons change its value by `0.01`.

```html
<input type="number" name="change" id="pennies" min="0" max="1" step="0.01" />
```

The `number` input type makes sense when the range of valid values is limited, for example a person's age or height. If the range is too large for incremental increases to make sense (such as USA ZIP codes, which range from `00001` to `99999`), the `tel` type might be a better option; it provides the numeric keypad while forgoing the number's spinner UI feature.

Slider controls
---------------

Another way to pick a number is to use a **slider**. You see these quite often on sites like house-buying sites where you want to set a maximum property price to filter by. Let's look at a live example to illustrate this:

Usage-wise, sliders are less accurate than text fields. Therefore, they are used to pick a number whose *precise* value is not necessarily important.

A slider is created using the `<input>` with its `type` attribute set to the value `range`. The slider-thumb can be moved via mouse or touch, or with the arrows of the keypad.

It's important to properly configure your slider. To that end, it's highly recommended that you set the `min`, `max`, and `step` attributes which set the minimum, maximum, and increment values, respectively.

Let's look at the code behind the above example, so you can see how it's done. First of all, the basic HTML:

```html
<label for="price">Choose a maximum house price: </label>
<input
 type="range"
 name="price"
 id="price"
 min="50000"
 max="500000"
 step="100"
 value="250000" />
<output class="price-output" for="price"></output>
```

This example creates a slider whose value may range between `50000` and `500000`, which increments/decrements by 100 at a time. We've given it a default value of `250000`, using the `value` attribute.

One problem with sliders is that they don't offer any kind of visual feedback as to what the current value is. This is why we've included an `<output>` element to contain the current value. You could display an input value or the output of a calculation inside any element, but `<output>` is special — like `<label>` — and it can take a `for` attribute that allows you to associate it with the element or elements that the output value came from.

To actually display the current value, and update it as it changed, you must use JavaScript, but this is relatively easy to do:

```js
const price = document.querySelector("#price");
const output = document.querySelector(".price-output");

output.textContent = price.value;

price.addEventListener("input", () => {
  output.textContent = price.value;
});
```

Here we store references to the `range` input and the `output` in two variables. Then we immediately set the `output`'s `textContent` to the current `value` of the input. Finally, an event listener is set to ensure that whenever the range slider is moved, the `output`'s `textContent` is updated to the new value.

**Note:** There is a nice tutorial covering this subject on CSS Tricks: The Output Element.

Date and time pickers
---------------------

Gathering date and time values has traditionally been a nightmare for web developers. For a good user experience, it is important to provide a calendar selection UI, enabling users to select dates without necessitating context switching to a native calendar application or potentially entering them in differing formats that are hard to parse. The last minute of the previous millennium can be expressed in the following different ways, for example: 1999/12/31, 23:59 or 12/31/99T11:59PM.

HTML date controls are available to handle this specific kind of data, providing calendar widgets and making the data uniform.

A date and time control is created using the `<input>` element and an appropriate value for the `type` attribute, depending on whether you wish to collect dates, times, or both. Here's a live example that falls back to `<select>` elements in non-supporting browsers:

Let's look at the different available types in brief. Note that the usage of these types is quite complex, especially considering browser support (see below); to find out the full details, follow the links below to the reference pages for each type, including detailed examples.

### `datetime-local`

`<input type="datetime-local">` creates a widget to display and pick a date with time with no specific time zone information.

```html
<input type="datetime-local" name="datetime" id="datetime" />
```

### `month`

`<input type="month">` creates a widget to display and pick a month with a year.

```html
<input type="month" name="month" id="month" />
```

### `time`

`<input type="time">` creates a widget to display and pick a time value. While time may *display* in 12-hour format, the *value returned* is in 24-hour format.

```html
<input type="time" name="time" id="time" />
```

### `week`

`<input type="week">` creates a widget to display and pick a week number and its year.

Weeks start on Monday and run to Sunday. Additionally, the first week 1 of each year contains the first Thursday of that year — which may not include the first day of the year, or may include the last few days of the previous year.

```html
<input type="week" name="week" id="week" />
```

### Constraining date/time values

All date and time controls can be constrained using the `min` and `max` attributes, with further constraining possible via the `step` attribute (whose value varies according to input type).

```html
<label for="myDate">When are you available this summer?</label>
<input
 type="date"
 name="myDate"
 min="2013-06-01"
 max="2013-08-31"
 step="7"
 id="myDate" />
```

Color picker control
--------------------

Colors are always a bit difficult to handle. There are many ways to express them: RGB values (decimal or hexadecimal), HSL values, keywords, and so on.

A `color` control can be created using the `<input>` element with its `type` attribute set to the value `color`:

```html
<input type="color" name="color" id="color" />
```

Clicking a color control generally displays the operating system's default color-picking functionality for you to choose.

Here is a live example for you to try out:

The value returned is always a lowercase 6-value hexadecimal color.

Test your skills!
-----------------

You've reached the end of this article, but can you remember the most important information? You can find some further tests to verify that you've retained this information before you move on — see Test your skills: HTML5 controls.

Summary
-------

That brings us to the end of our tour of the HTML5 form input types. There are a few other control types that cannot be easily grouped together due to their very specific behaviors, but which are still essential to know about. We cover those in the next article.

* Previous
* Overview: Forms
* Next
### Advanced Topics

* How to build custom form controls
* Sending forms through JavaScript
* Property compatibility table for form widgets


Test your skills: Other controls - Learn web development

Test your skills: Other controls
================================

The aim of this skill test is to assess whether you've understood our Other form controls article.

**Note:** You can try solutions in the interactive editors on this page or in an online editor such as CodePen, JSFiddle, or Glitch.

If you get stuck, you can reach out to us in one of our communication channels.

Other controls 1
----------------

In our first "other controls" assessment, we'll get you to create a multi-line text input.

1. Create a basic multi-line text input.
2. Associate it semantically with the provided "Comment" label.
3. Give the input 35 columns, and 10 rows of space in which to add comments.
4. Give the comments a maximum length of 100 characters.

To create the input, update the HTML code in the editor below:

Download the starting point for this task to work in your own editor or in an online editor.

Other controls 2
----------------

Now it's time to have a go at implementing a drop-down select menu, to allow a user to pick their favorite food from the choices provided.

1. Create your basic select box structure.
2. Associate it semantically with the provided "food" label.
3. Inside the list, split the choices up into 2 subgroups — "mains" and "snacks".

To create the menu, update the HTML code in the editor below:

Download the starting point for this task to work in your own editor or in an online editor.

Other controls 3
----------------

In our final task of this set, we start with much the same list of food choices. However, this time we want to do things differently:

1. Create a basic text input that is semantically associated with the provided label.
2. Put the food choices into a list that can be associated with a form input.
3. Associate the list with your text input, so that when you type characters, any of the list options that match the character sequence are given in a dropdown list as autocomplete suggestions.

To create the input, update the HTML code in the editor below:

Download the starting point for this task to work in your own editor or in an online editor.


User input methods and controls - Learn web development

User input methods and controls
===============================

Web forms require user input. When designing web forms, or really any web content, it's important to consider how users interact with their devices and browsers. Web user input goes beyond simple mouse and keyboard: think of touchscreens for example.

In this article, we take a look at the different ways users interact with forms and other web content and provide recommendations for managing user input, real-world examples, and links to further information.

As you develop more complex and interactive forms or other UI features, there are many HTML elements and JavaScript APIs you may want to investigate. For example, you may want to create custom form controls that require non-semantic elements to be content editable. You might want to support touch events, determine or control the screen's orientation, make a form take up the full screen, or enable drag and drop features. This guide introduces all these features, and directs you to more information on each topic.

To provide a good experience to the greatest number of users, you need to support multiple input methods, including mouse, keyboard, finger touch, and so on. Available input mechanisms depend on the capabilities of the device running the application.

You should always be mindful of keyboard accessibility — many web users only use the keyboard to navigate websites and apps, and locking them out of your functionality is a bad idea.

Topics covered
--------------

* To support touch screen displays, touch events interpret finger activity on touch-based user interfaces from mobile devices, to refrigerator panels, to museum kiosk displays.
* The Fullscreen API allows you to display your content in fullscreen mode, which is needed if your form is being served on a refrigerator or museum kiosk.
* When you need to create a custom form control, like a rich-text editor, the `contentEditable` attribute enables creating editable controls from normally non-editable HTML elements.
* The Drag and Drop API allows users to drag elements around a page and drop them in different locations. This can help improve the user experience when it comes to selecting files for upload or reordering content modules within a page.
* When screen orientation matters for your layout, you can use CSS media queries to style your forms based on the browser orientation, or even use the Screen Orientation API to read the screen orientation state and perform other actions.

The following sections provide a set of recommendations and best practices for enabling the widest possible set of users to use your websites and applications.

Supporting common input mechanisms
----------------------------------

### Keyboard

Most users will use a keyboard to enter data into your form controls. Some will also use the keyboard to navigate to those form controls. To be accessible, and for better user experience, it's important to properly label all form controls. When each form control has a correctly associated `<label>`, your form will be fully accessible to all, most notably anyone navigating your form with a keyboard, a screen reader, and possibly no screen at all.

If you want to add additional keyboard support, such as validating a form control when a specific key is hit, you can use event listeners to capture and react to keyboard events. For example, if you want to add controls when any key gets pressed, you need to add an event listener on the window object:

```js
window.addEventListener("keydown", handleKeyDown, true);
window.addEventListener("keyup", handleKeyUp, true);
```

`handleKeyDown` and `handleKeyUp` are functions defining the control logic to be executed when the `keydown` and `keyup` events are fired.

**Note:** Have a look at the Events reference and `KeyboardEvent` guide to find out more about keyboard events.

### Mouse

You can also capture mouse and other pointer events. The events occurring when the user interacts with a pointing device such as a mouse are represented by the `MouseEvent` DOM Interface. Common mouse events include `click`, `dblclick`, `mouseup`, and `mousedown`. The list of all events using the Mouse Event Interface is provided in the Events reference.

When the input device is a mouse, you can also control user input through the Pointer Lock API and implement Drag & Drop (see below). You can also use CSS to test for pointer device support.

### Finger touch

To provide additional support for touchscreen devices, it's a good practice to take into consideration the different capabilities in terms of screen resolution and user input. Touch events can help you implement interactive elements and common interaction gestures on touchscreen devices.

If you want to use touch events, you need to add event listeners and specify handler functions, which will be called when the event gets fired:

```js
element.addEventListener("touchstart", handleStart, false);
element.addEventListener("touchcancel", handleCancel, false);
element.addEventListener("touchend", handleEnd, false);
element.addEventListener("touchmove", handleMove, false);
```

where `element` is the DOM element you want to register the touch events on.

**Note:** For further information about what you can do with touch events, please read our touch events guide.

### Pointer Events

Mice aren't the only pointing devices. Your user's devices may incorporate multiple forms of input, like mouse, finger touch, and pen input. Each of these pointers has a different size. The Pointer Events API may come in handy if you need to manage events across devices by normalizing the handling of each one. A pointer can be any point of contact on the screen made by a mouse cursor, pen, touch (including multi-touch), or other pointing input device.

The events for handling generic pointer input look a lot like those for mouse: `pointerdown`, `pointermove`, `pointerup`, `pointerover`, `pointerout`, etc. The `PointerEvent` interface provides all the details you may want to capture about the pointer device, including its size, pressure, and angle.

Implement controls
------------------

### Screen Orientation

If you need slightly different layouts depending on whether the user is in portrait or landscape mode, you can use CSS media queries to define CSS for different layouts or form control widths based on the size or orientation of the screen when styling web forms.

When screen orientation matters for your form, you can read the screen orientation state, be informed when this state changes, and able to lock the screen orientation to a specific state (usually portrait or landscape) through the Screen Orientation API.

* Orientation data can be retrieved through `screenOrientation.type` or with CSS through the `orientation` media feature.
* When the screen orientation changes, the `change` event is fired on the screen object.
* Locking the screen orientation is made possible by invoking the `ScreenOrientation.lock()` method.
* The `ScreenOrientation.unlock()` method removes all the previous screen locks that have been set.

**Note:** More information about the Screen Orientation API can be found in Managing screen orientation.

### Fullscreen

If you need to present your form in fullscreen mode, such as when your form is displayed on a museum kiosk, toll booth, or really any publically displayed user interface, it is possible to do so by calling `Element.requestFullscreen()` on that element:

```js
const elem = document.getElementById("myForm");
if (elem.requestFullscreen) {
  elem.requestFullscreen();
}
```

**Note:** To find out more about adding fullscreen functionality to your application, read our documentation about using fullscreen mode.

### Drag & Drop

A common user interaction is the physical dragging of elements to be dropped elsewhere on the screen. Drag and drop can help improve the user experience when it comes to selecting files for upload or reordering content modules within a page. There's an API for that!

The Drag & Drop API enables users to click and hold the mouse button down over an element, drag it to another location, and release the mouse button to drop the element there.

Here is an example that allows a section of content to be dragged.

```html
<div
 draggable="true"
 ondragstart="event.dataTransfer.setData('text/plain', 'This text may be dragged')">
  This text <strong>may</strong> be dragged.
</div>
```

in which we:

* Set the `draggable` attribute to `true` on the element that you wish to make draggable.
* Add a listener for the `dragstart` event and set the drag data within this listener.

**Note:** You can find more information in the MDN Drag & Drop documentation.

### contentEditable

Generally, you should use a `<textarea>` or an appropriate `<input>` type within a `<form>` to collect data from users, along with a descriptive `<label>`. But these elements may not meet your needs. For example, rich text editors capture italic, bold, and normal text, but no native form control captures rich text. This use case requires you to create a custom control that is stylable *and* editable. There's an attribute for that!

Any DOM element can be made directly editable using the `contenteditable` attribute.
```

div {
  width: 300px;
  height: 130px;
  border: 1px solid gray;
}
```

```html
<div contenteditable="true">This text can be edited by the user.</div>
```

The `contenteditable` attribute automatically adds the element to the document's default tabbing order, meaning the `tabindex` attribute does not need to be added. However, when using non-semantic elements for data entry when creating your own form controls, you will need to add JavaScript and ARIA to retrofit the element with form control functionality for everything else.

To provide a good user experience, any custom form control you create must be accessible and function like native form controls:

* The element's `role`, label, and description need to be added with ARIA.
* All user input methods needs to be supported, including keyboard, mouse, touch, and pointer events, all described above.
* JavaScript is required to handle functionality such as validation, submission, and saving of user-updated content.

**Note:** Examples and other resources can be found in the Content Editable guide.

Tutorials
---------

* Touch events Guide
* Managing screen orientation
* Using fullscreen mode
* Drag Operations Guide
* Form validation
* Sending forms through JavaScript
Reference
---------

* `MouseEvent` interface
* `KeyboardEvent` interface
* Touch events API
* Pointer Lock API
* Screen Orientation API
* Fullscreen API
* Drag & Drop API
* HTML `contenteditable` attribute