forked from deianvasilev/diveintohtml5
-
Notifications
You must be signed in to change notification settings - Fork 10
/
forms.html
553 lines (393 loc) · 42 KB
/
forms.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
<!DOCTYPE html>
<meta charset=utf-8>
<title>Web Forms - Dive Into HTML5</title>
<!--[if lt IE 9]><script src=j/html5.js></script><![endif]-->
<link rel=alternate type=application/atom+xml href=https://github.com/diveintomark/diveintohtml5/commits/master.atom>
<link rel=stylesheet href=screen.css>
<style>
body{counter-reset:h1 9}
</style>
<link rel=stylesheet media='only screen and (max-device-width: 480px)' href=mobile.css>
<link rel=prefetch href=index.html>
<p>You are here: <a href=index.html>Home</a> <span class=u>‣</span> <a href=table-of-contents.html#forms>Dive Into <abbr>HTML5</abbr></a> <span class=u>‣</span>
<h1><br>A Form of Madness</h1>
<p id=toc>
<p class=a>❧
<h2 id=divingin>Diving In</h2>
<p class=f><img src=i/aoc-e.png alt=E width=107 height=105>verybody knows about web forms, right? Make a <code><form></code>, a few <code><input type="text"></code> elements, maybe an <code><input type="password"></code>, finish it off with an <code><input type="submit"></code> button, and you’re done.
<p>You don’t know the half of it. <abbr>HTML5</abbr> 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.
<p class=a>❧
<h2 id=placeholder>Placeholder Text</h2>
<table class=bc>
<caption>Placeholder support</caption>
<thead>
<tr><th title="Internet Explorer">IE<th title="Mozilla Firefox">Firefox<th title="Apple Safari">Safari<th title="Google Chrome">Chrome<th>Opera<th>iPhone<th>Android
<tbody>
<tr><td>·<td>3.7+<td>4.0+<td>4.0+<td>11.0+<td>4.0+<td>·
</table>
<p>The first improvement <abbr>HTML5</abbr> brings to web forms is the ability to set <a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#the-placeholder-attribute>placeholder text in an input field</a>. 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.
<p>You’ve probably seen placeholder text before. For example, Mozilla Firefox includes placeholder text in the location bar that reads “Search Bookmarks and History”:
<p class=c><img src=i/location-bar-empty-unfocused.png alt="location bar with placeholder text" width=268 height=30>
<p>When you click on (or tab to) the location bar, the placeholder text disappears:
<p class=c><img src=i/location-bar-empty-focused.png alt="location bar with cursor and no placeholder text" width=268 height=30>
<p>Here’s how you can include placeholder text in your own web forms:
<pre><code><form>
<input name="q" <mark>placeholder="Search Bookmarks and History"</mark>>
<input type="submit" value="Search">
</form></code></pre>
<p>Browsers that don’t support the <code>placeholder</code> attribute will simply ignore it. No harm, no foul. <a href=examples/input-placeholder.html>See whether your browser supports placeholder text</a>.
<div class="pf clear">
<h4>Ask Professor Markup</h4>
<div class=inner>
<blockquote class=note>
<p><span>☞</span>Q: Can I use <abbr>HTML</abbr> markup in the <code>placeholder</code> attribute? I want to insert an image, or maybe change the colors.<br>
A: The <code>placeholder</code> attribute can only contain text, not <abbr>HTML</abbr> markup. However, there are <a href=http://trac.webkit.org/export/37527/trunk/LayoutTests/fast/forms/placeholder-pseudo-style.html>some vendor-specific CSS extensions</a> that allow you to style the placeholder text in some browsers.
</blockquote>
</div>
</div>
<p class=a>❧
<h2 id=autofocus>Autofocus Fields</h2>
<table class=bc>
<caption>Autofocus support</caption>
<thead>
<tr><th title="Internet Explorer">IE<th title="Mozilla Firefox">Firefox<th title="Apple Safari">Safari<th title="Google Chrome">Chrome<th>Opera<th>iPhone<th>Android
<tbody>
<tr><td>·<td>4.0+<td>4.0+<td>3.0+<td>10.0+<td>·<td>·
</table>
<p class=ss><img src=i/openclipart.org_johnny_automatic_angry_guy.png alt="angry guy with arms up" width=188 height=262>
<p>Web sites can use JavaScript to focus the first input field of a web form automatically. For example, the home page of <a href=http://www.google.com/>Google.com</a> 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.
<p>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.
<p>To solve this problem, <abbr>HTML5</abbr> introduces <a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#autofocusing-a-form-control>an <code>autofocus</code> attribute on all web form controls</a>. The <code>autofocus</code> 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.
<p>Here’s how you can set a form field to autofocus:
<pre><code><form>
<input name="q" <mark>autofocus</mark>>
<input type="submit" value="Search">
</form></code></pre>
<p>Browsers that don’t support the <code>autofocus</code> attribute will simply ignore it. <a href=examples/input-autofocus.html>See whether your browser supports autofocus fields</a>.
<p>What’s that? You say you want your autofocus fields to work in all browsers, not just these fancy-pants <abbr>HTML5</abbr> browsers? You can keep your current autofocus script. Just make two small changes:
<ol>
<li>Add the <code>autofocus</code> attribute to your <abbr>HTML</abbr> markup
<li><a href=detect.html#input-autofocus>Detect whether the browser supports the <code>autofocus</code> attribute</a>, and only run your own autofocus script if the browser doesn’t support autofocus natively.
</ol>
<p class="legend top" style="margin-left:10em"><span class=arrow>↶</span> Autofocus with fallback
<pre><code><form name="f">
<input id="q" <mark>autofocus</mark>>
<script>
if (<mark>!("autofocus" in document.createElement("input"))</mark>) {
document.getElementById("q").focus();
}
</script>
<input type="submit" value="Go">
</form>
…</code></pre>
<p><a href=examples/input-autofocus-with-fallback.html>See an example of <code>autofocus</code> with fallback</a>.
<h3 id=more-on-focus>Setting focus as early as possible</h3>
<p>Lots of web pages wait until <code>window.onload</code> fires to set focus. But the <code>window.onload</code> event doesn’t fire until <em>after</em> 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.
<p>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 <a href="http://docs.jquery.com/Tutorials:Introducing_$(document).ready()"><code>$(document).ready()</code></a> instead of <code>window.onload</code>.
<p class="legend top" style="margin-left:10em"><span class=arrow>↶</span> Autofocus with jQuery fallback
<pre><code><head>
<script src=jquery.min.js></script>
<script>
<mark>$(document).ready</mark>(function() {
if (!("autofocus" in document.createElement("input"))) {
$("#q").focus();
}
});
</script>
</head>
<body>
<form name="f">
<input id="q" autofocus>
<input type="submit" value="Go">
</form>
</code></pre>
<p><a href=examples/input-autofocus-with-fallback-document-ready.html>See an example of <code>autofocus</code> with jQuery fallback</a>.
<p>jQuery fires its custom <code>ready</code> event as soon as the page <abbr>DOM</abbr> 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 <code>window.onload</code> event fires.
<p>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 <code>autofocus_ready</code>. Then you can trigger this event manually, immediately after the autofocus form field is available. <i>Thanks to E. M. Sternberg for teaching me about this technique.</i>
<p class="legend top" style="margin-left:10em"><span class=arrow>↶</span> Autofocus with a custom event fallback
<pre><code><head>
<script src=jquery.min.js></script>
<script>
<mark>$(document).bind('autofocus_ready',</mark> function() {
if (!("autofocus" in document.createElement("input"))) {
$("#q").focus();
}
});
</script>
</head>
<body>
<form name="f">
<input id="q" autofocus>
<script><mark>$(document).trigger('autofocus_ready');</mark></script>
<input type="submit" value="Go">
</form>
</code></pre>
<p><a href=examples/input-autofocus-with-fallback-custom-event.html>See an example of <code>autofocus</code> with a custom event fallback</a>.
<p>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.
<p>To sum up:
<ul>
<li>Setting focus properly is important.
<li>If at all possible, let the browser do it by setting the <code>autofocus</code> attribute on the form field you want to have focus.
<li>If you code a fallback for older browsers, detect support for the <code>autofocus</code> attribute to make sure your fallback is <em>only</em> executed in older browsers.
<li>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 <code>$(document).ready()</code> event.
<li>Under no circumstances should you wait until <code>window.onload</code> to set focus.
</ul>
<p class=a>❧
<h2 id=type-email>Email Addresses</h2>
<p>For over a decade, web forms comprised just a few kinds of fields. The most common kinds were
<table class=st>
<tr class=ho><th>Field Type<th><abbr>HTML</abbr> Code<th>Notes
<tr class=zebra><th>checkbox<td><code><input type="checkbox"></code><td>can be toggled on or off
<tr><th>radio button<td><code><input type="radio"></code><td>can be grouped with other inputs
<tr class=zebra><th>password field<td><code><input type="password"></code><td>echos dots instead of characters as you type
<tr><th>drop-down lists<td><code><select><option>…</code><td>
<tr class=zebra><th>file picker<td><code><input type="file"></code><td>pops up an “open file” dialog
<tr><th>submit button<td><code><input type="submit"></code><td>
<tr class=zebra><th>plain text<td><code><input type="text"></code><td>the <code>type</code> attribute can be omitted
</table>
<p>All of these input types still work in <abbr>HTML5</abbr>. If you’re “upgrading to <abbr>HTML5</abbr>” (perhaps by <a href=semantics.html#the-doctype>changing your DOCTYPE</a>), you don’t need to make a single change to your web forms. Hooray for backward compatibility!
<p>However, <abbr>HTML5</abbr> defines 13 new field types, and for reasons that will become clear in a moment, there is no reason <em>not</em> to start using them.
<p>The first of these new input types is for <a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#e-mail-state>email addresses</a>. It looks like this:
<pre><code><form>
<mark><input type="email"></mark>
<input type="submit" value="Go">
</form></code></pre>
<p>I was about to write a sentence that started with “in browsers that don’t support <code>type="email"</code>…” but I stopped myself. Why? Because I’m not sure what it would mean to say that a browser doesn’t support <code>type="email"</code>. All browsers “support” <code>type="email"</code>. 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 <code>type="email"</code> will treat it as <code>type="text"</code> and render it as a plain text field.
<p>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 <code><input type="text"></code>. You see a text box, you type your email address in the text box, and that’s that. Along comes <abbr>HTML5</abbr>, which defines <code>type="email"</code>. Do browsers freak out? No. Every single browser on Earth treats an unknown <code>type</code> attribute as <code>type="text"</code> — even IE 6. So you can “upgrade” your web forms to use <code>type="email"</code> right now.
<p>What would it mean to say that a browser <em>DID</em> support <code>type="email"</code>? Well, it can mean any number of things. The <abbr>HTML5</abbr> 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 <code>type="text"</code> — so your users will never know the difference (<a href=#validation>until they try to submit the form</a>).
<p>And then there’s the iPhone.
<p>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 <abbr>HTML5</abbr> input types, and <em>dynamically changes the on-screen keyboard</em> to optimize for that kind of input.
<p>For example, email addresses are text, right? Sure, but they’re a special kind of text. For example, virtually all email addresses contain the <code>@</code> sign and at least one period (<code>.</code>), but they’re unlikely to contain any spaces. So when you use an iPhone and focus an <code><input type="email"></code> element, you get an on-screen keyboard that contains a smaller-than-usual space bar, plus dedicated keys for the <code>@</code> and <code>.</code> characters.
<p class=c><img src=i/input-type-email.png alt="iPhone rendering input type=email field" title="note the dedicated @ and . keys next to the space bar" width=222 height=333 class=fr><br><a href=examples/input-type-email.html>Test <code>type="email"</code> for yourself</a>.
<p>To sum up: there’s no downside to converting all your email address form fields to <code>type="email"</code> 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.
<p class=a>❧
<h2 id=type-url>Web Addresses</h2>
<p>Web addresses — which standards wonks call <abbr>URLs</abbr>, except for a few <a href="http://www.douglasadams.com/dna/pedants.html">pedants</a> which call them <abbr>URIs</abbr> — 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 “<code>http://www.google.com/</code>”, 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”.
<p>Behold... (drum roll please)... <code><input type="url"></code>. On the iPhone, it looks like this:
<p class=c><img src=i/input-type-url.png alt="iPhone rendering input type=url field" width=222 height=333 class=fr><br><a href=examples/input-type-url.html>Test <code>type="url"</code> for yourself</a>.
<p>The iPhone altered its virtual keyboard, just like it did for <a href=#type-email>email addresses</a>, 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”.)
<p>Most modern desktop browsers simply render <code>type="url"</code> like a regular text box, so users won’t even notice <a href=#validation>until they submit the form</a>. Browsers that don’t support <abbr>HTML5</abbr> will treat <code>type="url"</code> exactly like <code>type="text"</code>, so there’s no downside to using it for all your web-address-inputting needs.
<p class=a>❧
<h2 id=type-number>Numbers as Spinboxes</h2>
<p>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. <span class=u>π</span>? Now you’re just being irrational.
<p>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. <abbr>HTML5</abbr> has you covered.
<p class="legend top" style="margin-left:8em"><span class=arrow>↶</span> Pick a number, (almost) any number
<pre><code><input <mark>type="number"</mark>
min="0"
max="10"
step="2"
value="6"></code></pre>
<p>Let’s take that one attribute at a time. (You can <a href=examples/input-type-number-min-max-step.html>follow along with a live example</a> if you like.)
<ul>
<li><code>type="number"</code> means that this is a number field.
<li><code>min="0"</code> specifies the minimum acceptable value for this field.
<li><code>max="10"</code> is the maximum acceptable value.
<li><code>step="2"</code>, combined with the <code>min</code> value, defines the acceptable numbers in the range: <code>0</code>, <code>2</code>, <code>4</code>, and so on, up to the <code>max</code> value.
<li><code>value="6"</code> 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 <abbr>HTML5</abbr> builds on previous versions of <abbr>HTML</abbr>. You don’t need to relearn how to do stuff you’re already doing.)
</ul>
<p>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 <code>min</code> attribute but no <code>max</code> attribute. The default step value is 1, and you can omit the <code>step</code> attribute unless you need a different step value. If there’s no default value, then the <code>value</code> attribute can be the empty string or even omitted altogether.
<p>But <abbr>HTML5</abbr> doesn’t stop there. For the same low, low price of free, you get these handy JavaScript methods as well:
<ul>
<li><code>input.stepUp(n)</code> increases the field’s value by <code>n</code>.
<li><code>input.stepDown(n)</code> decreases the field’s value by <code>n</code>.
<li><code>input.valueAsNumber</code> returns the current value as a floating point number. (The <code>input.value</code> property is always a string.)
</ul>
<p>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 <a href=#type-email>once</a> <a href=#type-url>again</a> optimizes the virtual keyboard for numeric input.
<p class=c><img src=i/input-type-number.png alt="iPhone rendering input type=number field" width=222 height=333 class=fr>
<p>In the desktop version of Opera, the same <code>type="number"</code> field is rendered as a “spinbox” control, with little up and down arrows that you can click to change the value.
<p class=c><img src=i/input-type-number-opera.png alt="Opera rendering input type=number field" width=227 height=203 class=fr>
<p>Opera respects the <code>min</code>, <code>max</code>, and <code>step</code> 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.
<p class=c><img src=i/input-type-number-at-max-opera.png alt="Opera rendering input type=number field at max value" width=142 height=28 class=fr>
<p>As with all the other input types I’ve discussed in this chapter, browsers that don’t support <code>type="number"</code> will treat it as <code>type="text"</code>. The default value will show up in the field (since it’s stored in the <code>value</code> attribute), but the other attributes like <code>min</code> and <code>max</code> will be ignored. You’re free to implement them yourself, or you could reuse a JavaScript framework that has already implemented spinbox controls. Just <a href=detect.html#input-types>check for the native <abbr>HTML5</abbr> support</a> first, like this:
<pre><code>if (!<a href=detect.html#modernizr>Modernizr</a>.inputtypes.number) {
// no native support for type=number fields
// maybe try Dojo or some other JavaScript framework
}</code></pre>
<p class=a>❧
<h2 id=type-range>Numbers as Sliders</h2>
<p><a href=#type-number>Spinboxes</a> are not the only way to represent numeric input. You’ve probably also seen “slider” controls that look like this:
<p class=c><img src=i/input-type-range.png alt="Chrome rendering of input type=range field as slider control" width=175 height=25><br><a href=examples/input-type-range.html>Test <code>type="range"</code> for yourself</a>.
<p>You can now have slider controls in your web forms, too. The markup looks eerily similar to <a href=#type-range>spinbox controls</a>:
<p class="legend top" style="margin-left:8em"><span class=arrow>↶</span> The spitting image
<pre><code><input <mark>type="range"</mark>
min="0"
max="10"
step="2"
value="6"></code></pre>
<p>All the available attributes are the same as <code>type="number"</code> — <code>min</code>, <code>max</code>, <code>step</code>, <code>value</code> — and they mean the same thing. The only difference is the user interface. Instead of a field for typing, browsers are expected to render <code>type="range"</code> 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 <code>type="text"</code>, so there’s no reason you can’t start using it immediately.
<p class=a>❧
<h2 id=type-date>Date Pickers</h2>
<p><abbr>HTML</abbr> 4 did not include a date picker control. JavaScript frameworks have picked up the slack (<a href=http://docs.dojocampus.org/dijit/form/DateTextBox>Dojo</a>, <a href=http://docs.jquery.com/UI/Datepicker>jQuery UI</a>, <a href=http://developer.yahoo.com/yui/calendar/>YUI</a>, <a href=http://closure-library.googlecode.com/svn/docs/class_goog_ui_DatePicker.html>Closure Library</a>), but of course each of these solutions requires “buying into” the framework on which the date picker is built.
<p><abbr>HTML5</abbr> 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.
<p>So far, support is… sparse.
<table class=bc>
<caption>Date picker support</caption>
<thead>
<tr><th style="text-align:left">Input Type<th>Opera<th>Every other browser
<tbody>
<tr><th><code>type="date"</code><td>9.0+<td>·
<tr><th><code>type="month"</code><td>9.0+<td>·
<tr><th><code>type="week"</code><td>9.0+<td>·
<tr><th><code>type="time"</code><td>9.0+<td>·
<tr><th><code>type="datetime"</code><td>9.0+<td>·
<tr><th><code>type="datetime-local"</code><td>9.0+<td>·
</table>
<p>This is how Opera renders <a href=examples/input-type-date.html><code><input type="date"></code></a>:
<blockquote>
<p><img src=i/input-type-date.png alt="Opera's type=date picker" width=210 height=190>
</blockquote>
<p>If you need a time to go with that date, Opera also supports <a href=examples/input-type-datetime.html><code><input type="datetime"></code></a>:
<blockquote>
<p><img src=i/input-type-datetime.png alt="Opera's type=datetime picker" width=225 height=191>
</blockquote>
<p>If you only need a month + year (perhaps a credit card expiration date), Opera can render a <a href=examples/input-type-month.html><code><input type="month"></code></a>:
<blockquote>
<p><img src=i/input-type-month.png alt="Opera's type=month picker" width=210 height=189>
</blockquote>
<p>Less common, but also available, is the ability to pick a specific week of a year with <a href=examples/input-type-week.html><code><input type="week"></code></a>:
<blockquote>
<p><img src=i/input-type-week.png alt="Opera's type=week picker" width=210 height=191>
</blockquote>
<p>Last but not least, you can pick a time with <a href=examples/input-type-time.html><code><input type="time"></code></a>:
<blockquote>
<p><img src=i/input-type-time.png alt="Opera's type=time picker" width=98 height=22>
</blockquote>
<p>It’s likely that other browsers will eventually support these input types. But just like <a href=#type-email><code>type="email"</code></a> and the other input types, these form fields will be rendered as plain text boxes in browsers that don’t recognize <code>type="date"</code> and the other variants. If you like, you can simply use <code><input type="date"></code> and friends, make Opera users happy, and wait for other browsers to catch up. More realistically, you can use <code><input type="date"></code>, <a href=detect.html#input-types>detect whether the browser has native support for date pickers</a>, and fall back to a scripted solution of your choice (<a href=http://docs.dojocampus.org/dijit/form/DateTextBox>Dojo</a>, <a href=http://docs.jquery.com/UI/Datepicker>jQuery UI</a>, <a href=http://developer.yahoo.com/yui/calendar/>YUI</a>, <a href=http://closure-library.googlecode.com/svn/docs/class_goog_ui_DatePicker.html>Closure Library</a>, or some other solution).
<p class="legend top" style="margin-left:6em"><span class=arrow>↶</span> Date picker with fallback
<pre><code><form>
<input type="date">
</form>
...
<script>
var i = document.createElement("input");
i.setAttribute("type", "date");
if (i.type == "text") {
// No native date picker support :(
// Use Dojo/jQueryUI/YUI/Closure to create one,
// then dynamically replace that <input> element.
}
</script></code></pre>
<p class=a>❧
<h2 id=type-search>Search Boxes</h2>
<p>OK, this one is subtle. Well, the idea is simple enough, but the implementations may require some explanation. Here goes…
<p>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? <code><input type="text"></code>, just like every other text box on the web. Let’s fix that.
<pre style="float:left"><code><form>
<input name="q" <mark>type="search"</mark>>
<input type="submit" value="Find">
</form></code></pre>
<p class="legend right" style="margin-top:2.75em"><span class=arrow> ⇜</span> New-age search box
<p class="clear"><a href=examples/input-type-search.html>Test <code><input type="search"></code> in your own browser</a>. In some browsers, you won’t notice any difference from a regular text box. But if you’re using Safari on Mac OS X, it will look like this:
<p class=c><img src=i/input-type-search-safari.png alt="Safari/Mac rendering input type=search field" width=191 height=121>
<p>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 <code>type="search"</code> 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.
<p class=c><img src=i/input-type-search-safari-typing.png alt="Typing in a type=search field in Safari" width=191 height=121>
<p><a href=http://www.apple.com/>Apple.com</a> uses <code><input type="search"></code> 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 <code>type="search"</code> will treat it like <code>type="text"</code>, so there is absolutely no reason not to start using <code>type="search"</code> for all your search boxes today.
<div class="pf clear">
<h4>Professor Markup Says</h4>
<div class=inner>
<blockquote class=note>
<p>By default, older versions of Safari will not apply even the most basic CSS styles to <code><input type="search"></code> fields. If you want to force Safari to treat your search field like a normal text field (so you can apply your own <abbr>CSS</abbr> styles), add this rule to your stylesheet:
<blockquote><pre><code>input[type="search"] {
-webkit-appearance: textfield;
}</code></pre></blockquote>
<p><i>Thanks to John Lein for teaching me this trick.</i>
</blockquote>
</div>
</div>
<p class=a>❧
<h2 id=type-color>Color Pickers</h2>
<p><abbr>HTML5</abbr> also defines <a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state.html#color-state><code><input type="color"></code></a>, which lets you pick a color and returns the color’s hexadecimal representation. <del>No browser supports it yet, which is a shame, because I’ve always loved <a href=http://earthlingsoft.net/ssp/blog/2006/04/colour_me_picked>the Mac OS color picker</a>. Maybe someday.</del> Good news, everyone! <a href=http://dev.opera.com/articles/view/new-form-features-in-html5/#input-color>Opera 11 now supports <code>type=color</code></a>. 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.
<p class=c><img src=i/input-type-color.png alt="Opera rendering of input type=range field on multiple platforms" width=582 height=444><br><a href=examples/input-type-color.html>Test <code>type="color"</code> for yourself</a>.
<p><i>Thanks to Patrick Lauke and Chris Mills for relicensing this image for inclusion in this book.</i> You should <a href=http://dev.opera.com/articles/view/new-form-features-in-html5/>read their article about the new form features in Opera 11</a>.
<p class=a>❧
<h2 id=validation>Form Validation</h2>
<table class=bc>
<caption>Form validation support</caption>
<thead>
<tr><th title="Internet Explorer">IE<th title="Mozilla Firefox">Firefox<th title="Apple Safari">Safari<th title="Google Chrome">Chrome<th>Opera<th>iPhone<th>Android
<tbody>
<tr><td>·<td>4.0+<td>5.0+<td>10.0+<td>9.0+<td>·<td>·
</table>
<p>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 <abbr>HTML5</abbr> 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. <abbr>HTML5</abbr> can never replace your server-side validation, but it might someday replace your client-side validation.
<p>There are two big problems with validating email addresses in JavaScript:
<ol>
<li>A surprising number of your visitors (probably around 10%) won’t have JavaScript enabled
<li>You’ll get it wrong
</ol>
<p>Seriously, you’ll get it wrong. Determining whether a random string of characters is a valid email address <a href="http://www.regular-expressions.info/email.html">is unbelievably complicated</a>. The harder you look, <a href="http://www.ex-parrot.com/pdw/Mail-RFC822-Address.html">the more complicated it gets</a>. Did I mention it’s <a href="http://haacked.com/archive/2007/08/21/i-knew-how-to-validate-an-email-address-until-i.aspx">really, really complicated</a>? Wouldn’t it be easier to offload the entire headache to your browser?
<p class="legend top" style="width:500px;text-align:center">Most modern browsers validate type=“email” <span class=arrow>↷</span><br></p>
<p class=c><img src=i/input-type-email-validation.png alt="error message on invalid type=email field" width=243 height=76>
<p>That screenshot is from Opera 10, although the functionality has been present since Opera 9. <a href=http://blog.mozilla.com/webdev/2011/03/14/html5-form-validation-on-sumo/>Firefox 4 and Chrome 10 provide similar functionality</a>. The only markup involved is <a href=#type-email>setting the <code>type</code> attribute to <code>"email"</code></a>. When the user tries to submit a form with an <code><input type="email"></code> field, the browser automatically offers <abbr>RFC</abbr>-compliant email validation, even if scripting is disabled.
<p><abbr>HTML5</abbr> also offers validation of web addresses entered into <code><input type="url"></code> fields, and numbers in <code><input type="number"></code> fields. The validation of numbers even takes into account the <code>min</code> and <code>max</code> attributes, so browsers will not let you submit the form if you enter a number that is too large.
<p class=c><img src=i/input-type-number-validation.png alt="error message on invalid type=number field" width=135 height=76>
<p>There is no markup required to activate <abbr>HTML5</abbr> form validation; it is on by default. To turn it off, use the <code>novalidate</code> attribute.
<p class="legend top">Don’t validate me, bro <span class=arrow>↷</span><br></p>
<pre><code><form <mark>novalidate</mark>>
<input type="email" id="addr">
<input type="submit" value="Subscribe">
</form></code></pre>
<p class=a>❧
<h2 id=required>Required Fields</h2>
<table class=bc>
<caption><input required> support</caption>
<thead>
<tr><th title="Internet Explorer">IE<th title="Mozilla Firefox">Firefox<th title="Apple Safari">Safari<th title="Google Chrome">Chrome<th>Opera<th>iPhone<th>Android
<tbody>
<tr><td>·<td>4.0+<td>·<td>10.0+<td>9.0+<td>·<td>·
</table>
<p><a href=#validation><abbr>HTML5</abbr> form validation</a> isn’t limited to the type of each field. You can also specify that certain fields are required. Required fields must have a value before you can submit the form.
<p>The markup for required fields is as simple as can be:
<pre><code><form>
<input id="q" <mark>required</mark>>
<input type="submit" value="Search">
</form></code></pre>
<p class="clear"><a href=examples/input-required.html>Test <code><input required></code> in your own browser</a>. Browsers may alter the default appearance of required fields. For example, this is what a required field looks like in Mozilla Firefox 4.0:
<p class=c><img src=i/input-required.png alt="default appearance of required fields in Firefox" width=250 height=122>
<p>Furthermore, if you attempt to submit the form without filling in the required value, Firefox will pop up an infobar telling you that the field is mandatory and can not be left blank.
<p class=a>❧
<h2 id=further-reading>Further Reading</h2>
<p>Specifications and standards:
<ul>
<li><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#states-of-the-type-attribute><code><input></code> types</a>
<li><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#the-placeholder-attribute>the <code><input placeholder></code> attribute</a>
<li><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#autofocusing-a-form-control>the <code><input autofocus></code> attribute</a>
<li><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#attr-fs-novalidate>the <code><form novalidate></code> attribute</a>
<li><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#the-required-attribute>The <code><input required></code> attribute</a>
</ul>
<p>JavaScript libraries:
<ul>
<li><a href=http://www.modernizr.com/>Modernizr</a>, an <abbr>HTML5</abbr> detection library
</ul>
<p>Useful articles:
<ul>
<li><a href=http://www.alistapart.com/articles/forward-thinking-form-validation/>Forward Thinking Form Validation</a>
<li><a href=http://dev.opera.com/articles/view/new-form-features-in-html5/>New form features in Opera 11</a>
<li><a href=https://developer.mozilla.org/en/HTML/HTML5/Forms_in_HTML5>Mozilla Developer Center: Forms in HTML5</a>
<li><a href=https://developer.mozilla.org/en/HTML/HTML5/Forms_in_HTML5><abbr>HTML5</abbr> Forms in Mozilla Firefox 4.0+</a>
<li><a href=http://blog.mozilla.com/webdev/2011/03/14/html5-form-validation-on-sumo/>HTML5 Form Validation</a>
</ul>
<p class=a>❧
<p>This has been “A Form of Madness.” The <a href=table-of-contents.html>full table of contents</a> has more if you’d like to keep reading.
<div class=pf>
<h4>Did You Know?</h4>
<div class=moneybags>
<blockquote><p>In association with Google Press, O’Reilly is distributing this book in a variety of formats, including paper, ePub, Mobi, and <abbr>DRM</abbr>-free <abbr>PDF</abbr>. The paid edition is called “HTML5: Up & Running,” and it is available now. This chapter is included in the paid edition.
<p>If you liked this chapter and want to show your appreciation, you can <a href="http://www.amazon.com/HTML5-Up-Running-Mark-Pilgrim/dp/0596806027?ie=UTF8&tag=diveintomark-20&creativeASIN=0596806027">buy “HTML5: Up & Running” with this affiliate link</a> or <a href=http://oreilly.com/catalog/9780596806033>buy an electronic edition directly from O’Reilly</a>. You’ll get a book, and I’ll get a buck. I do not currently accept direct donations.
</blockquote>
</div>
</div>
<p class=c>Copyright MMIX–MMXI <a href=about.html>Mark Pilgrim</a>
<form action=http://www.google.com/cse><div><input type=hidden name=cx value=013556084273090989037:f1s-wnbz68q><input type=hidden name=ie value=UTF-8><input type=search name=q size=25 placeholder="powered by Google™"> <input type=submit name=sa value=Hledat></div></form>
<script src=j/jquery.js></script>
<script src=j/modernizr.js></script>
<script src=j/dih5.js></script>
<script type="text/javascript"><!--
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-25728182-1']);
_gaq.push(['_setDomainName', '.html5.cz']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
// --></script>