22 August 2011
Understanding HTML5 intelligent forms – Part 1
Basic knowledge of HTML forms.
Intermediate
Validating user input in online forms needs to be done in two places—in the browser to prevent the form from being submitted with insufficient or invalid data, and on the server to filter out potential attacks. You'll still need to write your own server-side processing script or use a third-party one, but HTML5 is assuming most of the burden of validating user input before submitting it to the server. In Part 1 of this two-part tutorial series, I described the specialized input types for such values such as phone numbers, email addresses, and dates. In this second part, you'll learn about new form attributes that allow you to specify required fields, minimum and maximum values, and so on. You'll also learn how to ensure that ZIP codes, phone numbers, and similar values conform to a set format.
To demonstrate how various HTML5 attributes work, the files in html5_forms_pt2.zip contain simple forms, such as this one in on-off_01.html:
<form method="post" name="form1">
<p>
<label for="name">Name:</label>
<input type="text" name="name" id="name">
</p>
<p>
<label for="website">Website:</label>
<input type="url" name="website" id="website">
</p>
<p>
<label for="email">Email:</label>
<input type="email" name="email" id="email">
</p>
<p>
<input type="submit" name="send" id="send" value="Submit">
</p>
</form>
The type attribute of the first <input> tag uses the default text value, which creates an ordinary text input field. The second and third fields use the new url and email types. Figure 1 shows what the form looks like in a browser.
As explained in Part 1, older browsers that don't understand HTML5 form elements treat them as ordinary text input fields. Modern HTML5-compliant browsers check that the data matches the specified type before allowing the form to be submitted.
Use the example files in a variety of browsers to see the level of support they offer. The forms don't send the data anywhere. Processing form data is a huge subject beyond the scope of this tutorial, but clicking the submit button simulates what happens when a form is submitted. If the input fields clear, it indicates that the data was submitted successfully. If the data is invalid, modern browsers display an error message, preventing the form from being submitted until the error is corrected.
HTML5 defines several Boolean attributes—ones that represent true or false—for forms, namely:
autofocusrequiredmultipleformnovalidatenovalidateAdding one of these attributes to a tag turns the feature on. Leaving it out (or removing it programmatically) turns the feature off. Closely related to these Boolean attributes is autocomplete , which is on by default. To turn it off, you need to add it to a tag and explicitly set its value.
As a courtesy to the user, it's a good idea to set the focus in the first field for many forms. Previously, the only way to do this has been with JavaScript. With HTML5, just add the autofocus attribute to the <input> tag like this (on-off_02.html):
<input type="text" name="name" id="name" autofocus>
If you load the page into a modern browser, the cursor is automatically inserted in the field. Most browsers also highlight the field to draw the user's attention, as shown in Figure 2.
Only one field can have focus at any given time, so you should use autofocus only once in a form. It works well for login forms and pages that are solely dedicated to filling in a form. But you probably shouldn't use it for a search field that's incidental to the main content.
Note: If you're using XHTML-style markup, you need to set the value of autofocus and other Boolean attributes to the same value as the attribute name like this: autofocus="autofocus" .
Making fields required is just as easy. Simply add the required attribute to the <input> tag like this:
<input type="text" name="name" id="name" autofocus required>
If you attempt to submit the form without entering a value into the field, browsers that recognize the required attribute will prevent you from doing so, as Figure 3 shows (you can test it in on-off_03.html).
input[required] {
background-color: #E5F5EF;
}
In on-off_04.html, the required attribute has been added to the name and email fields producing the result shown in Figure 4.
All browsers except Internet Explorer (IE) 6 support attribute selectors. If you still need to support IE 6, you can hide the paragraph at the top of the form in IE 6 using a class and an IE conditional comment setting the class's display property to none like this:
<!--[if IE 6]>
<style>
.notie6 {
display: none;
}
</style>
<![endif]-->
Load on-off_04.html into different browsers, and try submitting the form without entering a value. Among modern browsers, IE 9 and Safari 5.1 are the only ones that submit the required fields without validation. Chrome and Opera check only the first invalid field. However, Firefox 5 and IE 10 Preview 2 not only display an error message for the first field, but also outline both invalid fields in red (see Figure 5).
The multiple attribute isn't new to HTML5, but its role has been expanded. Previously, its use was restricted to <select> elements, allowing you to convert a drop-down menu into a multiple-selection list. In HTML5, you can use it with other form fields to permit the submission of multiple values where normally only one would be accepted. In practice, this means with file upload and email fields.
The multiple attribute on file upload fields has been supported since Firefox 3.6, Safari 4, Chrome 4, and Opera 10. It's also supported by IE 10 Preview 2. Testing support for file upload fields requires a server-side technology, such as PHP or ColdFusion, which is beyond the scope of this tutorial. However, you can easily test email fields.
email input type).
multiple attribute to the <input> tag like this (or use on-off_06.html):<input type="email" name="email" id="email" autofocus multiple>
If there was no space between the comma and the addresses, all three browsers should accept the addresses.
If there was a space between the comma and the addresses, Firefox and Opera accept the addresses, but Chrome 13 displays the error message shown in Figure 7.
This is likely to confuse many users because it fails to explain that the problem is the space after the comma.
IE 10 Preview 2 behaves the same way as Firefox and Opera in that it accepts a space after the comma and rejects any other separator without explaining why.
Although the error messages with multiple email fields can be confusing, the main advantage of the HTML5 email input type is the way it rejects the submission of multiple addresses unless you specifically add the multiple attribute to the <input> tag. This is a safeguard against casual spammers. Unfortunately, it's very easy for the determined spammer to get around this restriction, so you still need to validate user data on the server.
Most browsers try to help users by suggesting values that have previously been entered in the same form or in fields with common names, such as address or email. For example, Safari displays a list of recent values entered in an email field, (see as Figure 8) shows.
Most of the time, this behavior is welcome, but allowing the browser to autocomplete certain fields, such as username, password, or credit card number can be insecure. HTML5 gives you control with the autocomplete attribute, which can be applied to a whole form or to individual input elements. By default, autocomplete is turned on, so you don't need to do anything if you're happy for the browser to make suggestions.
To turn off autocompletion for an entire form, add autocomplete="off" to the opening <form> tag. To turn off autocompletion for an individual element, add autocomplete="off" to the element's tag. For example, the email field in on-off_07.html looks like this:
<input type="email" name="email" id="email" autofocus autocomplete="off">
This turns off autocompletion for the email field, but leaves the default behavior for other fields.
Note: In my experiments, adding autocomplete="off" to an opening form tag is one ring to rule them all. You cannot override it for an individual element by adding autocomplete="on" to the element's tag.
Validating user input is important, so why would you want to turn off HTML5's automatic validation? There are several reasons:
Whatever your reason for wanting to turn off automatic validation, there are two ways to do so:
novalidate attribute to the opening <form> tag.formnovalidate attribute to the submit button's tag.Why two different attributes? Using novalidate in the opening <form> tag is basically a catch-all way of preventing the form from being validated when it's submitted. The formnovalidate attribute gives you a finer degree of control because it applies only when that particular button is clicked. For example, you could have separate buttons to save a draft and to submit the data like this:
<input type="submit" name="draft" id="draft" value="Save Draft" formnovalidate>
<input type="submit" name="send" id="send" value="Submit">
You can test this in on-off_08.html. Leave one of the required fields empty, and click the Save Draft button. The other fields clear, because automatic validation is skipped (it's a dummy form, so no data is actually saved). Try it again with the Submit button. This time, the browser does the normal validation checks and reports that the required field needs to be filled in.
In HTML 4.01 and XHTML 1.0, the maxlength attribute sets the maximum number of characters permitted in a text or password field. HTML5 extends its use to the following new input types:
searchtelemailurlMore significantly, perhaps, you can now also use maxlength to limit the number of characters in a <textarea> element. Currently, this is supported by the latest versions of Firefox, Chrome, and Safari. Once the limit is reached, the browser stops any further characters from being entered. You can test this in textarea-maxlength.html, which limits the number of permitted characters to 50 like this:
<textarea name="comments" id="comments" maxlength="50"></textarea>
Note also that the <textarea> tag no longer requires the rows and columns attributes. Use CSS to set the text area's width and height.
When using the HTML5 number and range input types, you can specify the minimum and maximum acceptable values with the min and max attributes. You can also specify the size of the increment between values using the step attribute. The values for min , max , and step must be numbers (integers or floating-point).
The markup in min-max_01.html sets the permitted range of values to 1–4 like this:
<input type="number" name="tickets" id="tickets" min="1" max="4">
The step attribute is omitted, so the default value of 1 is used. If you load the page into a browser that supports the number type (currently Safari, Chrome, or Opera), clicking the up and down arrows on the right of the input field displays only whole numbers between 1 and 4. You can type an out-of-range number directly into the field, but you get an error message as shown in Figure 9 when you click the submit button.
You need to be careful when using a floating-point number for step because of rounding errors caused by floating-point values. Opera automatically adjusts the value to the same number of decimal places as step , but Safari and Chrome use the raw number generated by the computer. To demonstrate the difference, min-max_02.html contains two sliders designed to generate a value between 0 and 1 in increments of 0.1. The HTML markup looks like this:
like this:
<p>
<label for="opacity">Opacity:</label>
<input type="range" name="opacity" id="opacity" min="0" max="1" step="0.1" value="0" onchange="display_rate.value=this.value">
<output name="display_rate" for="opacity"></output>
</p>
<p>
<label for="opacity2">Opacity (rounded):</label>
<input type="range" name="opacity2" id="opacity2" min="0" max="1" step="0.1" value="0" onchange="display_rate2.value=parseFloat(this.value).toFixed(1)">
<output name="display_rate2" for="opacity2"></output>
</p>
Figure 10 shows what happens when both sliders are set to 0.3 in Safari.
Strictly speaking, the rounding error is not a problem because the HTML5 specification says the range input type is intended for situations where a precise value is not important. However, if you need to display the value onscreen, you need to use the JavaScript parseFloat() method to convert it to a number, and then set the number of decimal places with toFixed() . The onchange handler in the second slider rounds the selected value like this:
display_rate2.value=parseFloat(this.value).toFixed(1)
Note: See Part 1 of this tutorial series for an explanation of the code used to display the output of an HTML5 slider.
The min , max , and step attributes can also be used to set a permitted range of dates or times. However, the HTML5 date- and time-related input types accept only values that conform to formats that are more suited to a technical environment (see Table 2 in Part 1 of this tutorial).
The code in min-max_03.html limits the range of dates to between January 1, 2011 and December 31, 2015 like this:
<input type="date" name="date" id="date" min="2011-01-01" max="2015-12-31" step="10">
The value of step has been set to 10, which further limits the choice of dates to every tenth day. In Safari and Chrome, clicking the up arrow inserts tomorrow's date (or the upper limit if the range has been exceeded). Clicking the down arrow inserts the date from 10 days ago. If you keep clicking, the date increases in steps of 10 days until you reach the end of the range.
In Opera, the calendar opens with dates in 10-day increments calculated from tomorrow's date highlighted in bold type. You can use the calendar's navigation arrows to move to different months or years within the specified range, but only highlighted dates can be selected (see Figure 11).
The value of step affects only the smallest unit. In the case of date , the increment is calculated in days. You cannot set date to increment one month at a time.
When used with time-related input elements, specifiying a value for step forces the field to display seconds as well as hours and minutes. The step attribute can also be set to the case-insensitive keyword any . In Safari and Chrome, using step="any" in a time input element sets the current time to the closest millisecond. Figure 12 shows the output in Chrome of the following time input elements after clicking the down arrow of each field in turn (the code is in min-max_04.html):
<p>
<label for="time">Time:</label>
<input type="time" name="time" id="time">
</p>
<p>
<label for="time10">Step="10":</label>
<input type="time" name="time10" id="time10" step="10">
</p>
<p>
<label for="any">Step="any":</label>
<input type="time" name="any" id="any" step="any">
</p>
The first time element doesn't use step , so it displays only hours and minutes. Clicking the up or down arrow increases or decreases the value one minute at a time. In the second one, step is set to 10, so it displays hours, minutes, and seconds, which can be adjusted in increments of ten seconds. The final field uses step="any" , which inserts the current time to the closest millisecond. Clicking the up or down arrow has no effect. The value is fixed.
Instead of inserting the current time, Opera defaults to 12:00. Setting step to a numeric value displays seconds in the same way as Safari and Chrome, but step="any" has no effect; Opera displays only hours and minutes.
Many online forms help users by displaying hints inside text fields, usually in light gray. When the field has focus, the hint disappears. Previously, you needed to code everything in JavaScript. Not any more. With HTML5, you just add the placeholder attribute to the <input> tag and set its value to whatever you want to appear as the hint. Figure 13 shows the output of the following code in placeholder.html:
<p>
<label for="zip">Zip Code:</label>
<input type="text" name="zip" id="zip" placeholder="5 digits">
</p>
<p>
<label for="arrival">Arrival Date:</label>
<input type="text" name="arrival" id="arrival" placeholder="MM/DD/YYYY">
</p>
All browsers except IE support placeholder—and it's coming in IE 10.
Displaying hints is all very fine, but it's not much use unless you can check whether the user has entered the data in the correct format. Thanks to the pattern attribute, you can. The only snag is that the pattern needs to be a regular expression (regex). Building regular expressions isn't easy, but it's a vital skill for working with many web-related languages. You can learn more about regexes in my two-part tutorial Using regular expressions. There are also online repositories, such as the one at http://regexlib.com, where you can find regular expressions that have been tried and tested by others.
When using the pattern attribute, the following restrictions apply:
^ and $ anchors for the beginning and end of the pattern are automatically implied.i to perform a case-insensitive match.The HTML5 specification also recommends including a description of the regex in the title attribute. Browsers use this as part of the error message if the input fails validation.
The code in pattern.html includes regular expressions for a five-digit zip code and a date formatted as MM/DD/YYYY :
<p>
<label for="zip">Zip Code:</label>
<input type="text" name="zip" id="zip" placeholder="5 digits" pattern="\d{5}" title="The zip code should consist of five numbers only">
</p>
<p>
<label for="arrival">Arrival Date:</label>
<input type="text" name="arrival" id="arrival" placeholder="MM/DD/YYYY" pattern="(0[1-9]|1[0-2])\/(0[1-9]|[12][0-9]|3[01])\/\d{4}" title="The date should be in the format MM/DD/YYYY with leading zeros where necessary">
</p>
Figure 14 shows what happens when Santa Claus enters his arrival date using the European DD/MM/YYYY format (after all, he comes from Lappland).
Note: A regex only matches a pattern. It doesn't check whether a date is valid. Nor can it distinguish between American- and European-style dates when both month and date are less than 12. For example, 07/04/2011 could mean either July 4 to an American or 7 April to a European, but it would still be accepted by the regex.
The regex for DD/MM/YYYY looks like this:
(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[0-2])\/\d{4}
The pattern attribute is supported by the latest versions of all browsers, except Safari 5.1 and IE 9 (but it's supported by IE 10 Preview 2).
Earlier, I demonstrated the use of formnovalidate to turn off automatic validation when a particular Submit button is clicked. Closely related to this attribute are four others, which override the form's defaults:
formaction overrides the action attributeformenctype overrides the enctype attributeformmethod overrides the method attributeformtarget overrides the target attributeAdding these attributes to a submit button causes the button to override the value of the equivalent attribute in the opening <form> tag—or the default value if it's not defined in the opening tag. For example, if the method attribute in the opening <form> tag is set to post , you can use formmethod="get" to override it when a specific button is clicked.
To demonstrate how this works, the form in overrides.html looks like this:
<form action="submit.html" method="post" name="form1">
<!-- input fields omitted -->
<p>
<input type="submit" name="draft" id="draft" value="Save Draft" formnovalidate formaction="draft.html">
<input type="submit" name="send" id="send" value="Submit" formmethod="get">
</p>
</form>
The default settings in the opening <form> tag send the data to submit.html by the post method for processing. However, the form has two submit buttons.
formnovalidate attribute turns off validation and the formaction attribute diverts the data to draft.html for processing. The <input> tag contains no other overrides, so the form is submitted by the post method, as specified in the opening <form> tag.formmethod attribute to override the post method and resets it to get . The <input> tag contains no other overrides, so the form is validated before being sent to the default submit.html for processing.You can see the principle behind how this works by loading overrides.html into the latest version of Chrome, Firefox, Opera, or Safari. Clicking the buttons shows the different ways the form reacts by taking you to dummy processing pages.
post method. (Even when all fields are empty, the form still submits their names and name of the submit button.)get method, and is attached to the URL as a query string (see Figure 15).
The ability to override the default form behaviors is an extremely powerful addition to HTML5. Unfortunately, it's not supported by Internet Explorer until IE 10. This means, in effect, that you won't be able to use these overrides for many years unless you're designing a form for an intranet where you know that everyone will be using a compliant browser. Shame, really.
In HTML 4.01 and XHTML 1.0, all form elements must be nested inside the opening and closing <form> tags. However, in HTML5 you can put a form element anywhere you like and associate it with a form using the new form attribute and setting it to the form's ID. For example, this is perfectly legitimate in HTML5:
<form action="submit.html" method="post" name="form1">
<!-- input fields omitted -->
<p>
<input type="submit" name="draft" id="draft" value="Save Draft" formnovalidate formaction="draft.html">
<input type="submit" name="send" id="send" value="Submit" formmethod="get">
</p>
</form>
The problem, as always, is lack of support. Until the form attribute is supported by all browsers in current use, you need to keep all form elements nested within the <form> tags.
Another important HTML5 form attribute is list , which associates a <datalist> element with an <input> field. This was described in Part 1 of this tutorial series.
One minor change is that you can now use the height and width attributes on an <input> element that uses an image as a button ( type="image" ).
If you have managed to survive this far, you'll realize that HTML5 introduces many new features designed to make online forms more intelligent. Unfortunately, the date- and time-related input elements aren't very user-friendly. Neverthless, the prospect of creating self-validating forms is appealing. The big question is when can you start using these new features. My personal view is that you can—and should—start using them now, with the exception of the form , formaction , formenctype , formmethod , and formtarget attributes. The only proviso is that you should turn off JavaScript validation. Of course, this means older browsers won't validate your forms before submitting them to the server; but validation still needs to be done on the server to stop spam and other attacks, as well as to eliminate user error. So, any problems will still be caught there. Adopting the HTML5 features will provide a better user experience for visitors using newer browsers without affecting the form's functionality in older ones.
Useful resources:
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.
Tutorials and samples |
| 04/23/2012 | Resolution/Compatibility/liquid layout |
|---|---|
| 04/20/2012 | using local/testing server with cs5 inserting images look fine in the split screen but do not show |
| 04/18/2012 | Ap Div help |
| 04/23/2012 | Updating |