A Form of Madness

Diving In

verybody knows about web forms, right? Make a <form>, a few <input type="text"> elements, maybe an <input type="password">, finish it off with an <input type="submit"> button, and you’re done.

You don’t know the half of it. HTML5 defines over a dozen new input types that you can use in your forms. And when I say “use,” I mean you can use them right now — without any shims, hacks, or workarounds. Now don’t get too excited; I don’t mean to say that all of these exciting new features are actually supported in every browser. Oh goodness no, I don’t mean that at all. In modern browsers, yes, your forms will kick all kinds of ass. But in legacy browsers, your forms will still work, albeit with less ass kicking. Which is to say, all of these features degrade gracefully in every browser. Even IE 6.

❧

Placeholder Text

Placeholder support

IE

Firefox

Safari

Chrome

Opera

iPhone

Android

·

3.7+

4.0+

4.0+

11.0+

4.0+

·

The first improvement HTML5 brings to web forms is the ability to set placeholder text in an input field. Placeholder text is displayed inside the input field as long as the field is empty and not focused. As soon as you click on (or tab to) the input field, the placeholder text disappears.

You’ve probably seen placeholder text before. For example, Mozilla Firefox includes placeholder text in the location bar that reads “Search Bookmarks and History”:

When you click on (or tab to) the location bar, the placeholder text disappears:

Ask Professor Markup

☞Q: Can I use HTML markup in the placeholder attribute? I want to insert an image, or maybe change the colors.
A: The placeholder attribute can only contain text, not HTML markup. However, there are some vendor-specific CSS extensions that allow you to style the placeholder text in some browsers.

❧

Autofocus Fields

Autofocus support

IE

Firefox

Safari

Chrome

Opera

iPhone

Android

·

4.0+

4.0+

3.0+

10.0+

·

·

Web sites can use JavaScript to focus the first input field of a web form automatically. For example, the home page of Google.com will autofocus the input box so you can type your search keywords. While this is convenient for most people, it can be annoying for power users or people with special needs. If you press the space bar expecting to scroll the page, the page will not scroll because the focus is already in a form input field. (It types a space in the field instead of scrolling.) If you focus a different input field while the page is still loading, the site’s autofocus script may “helpfully” move the focus back to the original input field, disrupting your flow and causing you to type in the wrong place.

Because the autofocusing is done with JavaScript, it can be tricky to handle all of these edge cases, and there is little recourse for people who don’t want a web page to “steal” the focus.

To solve this problem, HTML5 introduces an autofocus attribute on all web form controls. The autofocus attribute does exactly what it says on the tin: as soon as the page loads, it moves the input focus to a particular input field. But because it’s just markup instead of script, the behavior will be consistent across all web sites. Also, browser vendors (or extension authors) can offer users a way to disable the autofocusing behavior.

Setting focus as early as possible

Lots of web pages wait until window.onload fires to set focus. But the window.onload event doesn’t fire until after all your images have loaded. If your page has a lot of images, such a naive script could potentially re-focus the field after the user has started interacting with another part of your page. This is why power users hate autofocus scripts.

The example in the previous section placed the auto-focus script immediately after the form field that it references. This is the optimal solution, but it may offend your sensibilities to put a block of JavaScript code in the middle of your page. (Or, more mundanely, your back-end systems may just not be that flexible.) If you can’t insert a script in the middle of your page, you should set focus during a custom event like jQuery’s $(document).ready() instead of window.onload.

jQuery fires its custom ready event as soon as the page DOM is available — that is, it waits until the page text is loaded, but it doesn’t wait until all the images are loaded. This is not an optimal approach — if the page is unusually large or the network connection is unusually slow, a user could still start interacting with the page before your focus script executes. But it is still far better than waiting until the window.onload event fires.

If you are willing and able to insert a single script statement in your page markup, there is a middle ground that is less offensive than the first option and more optimal than the second. You can use jQuery’s custom events to define your own event, say autofocus_ready. Then you can trigger this event manually, immediately after the autofocus form field is available. Thanks to E. M. Sternberg for teaching me about this technique.

This is as optimal as the first approach; it will set focus to the form field as soon as technically possible, while the text of the page is still loading. But it transfers the bulk of your application logic (focusing the form field) out of the body of the page and into the head. This example relies on jQuery, but the concept of custom events is not unique to jQuery. Other JavaScript libraries like YUI and Dojo offer similar capabilities.

To sum up:

Setting focus properly is important.

If at all possible, let the browser do it by setting the autofocus attribute on the form field you want to have focus.

If you code a fallback for older browsers, detect support for the autofocus attribute to make sure your fallback is only executed in older browsers.

Set focus as early as possible. Insert the focus script into your markup immediately after the form field. If that offends you, use a JavaScript library that supports custom events, and trigger a custom event immediately after the form field markup. If that’s not possible, use something like jQuery’s $(document).ready() event.

Under no circumstances should you wait until window.onload to set focus.

❧

Email Addresses

For over a decade, web forms comprised just a few kinds of fields. The most common kinds were

Field Type

HTML Code

Notes

checkbox

<input type="checkbox">

can be toggled on or off

radio button

<input type="radio">

can be grouped with other inputs

password field

<input type="password">

echos dots instead of characters as you type

drop-down lists

<select><option>…

file picker

<input type="file">

pops up an “open file” dialog

submit button

<input type="submit">

plain text

<input type="text">

the type attribute can be omitted

All of these input types still work in HTML5. If you’re “upgrading to HTML5” (perhaps by changing your DOCTYPE), you don’t need to make a single change to your web forms. Hooray for backward compatibility!

However, HTML5 defines 13 new field types, and for reasons that will become clear in a moment, there is no reason not to start using them.

The first of these new input types is for email addresses. It looks like this:

<form>
<input type="email">
<input type="submit" value="Go">
</form>

I was about to write a sentence that started with “in browsers that don’t support type="email"…” but I stopped myself. Why? Because I’m not sure what it would mean to say that a browser doesn’t support type="email". All browsers “support” type="email". They may not do anything special with it (you’ll see a few examples of special treatment in a moment), but browsers that don’t recognize type="email" will treat it as type="text" and render it as a plain text field.

I can not emphasize how important this is. The web has millions of forms that ask you to enter an email address, and all of them use <input type="text">. You see a text box, you type your email address in the text box, and that’s that. Along comes HTML5, which defines type="email". Do browsers freak out? No. Every single browser on Earth treats an unknown type attribute as type="text" — even IE 6. So you can “upgrade” your web forms to use type="email" right now.

What would it mean to say that a browser DID support type="email"? Well, it can mean any number of things. The HTML5 specification doesn’t mandate any particular user interface for the new input types. Most desktop browsers like Safari, Chrome, Opera, and Firefox simply render it as a text box — exactly like type="text" — so your users will never know the difference (until they try to submit the form).

And then there’s the iPhone.

The iPhone does not have a physical keyboard. All “typing” is done by tapping on an on-screen keyboard that pops up at appropriate times, like when you focus a form field in a web page. Apple did something clever in the iPhone’s web browser. It recognizes several of the new HTML5 input types, and dynamically changes the on-screen keyboard to optimize for that kind of input.

For example, email addresses are text, right? Sure, but they’re a special kind of text. For example, virtually all email addresses contain the @ sign and at least one period (.), but they’re unlikely to contain any spaces. So when you use an iPhone and focus an <input type="email"> element, you get an on-screen keyboard that contains a smaller-than-usual space bar, plus dedicated keys for the @ and . characters.

To sum up: there’s no downside to converting all your email address form fields to type="email" immediately. Virtually no one will even notice, except iPhone users, who probably won’t notice either. But the ones who do notice will smile quietly and thank you for making their web experience just a little easier.

❧

Web Addresses

Web addresses — which standards wonks call URLs, except for a few pedants which call them URIs — are another type of specialized text. The syntax of a web address is constrained by the relevant Internet standards. If someone asks you to enter a web address into a form, they’re expecting something like “http://www.google.com/”, not “125 Farwood Road.” Forward slashes are common — even Google’s home page has three of them. Periods are also common, but spaces are forbidden. And every web address has a domain suffix like “.com” or “.org”.

Behold... (drum roll please)... <input type="url">. On the iPhone, it looks like this:

The iPhone altered its virtual keyboard, just like it did for email addresses, but now optimized for web addresses instead. The space bar has been completely replaced with three virtual keys: a period, a forward slash, and a “.com” button. (You can long-press the “.com” button to choose other common suffixes like “.org” or “.net”.)

Most modern desktop browsers simply render type="url" like a regular text box, so users won’t even notice until they submit the form. Browsers that don’t support HTML5 will treat type="url" exactly like type="text", so there’s no downside to using it for all your web-address-inputting needs.

❧

Numbers as Spinboxes

Next up: numbers. Asking for a number is trickier than asking for an email address or web address. First of all, numbers are more complicated than you might think. Quick: pick a number. -1? No, I meant a number between 1 and 10. 7½? No no, not a fraction, silly. π? Now you’re just being irrational.

My point is, you don’t often ask for “just a number.” It’s more likely that you’ll ask for a number in a particular range. You may only want certain kinds of numbers within that range — maybe whole numbers but not fractions or decimals, or something more esoteric like numbers divisible by 10. HTML5 has you covered.

step="2", combined with the min value, defines the acceptable numbers in the range: 0, 2, 4, and so on, up to the max value.

value="6" is the default value. This should look familiar. It’s the same attribute name you’ve always used to specify values for form fields. (I mention it here to drive home the point that HTML5 builds on previous versions of HTML. You don’t need to relearn how to do stuff you’re already doing.)

That’s the markup side of a number field. Keep in mind that all of those attributes are optional. If you have a minimum but no maximum, you can specify a min attribute but no max attribute. The default step value is 1, and you can omit the step attribute unless you need a different step value. If there’s no default value, then the value attribute can be the empty string or even omitted altogether.

But HTML5 doesn’t stop there. For the same low, low price of free, you get these handy JavaScript methods as well:

input.stepUp(n) increases the field’s value by n.

input.stepDown(n) decreases the field’s value by n.

input.valueAsNumber returns the current value as a floating point number. (The input.value property is always a string.)

Having trouble visualizing it? Well, the exact interface of a number control is up to your browser, and different browser vendors have implemented support in different ways. On the iPhone, where input is difficult to begin with, the browser onceagain optimizes the virtual keyboard for numeric input.

In the desktop version of Opera, the same type="number" field is rendered as a “spinbox” control, with little up and down arrows that you can click to change the value.

Opera respects the min, max, and step attributes, so you’ll always end up with an acceptable numeric value. If you bump up the value to the maximum, the up arrow in the spinbox is greyed out.

As with all the other input types I’ve discussed in this chapter, browsers that don’t support type="number" will treat it as type="text". The default value will show up in the field (since it’s stored in the value attribute), but the other attributes like min and max will be ignored. You’re free to implement them yourself, or you could reuse a JavaScript framework that has already implemented spinbox controls. Just check for the native HTML5 support first, like this:

if (!Modernizr.inputtypes.number) {
// no native support for type=number fields
// maybe try Dojo or some other JavaScript framework
}

❧

Numbers as Sliders

Spinboxes are not the only way to represent numeric input. You’ve probably also seen “slider” controls that look like this:

You can now have slider controls in your web forms, too. The markup looks eerily similar to spinbox controls:

↶ The spitting image

<input type="range"
min="0"
max="10"
step="2"
value="6">

All the available attributes are the same as type="number" — min, max, step, value — and they mean the same thing. The only difference is the user interface. Instead of a field for typing, browsers are expected to render type="range" as a slider control. Safari, Chrome, and Opera all do this. (Sadly, the iPhone renders it as a simple text box. It doesn’t even optimize its on-screen keyboard for numeric input.) All other browsers simply treat the field as type="text", so there’s no reason you can’t start using it immediately.

❧

Date Pickers

HTML 4 did not include a date picker control. JavaScript frameworks have picked up the slack (Dojo, jQuery UI, YUI, Closure Library), but of course each of these solutions requires “buying into” the framework on which the date picker is built.

HTML5 finally defines a way to include a native date picker control without having to script it yourself. In fact, it defines six: date, month, week, time, date + time, and date + time - timezone.

It’s likely that other browsers will eventually support these input types. But just like type="email" and the other input types, these form fields will be rendered as plain text boxes in browsers that don’t recognize type="date" and the other variants. If you like, you can simply use <input type="date"> and friends, make Opera users happy, and wait for other browsers to catch up. More realistically, you can use <input type="date">, detect whether the browser has native support for date pickers, and fall back to a scripted solution of your choice (Dojo, jQuery UI, YUI, Closure Library, or some other solution).

Search Boxes

OK, this one is subtle. Well, the idea is simple enough, but the implementations may require some explanation. Here goes…

Search. Not just Google Search or Yahoo Search. (Well, those too.) Think of any search box, on any page, on any site. Amazon has a search box. Newegg has a search box. Most blogs have a search box. How are they marked up? <input type="text">, just like every other text box on the web. Let’s fix that.

Can you spot the difference? The input box has rounded corners! I know, I know, you can hardly contain your excitement. But wait, there’s more! When you actually start typing into the type="search" box, Safari inserts a small “x” button on the right side of the box. Clicking the “x” clears the contents of the field. (Google Chrome, which shares much technology with Safari under the hood, also exhibits this behavior.) Both of these small tweaks are done to match the look and feel of native search boxes in iTunes and other Mac OS X client applications.

Apple.com uses <input type="search"> for their site-search box, to help give their site a “Mac-like” feel. But there’s nothing Mac-specific about it. It’s just markup, so each browser on each platform can choose to render it according to platform-specific conventions. As with all the other new input types, browsers that don’t recognize type="search" will treat it like type="text", so there is absolutely no reason not to start using type="search" for all your search boxes today.

Professor Markup Says

By default, older versions of Safari will not apply even the most basic CSS styles to <input type="search"> fields. If you want to force Safari to treat your search field like a normal text field (so you can apply your own CSS styles), add this rule to your stylesheet:

input[type="search"] {
-webkit-appearance: textfield;
}

Thanks to John Lein for teaching me this trick.

❧

Color Pickers

HTML5 also defines <input type="color">, which lets you pick a color and returns the color’s hexadecimal representation. No browser supports it yet, which is a shame, because I’ve always loved the Mac OS color picker. Maybe someday. Good news, everyone! Opera 11 now supports type=color. On Mac and Windows, it integrates with the platform's native color picker. On Linux, it drops down a basic color picker. On all platforms, the return value of the input control is a six-digit hexadecimal RGB color, suitable for framing or using anywhere that accepts a CSS color.

Form Validation

Form validation support

IE

Firefox

Safari

Chrome

Opera

iPhone

Android

·

4.0+

5.0+

10.0+

9.0+

·

·

In this chapter, I’ve talked about new input types and new features like auto-focus form fields, but I haven’t mentioned what is perhaps the most exciting part of HTML5 forms: automatic input validation. Consider the common problem of entering an email address into a web form. You probably have some client-side validation in JavaScript, followed by server-side validation in PHP or Python or some other server-side scripting language. HTML5 can never replace your server-side validation, but it might someday replace your client-side validation.

There are two big problems with validating email addresses in JavaScript:

A surprising number of your visitors (probably around 10%) won’t have JavaScript enabled

HTML5 also offers validation of web addresses entered into <input type="url"> fields, and numbers in <input type="number"> fields. The validation of numbers even takes into account the min and max attributes, so browsers will not let you submit the form if you enter a number that is too large.

There is no markup required to activate HTML5 form validation; it is on by default. To turn it off, use the novalidate attribute.

Did You Know?

In association with Google Press, O’Reilly is distributing this book in a variety of formats, including paper, ePub, Mobi, and DRM-free PDF. The paid edition is called “HTML5: Up & Running,” and it is available now. This chapter is included in the paid edition.