forked from diveintohtml5-zh-cn/diveintohtml5.zh-cn
-
Notifications
You must be signed in to change notification settings - Fork 2
/
extensibility.html
950 lines (710 loc) · 88.4 KB
/
extensibility.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
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
<!DOCTYPE html>
<meta charset=utf-8>
<title>Distributed Extensibility - Dive Into HTML5</title>
<!--[if lt IE 9]><script src=j/html5.js></script><![endif]-->
<link rel="shortcut icon" href=favicon.ico>
<link rel=alternate type=application/atom+xml href=http://hg.diveintohtml5.org/hgweb.cgi/atom-log>
<link rel=stylesheet href=screen.css>
<style>
body{counter-reset:h1 10}
.st td{vertical-align:top;padding-left:5px}
.st ul{list-style:none;margin:0;padding:0}
pre{padding-left:0}
.follow{text-align:center;font-size:small}
.fakeresults,.fakeresults p{font:small/1.2 "Arial Unicode MS",Arial,FreeSerif,"DejaVu Sans",sans-serif}
.fakeresults a{color:#00c !important;text-decoration:underline !important;border-bottom:0 !important}
.fakeresults p{margin:0;padding:0}
.fakelink{color:#00c;cursor:pointer;text-decoration:underline}
.fakeinfo{color:grey}
.fakeurl{color:green}
.fakestar{color:orange;-webkit-text-stroke:0.5px grey}
table.faketable{border-collapse:collapse}
.padright{padding-right:18px}
</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#extensibility>Dive Into <abbr>HTML5</abbr></a> <span class=u>‣</span>
<h1><br>“Distributed,”<br>“Extensibility,”<br>&<br>Other Fancy Words</h1>
<p id=toc>
<p class=a>❧
<h2 id=divingin>Diving In</h2>
<p class=f><img src=i/aoc-t.png alt=T width=107 height=105>here are <a href=http://simon.html5.org/html5-elements>over 100 elements</a> in <abbr>HTML5</abbr>. Some are <a href=semantics.html>purely semantic</a>, others are <a href=canvas.html>just containers for scripted <abbr>APIs</abbr></a>. Throughout <a href=past.html>the history of <abbr>HTML</abbr></a>, standards wonks have argued about which elements should be included in the language. Should <abbr>HTML</abbr> include a <code><figure></code> element? A <code><person></code> element? How about a <code><rant></code> element? Decisions are made, specs are written, authors author, implementors implement, and the web lurches ever forward.
<p>Of course, <abbr>HTML</abbr> can’t please everyone. No standard can. Some ideas don’t make the cut. For example, there is no <code><person></code> element in <abbr>HTML5</abbr>. (There’s no <code><rant></code> element either, damn it!) There’s nothing stopping you from including a <code><person></code> element in a web page, but <a href=http://html5.validator.nu/>it won’t validate</a>, <a href=semantics.html#unknown-elements>it won’t work consistently across browsers</a>, and it might conflict with future <abbr>HTML</abbr> specs if we want to add it later.
<p>Right, so if making up your own elements isn’t the answer, what’s a semantically inclined web author to do? There have been attempts to extend previous versions of <abbr>HTML</abbr>. The most popular method is <a href=http://microformats.org/>microformats</a>, which uses the <code>class</code> and <code>rel</code> attributes in <abbr>HTML</abbr> 4. Another option is <a href=http://www.w3.org/TR/rdfa-syntax/>RDFa</a>, which was originally designed to be used in <a href=past.html#postscript><abbr>XHTML</abbr></a> but is now <a href=http://www.w3.org/TR/rdfa-in-html/>being ported to <abbr>HTML</abbr></a> as well.
<p>Microformats and <abbr>RDFa</abbr> each have their strengths and weaknesses. They take radically different approaches towards the same goal: extending web pages with additional semantics that are not part of the core <abbr>HTML</abbr> language. I don’t intend to turn this chapter into a format flamewar. (That would definitely require a <code><rant></code> element!) Instead, I want to focus on a third option which is part of, and tightly integrated into, <abbr>HTML5</abbr> itself: microdata.
<p class=a>❧
<h2 id=what-is-microdata>What is Microdata?</h2>
<p>Each word in the following sentence is important, so pay attention.
<div class=pf>
<h4>Professor Markup Says</h4>
<div class=inner>
<blockquote>
<p>Microdata annotates the <abbr>DOM</abbr> with scoped name/value pairs from custom vocabularies.
</blockquote>
</div>
</div>
<p>Now what does that mean? Let’s start from the end and work backwards. Microdata centers around custom vocabularies. Think of “the set of all <abbr>HTML5</abbr> elements” as one vocabulary. This vocabulary includes elements to represent <a href=semantics.html#new-elements>a section or an article</a>, but it doesn’t include elements to represent a person or an event. If you want to represent a person on a web page, you’ll need to define your own vocabulary. Microdata lets you do this. Anyone can define a microdata vocabulary and start embedding custom properties in their own web pages.
<p>The next thing to know about microdata is that it works with name/value pairs. Every microdata vocabulary defines a set of named properties. For example, a Person vocabulary could define properties like <code>name</code> and <code>photo</code>. To include a specific microdata property on your web page, you provide the property name in a specific place. Depending on where you declare the property name, microdata has rules about how to extract the property value. (More on this in the next section.)
<p>Along with named properties, microdata relies heavily on the concept of “scoping.” The simplest way to think of microdata scoping is to think about the natural parent-child relationship of elements in the <abbr>DOM</abbr>. The <a href=semantics.html#html-element><code><html></code></a> element usually contains two children, <a href=semantics.html#head-element><code><head></code></a> and <code><body></code>. The <code><body></code> element usually contains multiple children, each of which may have child elements of their own. For example, your page might include an <code><h1></code> element within an <code><hgroup></code> element within a <a href=semantics.html#header-element><code><header></code></a> element within the <code><body></code> element. A data table might contain <code><td></code> within <code><tr></code> within <code><table></code> (within <code><body></code>). Microdata re-uses the hierarchical structure of the <abbr>DOM</abbr> itself to provide a way to say “all the properties within <em>this</em> element are taken from <em>this</em> vocabulary.” This allows you to use more than one microdata vocabulary on the same page. You can even nest microdata vocabularies within other vocabularies, all by re-using the natural structure of the <abbr>DOM</abbr>. (I’ll show multiple examples of nested vocabularies throughout this chapter.)
<p>Now, I’ve already touched on the <abbr>DOM</abbr>, but let me elaborate on that. Microdata is about applying additional semantics to <em>data that’s already visible on your web page</em>. Microdata is not designed to be a standalone data format. It’s a complement to <abbr>HTML</abbr>. As you’ll see in the next section, microdata works best when you’re already using <abbr>HTML</abbr> correctly, but the <abbr>HTML</abbr> vocabulary isn’t quite expressive enough. Microdata is great for fine-tuning the semantics of data that’s already in the <abbr>DOM</abbr>. If the data you’re <span title="I totally just made that up">semanti-fying</span> isn’t in the <abbr>DOM</abbr>, you should step back and re-evaluate whether microdata is the right solution.
<p>Does this sentence make more sense now? “Microdata annotates the <abbr>DOM</abbr> with scoped name/value pairs from custom vocabularies.” I hope so. Let’s see it in action.
<p class=a>❧
<h2 id=data-model>The Microdata Data Model</h2>
<p>Defining your own microdata vocabulary is easy. First, you need a namespace, which is just a <abbr>URL</abbr>. The namespace <abbr>URL</abbr> could actually point to a working web page, although that’s not strictly required. Let’s say I want to create a microdata vocabulary that describes a person. If I own the <code>data-vocabulary.org</code> domain, I’ll use the <abbr>URL</abbr> <code>http://data-vocabulary.org/Person</code> as the namespace for my microdata vocabulary. That’s an easy way to create a globally unique identifier: pick a <abbr>URL</abbr> on a domain that you control.
<p>In this vocabulary, I need to define some named properties. Let’s start with three basic properties:
<ul>
<li><code>name</code> (your full name)
<li><code>photo</code> (a link to a picture of you)
<li><code>url</code> (a link to a site associated with you, like a weblog or a Google profile)
</ul>
<p>Some of these properties are <abbr>URLs</abbr>, others are plain text. Each of them lends itself to a natural form of markup, even before you start thinking about microdata or vocabularies or whatnot. Imagine that you have a profile page or an “about” page. Your name is probably marked up as a heading, like an <code><h1></code> element. Your photo is probably an <code><img></code> element, since you want people to see it. And any <abbr>URL</abbr>s associated your profile are probably already marked up as hyperlinks, because you want people to be able to click them. For the sake of discussion, let’s say your entire profile is also wrapped in a <code><section></code> element to separate it from the rest of the page content. Thus:
<p class="legend top" style="margin-left:6em"><span class=arrow>↶</span> It’s all about me
<pre><code><section>
<h1>Mark Pilgrim</h1>
<p><img src="http://www.example.com/photo.jpg" alt="[me smiling]"></p>
<p><a href="http://diveintomark.org/">weblog</a></p>
</section></code></pre>
<p>Microdata’s data model is name/value pairs. A microdata property name (like <code>name</code> or <code>photo</code> or <code>url</code> in this example) is always declared on an <abbr>HTML</abbr> element. The corresponding property value is then taken from the element’s <abbr>DOM</abbr>. For most <abbr>HTML</abbr> elements, the property value is simply the text content of the element. But there are a handful of exceptions.
<table id=property-values class=st>
<caption>Where Do Microdata Property Values Come From?</caption>
<tr class=ho><th>Element<th>Value
<tr class=zebra><td><code><meta></code><td><code>content</code> attribute
<tr><td><ul><li><code><audio></code><li><code><embed></code><li><code><iframe></code><li><code><img></code><li><code><source></code><li><code><video></code></ul><td><code>src</code> attribute
<tr class=zebra><td><ul><li><code><a></code><li><code><area></code><li><code><link></code></ul><td><code>href</code> attribute
<tr><td><code><object></code><td><code>data</code> attribute
<tr class=zebra><td><code><time></code><td><code>datetime</code> attribute
<tr><td>all other elements<td>text content
</table>
<p>“Adding microdata” to your page is a matter of adding a few attributes to the <abbr>HTML</abbr> elements you already have. The first thing you always do is declare which microdata vocabulary you’re using, by adding an <code>itemtype</code> attribute. The second thing you always do is declare the scope of the vocabulary, using an <code>itemscope</code> attribute. In this example, all the data we want to semanti-fy is in a <code><section></code> element, so we’ll declare the <code>itemtype</code> and <code>itemscope</code> attributes on the <code><section></code> element.
<pre><code> <section <mark>itemscope</mark> <mark>itemtype="http://data-vocabulary.org/Person"</mark>></code></pre>
<p>Your name is the first bit of data within the <code><section></code> element. It’s wrapped in an <code><h1></code> element. The <code><h1></code> element doesn’t have any special processing in the <a href=#property-values><abbr>HTML5</abbr> microdata data model</a>, so it falls under the “all other elements” rule where the microdata property value is simply the text content of an element. (This would work equally well if your name was wrapped in a <code><p></code>, <code><div></code>, or <code><span></code> element.)
<pre><code> <h1 <mark>itemprop="name"</mark>>Mark Pilgrim</h1></code></pre>
<p>In English, this says “here is the <code>name</code> property of the <code>http://data-vocabulary.org/Person</code> vocabulary, and the value of the property is <code>Mark Pilgrim</code>.”
<p id=person-photo>Next up: the <code>photo</code> property. This is supposed to be a <abbr>URL</abbr>. According to the <a href=#property-values><abbr>HTML5</abbr> microdata data model</a>, the “value” of an <code><img></code> element is its <code>src</code> attribute. Hey look, the <abbr>URL</abbr> of your profile photo is already in an <code><img src></code> attribute. All you need to do is declare that the <code><img></code> element is the <code>photo</code> property.
<pre><code> <p><img <mark>itemprop="photo"</mark>
src="http://www.example.com/photo.jpg"
alt="[me smiling]"></p></code></pre>
<p>In English, this says “here is the <code>photo</code> property of the <code>http://data-vocabulary.org/Person</code> vocabulary, and the value of the property is <code>http://www.example.com/photo.jpg</code>.
<p>Finally, the <code>url</code> property is also a <abbr>URL</abbr>. According to the <a href=#property-values><abbr>HTML5</abbr> microdata data model</a>, the “value” of an <code><a></code> element is its <code>href</code> attribute. And once again, this fits perfectly with your existing markup. All you need to do is say that your existing <code><a></code> element is the <code>url</code> property:
<pre><code> <a <mark>itemprop="url"</mark> href="http://diveintomark.org/">dive into mark</a></code></pre>
<p>In English, this says “here is the <code>url</code> property of the <code>http://data-vocabulary.org/Person</code> vocabulary, and the value of the property is <code>http://diveintomark.org/</code>.
<p>Of course, if your markup looks a little different, that’s not a problem. You can add microdata properties and values to any <abbr>HTML</abbr> markup, even really gnarly 20th-century-era, tables-for-layout, Oh-God-why-did-I-agree-to-maintain-this markup. While I don’t recommend this kind of markup, it is still common, and you can still add microdata to it.
<p class="legend top" style="margin-left:6em"><span class=arrow>↶</span> For the love of God, don’t do this
<pre><code><TABLE>
<TR><TD>Name<TD>Mark Pilgrim
<TR><TD>Link<TD>
<A href=# onclick=goExternalLink()>http://diveintomark.org/</A>
</TABLE></code></pre>
<p>For marking up the <code>name</code> property, just add an <code>itemprop</code> attribute on the table cell that contains the name. Table cells have no special rules in the microdata property value table, so they get the default value, “the microdata property is the text content.”
<pre><code> <TR><TD>Name<TD <mark>itemprop="name"</mark>>Mark Pilgrim</code></pre>
<p>Adding the <code>url</code> property looks trickier. This markup doesn’t use the <code><a></code> element properly. Instead of putting the link target in the <code>href</code> attribute, it has nothing useful in the <code>href</code> attribute and uses Javascript in the <code>onclick</code> attribute to call a function (not shown) that extracts the <abbr>URL</abbr> and navigates to it. For extra “holy fuck, please stop doing that” bonus points, let’s pretend that the function also opens the link in a tiny popup window with no scroll bars. Wasn’t the internet fun last century?
<p>Anyway, you can still convert this into a microdata property, you just need to be a little creative. Using the <code><a></code> element directly is out of the question. The link target isn’t in the <code>href</code> attribute, and there’s no way to override the rule that says “in an <code><a></code> element, look for the microdata property value in the <code>href</code> attribute.” But you <em>can</em> add a wrapper element around the entire mess, and use that to add the <code>url</code> microdata property.
<p class="legend top" style="margin-left:6em"><span class=arrow>↶</span> This is what you get for subverting HTML
<pre><code><TABLE itemscope itemtype="http://data-vocabulary.org/Person">
<TR><TD>Name<TD>Mark Pilgrim
<TR><TD>Link<TD>
<mark><span itemprop="url"></mark>
<A href=# onclick=goExternalLink()>http://diveintomark.org/</A>
<mark></span></mark>
</TABLE></code></pre>
<p>Since the <code><span></code> element has no special processing, it uses the default rule, “the microdata property is the text content.” “Text content” doesn’t mean “all the markup inside this element” (like you would get with, say, the <code>innerHTML</code> <abbr>DOM</abbr> property). It means “just the text, ma’am.” In this case, <code>http://diveintomark.org/</code>, the text content of the <code><a></code> element inside the <code><span></code> element.
<p>To sum up: you can add microdata properties to any markup. If you’re using <abbr>HTML</abbr> correctly, you’ll find it easier to add microdata than if your <abbr>HTML</abbr> markup sucks, but it can always be done.
<p class=a>❧
<h2 id=person>Marking Up People</h2>
<p>By the way, the starter examples in the previous section weren’t completely made up. There really is a microdata vocabulary for marking up information about people, and it really is that easy. Let’s take a closer look.
<p>The easiest way to integrate microdata into a personal website is on your “about” page. You <em>do</em> have an “about” page, don’t you? If not, you can follow along as I extend <a href=examples/person.html>this sample “about” page</a> with additional semantics. The final result is here: <a href=examples/person-plus-microdata.html>person-plus-microdata.html</a>.
<p>Let’s look at the raw markup first, before any microdata properties have been added:
<pre><code><section>
<img width="204" height="250"
src="http://diveintohtml5.org/examples/2000_05_mark.jpg"
alt="[Mark Pilgrim, circa 2000]">
<h1>Contact Information</h1>
<dl>
<dt>Name</dt>
<dd>Mark Pilgrim</dd>
<dt>Position</dt>
<dd>Developer advocate for Google, Inc.</dd>
<dt>Mailing address</dt>
<dd>
100 Main Street<br>
Anytown, PA 19999<br>
USA
</dd>
</dl>
<h1>My Digital Footprints</h1>
<ul>
<li><a href="http://diveintomark.org/">weblog</a></li>
<li><a href="http://www.google.com/profiles/pilgrim">Google profile</a></li>
<li><a href="http://www.reddit.com/user/MarkPilgrim">Reddit.com profile</a></li>
<li><a href="http://www.twitter.com/diveintomark">Twitter</a></li>
</ul>
</section>
</code></pre>
<p>The first thing you always need to do is declare the vocabulary you’re using, and the scope of the properties you want to add. You do this by adding the <code>itemtype</code> and <code>itemscope</code> attributes on the outermost element that contains the other elements that contain the actual data. In this case, that’s a <code><section></code> element.
<pre><code><section <mark>itemscope</mark> <mark>itemtype="http://data-vocabulary.org/Person"</mark>></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/person.html>person.html</a>, after: <a href=examples/person-plus-microdata.html>person-plus-microdata.html</a>]
<p>Now you can start defining microdata properties from the <code>http://data-vocabulary.org/Person</code> vocabulary. But what are those properties? As it happens, you can see the list of properties by navigating to <a href=http://data-vocabulary.org/Person>data-vocabulary.org/Person</a> in your browser. The microdata specification does not require this, but I’d say it’s certainly a “best practice.” After all, if you want developers to actually <em>use</em> your microdata vocabulary, you need to document it. And where better to put your documentation than the vocabulary <abbr>URL</abbr> itself?
<table class=st>
<caption>Person vocabulary</caption>
<tr class=ho><th>Property<th>Description
<tr class=zebra><td><code>name</code><td>Name
<tr><td><code>nickname</code><td>Nickname
<tr class=zebra><td><code>photo</code><td>An image link
<tr><td><code>title</code><td>The person’s title (for example, “Financial Manager”)
<tr class=zebra><td><code>role</code><td>The person’s role (for example, “Accountant”)
<tr><td><code>url</code><td>Link to a web page, such as the person’s home page
<tr class=zebra><td><code>affiliation</code><td>The name of an organization with which the person is associated (for example, an employer)
<tr><td><code>friend</code><td>Identifies a social relationship between the person described and another person
<tr class=zebra><td><code>contact</code><td>Identifies a social relationship between the person described and another person
<tr><td><code>acquaintance</code><td>Identifies a social relationship between the person described and another person
<tr class=zebra><td><code>address</code><td>The location of the person. Can have the subproperties <code>street-address</code>, <code>locality</code>, <code>region</code>, <code>postal-code</code>, and <code>country-name</code>.
</table>
<p>The first thing in <a href=examples/person-plus-microdata.html>this sample “about” page</a> is a picture of me. Naturally, it’s marked up with an <code><img></code> element. To declare that this <code><img></code> element is my profile picture, all we need to do is add <code>itemprop="photo"</code> to the <code><img></code> element.
<pre><code> <img <mark>itemprop="photo"</mark> width="204" height="250"
src="http://diveintohtml5.org/examples/2000_05_mark.jpg"
alt="[Mark Pilgrim, circa 2000]"></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/person.html>person.html</a>, after: <a href=examples/person-plus-microdata.html>person-plus-microdata.html</a>]
<p>Where’s the microdata property value? It’s already there, in the <code>src</code> attribute. If you recall from the <a href=#property-values><abbr>HTML5</abbr> microdata data model</a>, the “value” of an <code><img></code> element is its <code>src</code> attribute. Every <code><img></code> element has a <code>src</code> attribute — otherwise it would just be a broken image — and the <code>src</code> is always a <abbr>URL</abbr>. See? If you’re using <abbr>HTML</abbr> correctly, microdata is easy.
<p>Furthermore, this <code><img></code> element isn’t alone on the page. It’s a child element of the <code><section></code> element, the one we just declared with the <code>itemscope</code> attribute. Microdata reuses the parent-child relationship of elements on the page to define the scoping of microdata properties. In plain English, we’re saying, “This <code><section></code> element represents a person. Any microdata properties you might find on the children of the <code><section></code> element are properties of that person.” If it helps, you can think of the <code><section></code> element has the subject of a sentence. The <code>itemprop</code> attribute represents the verb of the sentence, something like “is pictured at.” The microdata property value represents the object of the sentence.
<blockquote>
<p>This person [explicit, from <code><section itemscope itemtype="..."></code>]
<p>is pictured at [explicit, from <code><img itemprop="photo"></code>]
<p><code>http://diveintohtml5.org/examples/2000_05_mark.jpg</code> [implicit, from <code><img src></code> attribute]
</blockquote>
<p>The subject only needs to be defined once, by putting <code>itemscope</code> and <code>itemtype</code> attributes on the outermost <code><section></code> element. The verb is defined by putting the <code>itemprop="photo"</code> attribute on the <code><img></code> element. The object of the sentence doesn’t need any special markup at all, because the <a href=#property-values><abbr>HTML5</abbr> microdata data model</a> says that the property value of an <code><img></code> element is its <code>src</code> attribute.
<p>Moving on to the next bit of markup, we see an <code><h1></code> header and the beginnings of a <code><dl></code> list. Neither the <code><h1></code> nor the <code><dl></code> need to be marked up with microdata. Not every piece of <abbr>HTML</abbr> needs to be a microdata property. Microdata is about the properties themselves, not the markup or headers surrounding the properties. This <code><h1></code> isn’t a property; it’s just a header. Similarly, the <code><dt></code> that says “Name” isn’t a property; it’s just a label.
<p class="legend top" style="margin-left:8em"><span class=arrow>↶</span> Boring
<p class="legend left" style="margin-top:2.2em">Boring <span class=arrow>⇝</span> </p>
<pre><code> <h1><mark>Contact Information</mark></h1>
<dl>
<dt><mark>Name</mark></dt>
<dd>Mark Pilgrim</dd></code></pre>
<p>So where is the real information? It’s in the <code><dd></code> element, so that’s where we need to put the <code>itemprop</code> attribute. Which property is it? It’s the <code>name</code> property. Where is the property value? It’s the text within the <code><dd></code> element. Does that need to be marked up? the <a href=#property-values><abbr>HTML5</abbr> microdata data model</a> says no, <code><dd></code> elements have no special processing, so the property value is just the text within the element.
<p class="legend top" style="margin-left:5em"><span class=arrow>↶</span> That’s my name, don’t wear it out </p>
<pre><code> <dd <mark>itemprop="name"</mark>>Mark Pilgrim</dd></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/person.html>person.html</a>, after: <a href=examples/person-plus-microdata.html>person-plus-microdata.html</a>]
<p>What did we just say, in English? “This person’s name is Mark Pilgrim.” Well OK then. Onward.
<p id=title-and-affiliation>The next two properties are a little tricky. This is the markup, pre-microdata:
<pre><code> <dt>Position</dt>
<dd>Developer advocate for Google, Inc.</dd></code></pre>
<p>If you look at the definition of the Person vocabulary, the text “Developer advocate for Google, Inc.” actually encompasses <em>two</em> properties: <code>title</code> (“Developer advocate”) and <code>affiliation</code> (“Google, Inc.”). How can you express that in microdata? The short answer is, you can’t. Microdata doesn’t have a way to break up runs of text into separate properties. You can’t say “the first 18 characters of this text is one microdata property, and the last 12 characters of this text is another microdata property.”
<p>But all is not lost. Imagine that you wanted to style the text “Developer advocate” in a different font from the text “Google, Inc.” <abbr>CSS</abbr> can’t do that either. So what would you do? You would first need to wrap the different bits of text in dummy elements, like <code><span></code>, then apply different <abbr>CSS</abbr> rules to each <code><span></code> element.
<p>This technique is also useful for microdata. There are two distinct pieces of information here: a <code>title</code> and an <code>affiliation</code>. If you wrap each piece in a dummy <code><span></code> element, you can declare that each <code><span></code> is a separate microdata property.
<pre><code> <dt>Position</dt>
<dd><span <mark>itemprop="title"</mark>>Developer advocate</span> for
<span <mark>itemprop="affiliation"</mark>>Google, Inc.<span></dd></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/person.html>person.html</a>, after: <a href=examples/person-plus-microdata.html>person-plus-microdata.html</a>]
<p>Tada! “This person’s title is 'Developer advocate.' This person is employed by Google, Inc.” Two sentences, two microdata properties. A little more markup, but a worthwhile tradeoff.
<p id=address>The same technique is useful for marking up street addresses. The Person vocabulary defines an <code>address</code> property, which itself is a microdata item. That means the address has its own vocabulary (<code>http://data-vocabulary.org/Address</code>) and defines its own properties. The Address vocabulary defines 5 properties: <code>street-address</code>, <code>locality</code>, <code>region</code>, <code>postal-code</code>, and <code>country-name</code>.
<p>If you’re a programmer, you are probably familiar with dot notation to define objects and their properties. Think of the relationship like this:
<ul>
<li><code>Person</code>
<li><code>Person.address</code>
<li><code>Person.address.street-address</code>
<li><code>Person.address.locality</code>
<li><code>Person.address.region</code>
<li><code>Person.address.postal-code</code>
<li><code>Person.address.country-name</code>
</ul>
<p>In this example, the entire street address is contained in a single <code><dd></code> element. (Once again, the <code><dt></code> element is just a label, so it plays no role in adding semantics with microdata.) Notating the <code>address</code> property is easy. Just add an <code>itemprop</code> attribute on the <code><dd></code> element.
<pre><code> <dt>Mailing address</dt>
<dd <mark>itemprop="address"</mark>></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/person.html>person.html</a>, after: <a href=examples/person-plus-microdata.html>person-plus-microdata.html</a>]
<p>But remember, the address property is itself a microdata item. That means we need to add the <code>itemscope</code> and <code>itemtype</code> attributes too.
<pre><code> <dt>Mailing address</dt>
<dd itemprop="address" <mark>itemscope</mark>
<mark>itemtype="http://data-vocabulary.org/Address"</mark>></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/person.html>person.html</a>, after: <a href=examples/person-plus-microdata.html>person-plus-microdata.html</a>]
<p>We’ve seen all of this before, but only for top-level items. A <code><section></code> element defines <code>itemtype</code> and <code>itemscope</code>, and all the elements within the <code><section></code> element that define microdata properties are “scoped” within that specific vocabulary. But this is the first time we’ve seen <em>nested</em> scopes — defining a new <code>itemtype</code> and <code>itemscope</code> (on the <code><dd></code> element) within an existing one (on the <code><section></code> element). This nested scope works exactly like the <abbr>HTML</abbr> <abbr>DOM</abbr>. The <code><dd></code> element has a certain number of child elements, all of which are scoped to the vocabulary defined on the <code><dd></code> element. Once the <code><dd></code> element is closed with a corresponding <code></dd></code> tag, the scope reverts to the vocabulary defined by the parent element (<code><section></code>, in this case).
<p>The properties of the Address suffer the same problem we encountered with <a href=#title-and-affiliation>the <code>title</code> and <code>affiliation</code> properties</a>. There’s just one long run of text, but we want to break it up into five separate microdata properties. The solution is the same: wrap each distinct piece of information in a dummy <code><span></code> element, then declare microdata properties on each <code><span></code> element.
<pre><code> <dd itemprop="address" itemscope
itemtype="http://data-vocabulary.org/Address">
<span <mark>itemprop="street-address"</mark>>100 Main Street</span><br>
<span <mark>itemprop="locality"</mark>>Anytown</span>,
<span <mark>itemprop="region"</mark>>PA</span>
<span <mark>itemprop="postal-code"</mark>>19999</span>
<span <mark>itemprop="country-name"</mark>>USA</span>
</dd>
</dl></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/person.html>person.html</a>, after: <a href=examples/person-plus-microdata.html>person-plus-microdata.html</a>]
<p>In English: “This person has a mailing address. The street address part of the mailing address is '100 Main Street.' The locality part is 'Anytown.' The region is 'PA.' The postal code is '19999.' The country name is 'USA.'” Easy peasy.
<div class="pf clear">
<h4>Ask Professor Markup</h4>
<div class=inner>
<blockquote class=note>
<p><span>☞</span>Q: Is this mailing address format US-specific?<br>
A: No. The properties of the Address vocabulary are generic enough that they can describe most mailing addresses in the world. Not all addresses will have values for every property, but that’s OK. Some addresses might require fitting more than one “line” into a single property, but that’s OK too. For example, if your mailing address has a street address and a suite number, they would both go into the <code>street-address</code> subproperty:
<pre><code><p itemprop="address" itemscope
itemtype="http://data-vocabulary.org/Address">
<span itemprop="street-address">
<mark>100 Main Street
Suite 415</mark>
</span>
...
</p></code></pre>
</blockquote>
</div>
</div>
<p id=person-url>There’s one more thing on this sample “about” page: a list of <abbr>URLs</abbr>. The Person vocabulary has a property for this, called <code>url</code>. A <code>url</code> property can be anything, really. (Well, it has to be a <abbr>URL</abbr>, but you probably guessed that.) What I mean is that the <code>url</code> property is loosely defined. The property can be any sort of <abbr>URL</abbr> that you want to associate with a Person: a weblog, a photo gallery, or a profile on another site like Facebook or Twitter.
<p>The other important thing to note here is that a single Person can have multiple <code>url</code> properties. Technically, any property can appear more than once, but until now, we haven’t taken advantage of that. For example, you could have two <code>photo</code> properties, each pointing to a different image <abbr>URL</abbr>. Here, I want to list four different <abbr>URLs</abbr>: my weblog, my Google profile page, my user profile on Reddit, and my Twitter account. In <abbr>HTML</abbr>, that’s a list of links: four <code><a></code> elements, each in their own <code><li></code> element. In microdata, each <code><a></code> element gets an <code>itemprop="url"</code> attribute.
<pre><code> <h1>My Digital Footprints</h1>
<ul>
<li><a href="http://diveintomark.org/"
<mark>itemprop="url"</mark>>weblog</a></li>
<li><a href="http://www.google.com/profiles/pilgrim"
<mark>itemprop="url"</mark>>Google profile</a></li>
<li><a href="http://www.reddit.com/user/MarkPilgrim"
<mark>itemprop="url"</mark>>Reddit.com profile</a></li>
<li><a href="http://www.twitter.com/diveintomark"
<mark>itemprop="url"</mark>>Twitter</a></li>
</ul></code></pre>
<p>According to the <a href=#property-values><abbr>HTML5</abbr> microdata data model</a>, <code><a></code> elements have special processing. The microdata property value is the <code>href</code> attribute, not the child text content. The text of each link is actually ignored by a microdata processor. Thus, in English, this says “This person has a <abbr>URL</abbr> at <code>http://diveintomark.org/</code>. This person has another <abbr>URL</abbr> at <code>http://www.google.com/profiles/pilgrim</code>. This person has another <abbr>URL</abbr> at <code>http://www.reddit.com/user/MarkPilgrim</code>. This person has another <abbr>URL</abbr> at <code>http://www.twitter.com/diveintomark</code>.”
<h3 id=rich-snippets>Introducing Google Rich Snippets</h3>
<p>I want to step back for just a moment and ask, “Why are we doing this?” Are we adding semantics just for the sake of adding semantics? Don’t get me wrong; I enjoy fiddling with angle brackets as much as the next webhead. But why microdata? Why bother?
<p>There are two major classes of applications that consume <abbr>HTML</abbr>, and by extension, <abbr>HTML5</abbr> microdata:
<ol>
<li>Web browsers
<li>Search engines
</ol>
<p>For browsers, <abbr>HTML5</abbr> defines <a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#microdata-dom-api>a set of <abbr>DOM</abbr> <abbr>APIs</abbr></a> for extracting microdata items, properties, and property values from a web page. As I write this, no browser supports this <abbr>API</abbr>. Not a single one. So that’s… kind of a dead end, at least until browsers catch up and implement the client-side <abbr>APIs</abbr>.
<p>The other major consumer of <abbr>HTML</abbr> is search engines. What could a search engine do with microdata properties about a person? Imagine this: instead of simply displaying the page title and an excerpt of text, the search engine could integrate some of that structured information and display it. Full name, job title, employer, address, maybe even a little thumbnail of a profile photo. Would that catch your attention? It would catch mine.
<p>Google supports microdata as part of their <a href="http://www.google.com/support/webmasters/bin/answer.py?hl=en&answer=99170">Rich Snippets</a> program. When Google’s web crawler parses your page and finds microdata properties that conform to the <code>http://data-vocabulary.org/Person</code> vocabulary, it parses out those properties and stores them alongside the rest of the page data. Google even provides <a href=http://www.google.com/webmasters/tools/richsnippets>a handy tool to see how Google “sees” your microdata properties</a>. Testing it against our <a href=examples/person-plus-microdata.html>sample microdata-enabled “about” page</a> yields this output:
<pre><samp>Item
<b>Type</b>: http://data-vocabulary.org/person
photo = http://diveintohtml5.org/examples/2000_05_mark.jpg
name = Mark Pilgrim
title = Developer advocate
affiliation = Google, Inc.
address = Item( 1 )
url = http://diveintomark.org/
url = http://www.google.com/profiles/pilgrim
url = http://www.reddit.com/user/MarkPilgrim
url = http://www.twitter.com/diveintomark
Item 1
<b>Type</b>: http://data-vocabulary.org/address
street-address = 100 Main Street
locality = Anytown
region = PA
postal-code = 19999
country-name = USA</samp></pre>
<p>It’s all there: the <code>photo</code> property from the <code><img src></code> attribute, all four <abbr>URLs</abbr> from the list of <code><a href></code> attributes, even the address object (listed as “Item 1”) and all five of its subproperties.
<p>And how does Google use all of this information? That depends. There’s no hard and fast rules about how microdata properties should be displayed, which ones should be displayed, or whether they should be displayed at all. If someone searches for “Mark Pilgrim,” <em>and</em> Google determines that this “about” page should rank in the results, <em>and</em> Google decides that the microdata properties it originally found on that page are worth displaying, then the search result listing might look something like this:
<blockquote class=fakeresults>
<p><a href=examples/person-plus-microdata.html>About Mark Pilgrim</a><br>
<span class=fakeinfo>Anytown PA - Developer advocate - Google, Inc.</span><br>
<span class=fakeexcerpt>Excerpt from the page will show up here.<br>
Excerpt from the page will show up here.</span><br>
<span class=fakeurl>diveintohtml5.org/examples/person-plus-microdata.html</span> - <span class=fakelink>Cached</span> - <span class=fakelink>Similar pages</span>
</blockquote>
<p>The first line, “About Mark Pilgrim,” is actually the title of the page, given in the <code><title></code> element. That’s not terribly exciting; Google does that for every page. But the second line is full of information taken directly from the microdata annotations we added to the page. “Anytown PA” was part of the <a href=#address>mailing address</a>, marked up with the <code>http://data-vocabulary.org/Address</code> vocabulary. “Developer advocate” and “Google, Inc.” were two properties from the <code>http://data-vocabulary.org/Person</code> vocabulary (<code>title</code> and <code>affiliation</code>, respectively).
<p>This is really quite amazing. You don’t need to be a large corporation making special deals with search engine vendors to customize your search result listings. Just take ten minutes and add a couple of <abbr>HTML</abbr> attributes to annotate the data you were already publishing anyway.
<div class="pf clear">
<h4>Ask Professor Markup</h4>
<div class=inner>
<blockquote class=note>
<p><span>☞</span>Q: I did everything you said, but my Google search result listing doesn’t look any different. What gives?<br>
A: “<a href="http://www.google.com/support/webmasters/bin/answer.py?hl=en&answer=99170">Google does not guarantee</a> that markup on any given page or site will be used in search results.” But even if Google decides not to use your microdata annotations, another search engine might. Like the rest of <abbr>HTML5</abbr>, microdata is an open standard that anyone can implement. It’s your job to provide as much data as possible. Let the rest of the world decide what to do with it. They might surprise you!
</blockquote>
</div>
</div>
<p class=a>❧
<h2 id=organization>Marking Up Organizations</h2>
<p>Microdata isn’t limited to a single vocabulary. “About” pages are nice, but you probably only have one of them. Still hungry for more? Let’s learn how to mark up organizations and businesses.
<p><a href=examples/organization.html>Here is a sample page of business listings</a>. Let’s look at the original <abbr>HTML</abbr> markup, without microdata.
<pre><code><article>
<h1>Google, Inc.</h1>
<p>
1600 Amphitheatre Parkway<br>
Mountain View, CA 94043<br>
USA
</p>
<p>650-253-0000</p>
<p><a href="http://www.google.com/">Google.com</a></p>
</article></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/organization.html>organization.html</a>, after: <a href=examples/organization-plus-microdata.html>organization-plus-microdata.html</a>]
<p>Short and sweet. All the information about the organization is contained within the <code><article></code> element, so let’s start there.
<pre><code><article <mark>itemscope</mark> <mark>itemtype="http://data-vocabulary.org/Organization"</mark>></code></pre>
<p>As with <a href=#person>marking up people</a>, you need to set the <code>itemscope</code> and <code>itemtype</code> attributes on the outermost element. In this case, the outermost element is an <code><article></code> element. The <code>itemtype</code> attribute declares the microdata vocabulary you’re using (in this case, <code>http://data-vocabulary.org/Organization</code>), and the <code>itemscope</code> attribute declares that all of the properties you set on child elements relate to this vocabulary.
<p>So what’s in the Organization vocabulary? It’s simple and straightforward. In fact, some of it should already look familiar.
<table class=st>
<caption>Organization vocabulary</caption>
<tr class=ho><th>Property<th>Description
<tr class=zebra><td><code>name</code><td>The name of the organization (for example, “Initech”)
<tr><td><code>url</code><td>Link to the organization’s home page
<tr class=zebra><td><code>address</code><td>The location of the organization. Can contain the subproperties <code>street-address</code>, <code>locality</code>, <code>region</code>, <code>postal-code</code>, and <code>country-name</code>.
<tr><td><code>tel</code><td>The telephone number of the organization
<tr class=zebra><td><code>geo</code><td>Specifies the geographical coordinates of the location. Always contains two subproperties, <code>latitude</code> and <code>longitude</code>.
</table>
<p>The first bit of markup within the outermost <code><article></code> element is an <code><h1></code>. This <code><h1></code> element contains the name of a business, so we’ll put an <code>itemprop="name"</code> attribute directly on the <code><h1></code> element.
<pre><code> <h1 <mark>itemprop="name"</mark>>Google, Inc.</h1></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/organization.html>organization.html</a>, after: <a href=examples/organization-plus-microdata.html>organization-plus-microdata.html</a>]
<p>According to the <a href=#property-values><abbr>HTML5</abbr> microdata data model</a>, <code><h1></code> elements don’t need any special processing. The microdata property value is simply the text content of the <code><h1></code> element. In English, we just said “the name of the Organization is 'Google, Inc.'”
<p id=organization-address>Next up is a street address. Marking up the address of an Organization works exactly the same way as <a href=#address>marking up the address of a Person</a>. First, add an <code>itemprop="address"</code> attribute to the outermost element of the street address (in this case, a <code><p></code> element). That states that this is the <code>address</code> property of the Organization. But what about the properties of the address itself? We also need to define the <code>itemtype</code> and <code>itemscope</code> attributes to say that this is an Address item that has its own properties.
<pre><code> <p <mark>itemprop="address"</mark> <mark>itemscope</mark>
<mark>itemtype="http://data-vocabulary.org/Address"</mark>></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/organization.html>organization.html</a>, after: <a href=examples/organization-plus-microdata.html>organization-plus-microdata.html</a>]
<p>Finally, we need to wrap each distinct piece of information in a dummy <code><span></code> element so we can add the appropriate microdata property name (<code>street-address</code>, <code>locality</code>, <code>region</code>, <code>postal-code</code>, and <code>country-name</code>) on each <code><span></code> element.
<pre><code> <p itemprop="address" itemscope
itemtype="http://data-vocabulary.org/Address">
<span <mark>itemprop="street-address"</mark>>1600 Amphitheatre Parkway</span><br>
<span <mark>itemprop="locality"</mark>>Mountain View</span>,
<span <mark>itemprop="region"</mark>>CA</span>
<span <mark>itemprop="postal-code"</mark>>94043</span><br>
<span <mark>itemprop="country-name"</mark>>USA</span>
</p></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/organization.html>organization.html</a>, after: <a href=examples/organization-plus-microdata.html>organization-plus-microdata.html</a>]
<p>In English, we just said “This organization has an address. The street address part is '1600 Amphitheatre Parkway'. The locality is 'Mountain View'. The region part is 'CA'. The postal code is '94043'. The name of the country is 'USA'.”
<p>Next up: a telephone number for the Organization. Telephone numbers are notoriously tricky, and the exact syntax is country-specific. (And if you want to call another country, it’s even worse.) In this example, we have a United States telephone number, in a format suitable for calling from elsewhere in the United States.
<pre><code> <p <mark>itemprop="tel"</mark>>650-253-0000</p></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/organization.html>organization.html</a>, after: <a href=examples/organization-plus-microdata.html>organization-plus-microdata.html</a>]
<p>(Hey, in case you didn’t notice, the Address vocabulary went out of scope when its <code><p></code> element was closed. Now we’re back to defining properties in the Organization vocabulary.)
<p>If you want to list more than one telephone number — maybe one for United States customers and one for international customers — you can do that. Any microdata property can be repeated. Just make sure each telephone number is in its own <abbr>HTML</abbr> element, separate from any label you may give it.
<pre><code>
<p>
US customers: <span <mark>itemprop="tel"</mark>>650-253-0000</span><br>
UK customers: <span <mark>itemprop="tel"</mark>>00 + 1* + 6502530000</span>
</p></code></pre>
<p>According to the <a href=#property-values><abbr>HTML5</abbr> microdata data model</a>, neither the <code><p></code> element nor the <code><span></code> element have special processing. The value of the microdata <code>tel</code> property is simply the text content. The Organization microdata vocabulary makes no attempt to subdivide the different parts of a telephone number. The entire <code>tel</code> property is just free-form text. If you want to put the area code in parentheses, or use spaces instead of dashes to separate the numbers, you can do that. If a microdata-consuming client wants to parse the telephone number, that’s entirely up to them.
<p id=organization-url>Next, we have another familiar property: <code>url</code>. Just like <a href=#person-url>associating a <abbr>URL</abbr> with a Person</a>, you can associate a <abbr>URL</abbr> with an Organization. This could be the company’s home page, a contact page, product page, or anything else. If it’s a <abbr>URL</abbr> about, from, or belonging to the Organization, mark it up with an <code>itemprop="url"</code> attribute.
<pre><code> <p><a <mark>itemprop="url"</mark> href="http://www.google.com/">Google.com</a></p></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/organization.html>organization.html</a>, after: <a href=examples/organization-plus-microdata.html>organization-plus-microdata.html</a>]
<p>According to the <a href=#property-values><abbr>HTML5</abbr> microdata data model</a>, the <code><a></code> element has special processing. The microdata property value is the value of the <code>href</code> attribute, not the link text. In English, this says “this organization is associated with the <abbr>URL</abbr> <code>http://www.google.com/</code>.” It doesn’t say anything more specific about the association, and it doesn’t include the link text “Google.com.”
<p>Finally, I want to talk about geolocation. No, not <a href=geolocation.html>the <abbr>W3C</abbr> Geolocation <abbr>API</abbr></a>. This is about how to mark up the physical location for an Organization, using microdata.
<p>To date, all of our examples have focused on marking up <em>visible</em> data. That is, you have an <code><h1></code> with a company name, so you add an <code>itemprop</code> attribute to the <code><h1></code> element to declare that the (visible) header text is, in fact, the name of an Organization. Or you have an <code><img></code> element that points to a photo, so you add an <code>itemprop</code> attribute to the <code><img></code> element to declare that the (visible) image is a photo of a Person.
<p id=geo>In this example, geolocation information isn’t like that. There is no visible text that gives the exact latitude and longitude (to four decimal places!) of the Organization. In fact, the <a href=examples/organization.html>organization.html</a> example (without microdata) has no geolocation information at all. It has a link to Google Maps, but even the <abbr>URL</abbr> of that link does not contain latitude and longitude coordinates. (It contains similar information in a Google-specific format.) But even if we had a link to a hypothetical online mapping service that did take latitude and longitude coordinates as <abbr>URL</abbr> parameters, microdata has no way of separating out the different parts of a <abbr>URL</abbr>. You can’t declare that the first <abbr>URL</abbr> query parameter is the latitude and the second <abbr>URL</abbr> query parameter is the longitude and the rest of the query parameters are irrelevant.
<p>To handle edge cases like this, <abbr>HTML5</abbr> provides a way to annotate <em>invisible</em> data. This technique should only be used as a last resort. If there is a way to display or render the data you care about, you should do so. Invisible data that only machines can read tends to “go stale” quickly. That is, someone will come along later and update the visible text but forget to update the invisible data. This happens more often than you think, and it <em>will</em> happen to you too.
<p>Still, there are cases where invisible data is unavoidable. Perhaps your boss <em>really</em> wants machine-readable geolocation information but doesn’t want to clutter up the interface with pairs of incomprehensible six-digit numbers. Invisible data is the only option. The only saving grace here is that you can put the invisible data immediately after the visible text that it describes, which may help remind the person who comes along later and updates the visible text that they need to update the invisible data right after it.
<p>In this example, we can create a dummy <code><span></code> element within the same <code><article></code> element as all the other Organization properties, then put the invisible geolocation data inside the <code><span></code> element.
<pre><code> <span <mark>itemprop="geo"</mark> <mark>itemscope</mark>
<mark>itemtype="http://data-vocabulary.org/Geo"</mark>>
<meta itemprop="latitude" content="37.4149" />
<meta itemprop="longitude" content="-122.078" />
</span>
</article></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/organization.html>organization.html</a>, after: <a href=examples/organization-plus-microdata.html>organization-plus-microdata.html</a>]
<p>Geolocation information is defined in its own vocabulary, like <a href=#address>the address of a Person or Organization</a>. Therefore, this <code><span></code> element needs three attributes:
<ol>
<li><code>itemprop="geo"</code> says that this element represents the <code>geo</code> property of the surrounding Organization
<li><code>itemtype="http://data-vocabulary.org/Geo"</code> says which microdata vocabulary this element’s properties conform to
<li><code>itemscope</code> says that this element is the enclosing element for a microdata item with its own vocabulary (given in the <code>itemtype</code> attribute). All the properties within this element are properties of <code>http://data-vocabulary.org/Geo</code>, not the surrounding <code>http://data-vocabulary.org/Organization</code>.
</ol>
<p>The next big question that this example answers is, “How do you annotate invisible data?” You use the <code><meta></code> element. In previous versions of <abbr>HTML</abbr>, you could only use the <code><meta></code> element within <a href=semantics.html#head-element>the <code><head></code> of your page</a>. In <abbr>HTML5</abbr>, you can use the <code><meta></code> element anywhere. And that’s exactly what we’re doing here.
<pre><code><<mark>meta</mark> itemprop="latitude" content="37.4149" /></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/organization.html>organization.html</a>, after: <a href=examples/organization-plus-microdata.html>organization-plus-microdata.html</a>]
<p>According to the <a href=#property-values><abbr>HTML5</abbr> microdata data model</a>, the <code><meta></code> element has special processing. The microdata property value is the <code>content</code> attribute. Since this attribute is never visibly displayed, we have the perfect setup for unlimited quantities of invisible data. With great power comes great responsibility. In this case, the responsibility is on you to ensure that this invisible data stays in sync with the visible text around it.
<p>There is no direct support for the Organization vocabulary in Google Rich Snippets, so I don’t have any pretty sample search result listings to show you. But organizations feature heavily in the next two case studies: events and reviews, and those <em>are</em> supported by Google Rich Snippets.
<p class=a>❧
<h2 id=event>Marking Up Events</h2>
<p>Shit happens. Some shit happens at pre-determined times. Wouldn’t it be nice if you could tell search engines exactly when shit was about to happen? There’s an angle bracket for that.
<p>Let’s start by looking at <a href=examples/event.html>a sample schedule of my speaking engagements</a>.
<pre><code><article>
<h1>Google Developer Day 2009</h1>
<img width="300" height="200"
src="http://diveintohtml5.org/examples/gdd-2009-prague-pilgrim.jpg"
alt="[Mark Pilgrim at podium]">
<p>
Google Developer Days are a chance to learn about Google
developer products from the engineers who built them. This
one-day conference includes seminars and “office hours”
on web technologies like Google Maps, OpenSocial, Android,
AJAX APIs, Chrome, and Google Web Toolkit.
</p>
<p>
<time datetime="2009-11-06T08:30+01:00">2009 November 6, 8:30</time>
&ndash;
<time datetime="2009-11-06T20:30+01:00">20:30</time>
</p>
<p>
Congress Center<br>
5th května 65<br>
140 21 Praha 4<br>
Czech Republic
</p>
<p><a href="http://code.google.com/intl/cs/events/developerday/2009/home.html">GDD/Prague home page</a></p>
</article></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/event.html>event.html</a>, after: <a href=examples/event-plus-microdata.html>event-plus-microdata.html</a>]
<p>All the information about the event is contained within the <code><article></code> element, so that’s where we need to put the <code>itemtype</code> and <code>itemscope</code> attributes.
<pre><code><article <mark>itemscope</mark> <mark>itemtype="http://data-vocabulary.org/Event"</mark>></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/event.html>event.html</a>, after: <a href=examples/event-plus-microdata.html>event-plus-microdata.html</a>]
<p>The <abbr>URL</abbr> for the Event vocabulary is <code><a href=http://data-vocabulary.org/Event>http://data-vocabulary.org/Event</a></code>, which also happens to contain a nice little chart describing the vocabulary’s properties. And what are those properties?
<table class=st>
<caption>Event vocabulary</caption>
<tr class=ho><th>Property<th>Description
<tr class=zebra><td><code>summary</code><td>The name of the event
<tr><td><code>url</code><td>Link to the event details page
<tr class=zebra><td><code>location</code><td>The location or venue of the event. Can optionally be represented by a nested <a href=#organization>Organization</a> or <a href=#address>Address</a>.
<tr><td><code>description</code><td>A description of the event
<tr class=zebra><td><code>startDate</code><td>The starting date and time of the event in <a href=http://www.iso.org/iso/date_and_time_format>ISO date format</a>
<tr><td><code>endDate</code><td>The ending date and time of the event in <a href=http://www.iso.org/iso/date_and_time_format>ISO date format</a>
<tr class=zebra><td><code>duration</code><td>The duration date of the event in <a href=http://en.wikipedia.org/wiki/ISO_8601#Durations>ISO duration format</a>
<tr><td><code>eventType</code><td>The category of the event (for example, “Concert” or “Lecture”). This is a freeform string, not an enumerated attribute.
<tr class=zebra><td><code>geo</code><td>Specifies the geographical coordinates of the location. Always contains two subproperties, <code>latitude</code> and <code>longitude</code>.
<tr><td><code>photo</code><td>A link to a photo or image related to the event
</table>
<p>The event’s name is in an <code><h1></code> element. According to the <a href=#property-values><abbr>HTML5</abbr> microdata data model</a>, <code><h1></code> elements have no special processing. The microdata property value is simply the text content of the <code><h1></code> element. All we need to do is add the <code>itemprop</code> attribute to declare that this <code><h1></code> element contains the name of the event.
<pre><code> <h1 <mark>itemprop="summary"</mark>>Google Developer Day 2009</h1></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/event.html>event.html</a>, after: <a href=examples/event-plus-microdata.html>event-plus-microdata.html</a>]
<p>In English, this says, “The name of this event is Google Developer Day 2009.”
<p>This event listing has a photo, which can be marked up with the <code>photo</code> property. As you would expect, the photo is already marked up with an <code><img></code> element. Like <a href=#person-photo>the <code>photo</code> property in the Person vocabulary</a>, an Event photo is a <abbr>URL</abbr>. Since the <a href=#property-values><abbr>HTML5</abbr> microdata data model</a> says that the property value of an <code><img></code> element is its <code>src</code> attribute, the only thing we need to do is add the <code>itemprop</code> attribute to the <code><img></code> element.
<pre><code> <img <mark>itemprop="photo"</mark> width="300" height="200"
src="http://diveintohtml5.org/examples/gdd-2009-prague-pilgrim.jpg"
alt="[Mark Pilgrim at podium]"></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/event.html>event.html</a>, after: <a href=examples/event-plus-microdata.html>event-plus-microdata.html</a>]
<p>In English, this says, “The photo for this event is at <code>http://diveintohtml5.org/examples/gdd-2009-prague-pilgrim.jpg</code>.”
<p>Next up is a longer description of the event, which is just a pargaraph of freeform text.
<pre><code> <p <mark>itemprop="description"</mark>>Google Developer Days are a chance to
learn about Google developer products from the engineers who built
them. This one-day conference includes seminars and “office
hours” on web technologies like Google Maps, OpenSocial,
Android, AJAX APIs, Chrome, and Google Web Toolkit.</p></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/event.html>event.html</a>, after: <a href=examples/event-plus-microdata.html>event-plus-microdata.html</a>]
<p>The next bit is something new. Events generally occur on specific dates and start and end at specific times. In <abbr>HTML5</abbr>, dates and times should be marked up with <a href=semantics.html#time-element>the <code><time></code> element</a>, and we are already doing that here. So the question becomes, how do we add microdata propeties to these <code><time></code> elements? Looking back at the <a href=#property-values><abbr>HTML5</abbr> microdata data model</a>, we see that the <code><time></code> element has special processing. The value of a microdata property on a <code><time></code> element is the value of the <code>datetime</code> attribute. And hey, the <code>startDate</code> and <code>endDate</code> properties of the Event vocabulary take an <abbr>ISO</abbr>-style date, just like the <code>datetime</code> property of a <code><time></code> element. Once again, the semantics of the core <abbr>HTML</abbr> vocabulary dovetail nicely with semantics of our custom microdata vocabulary. Marking up start and end dates with microdata is as simple as
<ol>
<li>Using <abbr>HTML</abbr> correctly in the first place (using <code><time></code> elements to mark up dates and times), and
<li>Adding a single <code>itemprop</code> attribute
</ol>
<pre><code> <p>
<time <mark>itemprop="startDate"</mark> datetime="2009-11-06T08:30+01:00">2009 November 6, 8:30</time>
&ndash;
<time <mark>itemprop="endDate"</mark> datetime="2009-11-06T20:30+01:00">20:30</time>
</p></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/event.html>event.html</a>, after: <a href=examples/event-plus-microdata.html>event-plus-microdata.html</a>]
<p>In English, this says, “This event starts on November 6, 2009, at 8:30 in the morning, and goes until November 6, 2009, at 20:30 (times local to Prague, <abbr>GMT</abbr>+1).”
<p>Next up is the <code>location</code> property. The <a href=http://data-vocabulary.org/Event>definition of the Event vocabulary</a> says that this can be either an Organization or an Address. In this case, the event is being held at a venue that specializes in conferences, the Congress Center in Prague. Marking it up as an Organization allows us to include the name of the venue as well as its address.
<p>First, let’s declare that the <code><p></code> element that contains the address is the <code>location</code> property of the Event, and that this element is also its own microdata item that conforms to the <code>http://data-vocabulary.org/Organization</code> vocabulary.
<pre><code> <p <mark>itemprop="location"</mark> <mark>itemscope</mark>
<mark>itemtype="http://data-vocabulary.org/Organization"</mark>></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/event.html>event.html</a>, after: <a href=examples/event-plus-microdata.html>event-plus-microdata.html</a>]
<p>Next, mark up the name of the Organization by wrapping the name in a dummy <code><span></code> element and adding an <code>itemprop</code> attribute to the <code><span></code> element.
<pre><code> <span <mark>itemprop="name"</mark>>Congress Center</span><br></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/event.html>event.html</a>, after: <a href=examples/event-plus-microdata.html>event-plus-microdata.html</a>]
<p>Due to the microdata scoping rules, this <code>itemprop="name"</code> is defining a property in the Organization vocabulary, not the Event vocabulary. The <code><p></code> element defined the beginning of the scope of the Organization properties, and that <code><p></code> element hasn’t yet been closed with an <code></p></code> tag. Any microdata properties we define here are properties of the most-recently-scoped vocabulary. Nested vocabularies are like a <a href="http://en.wikipedia.org/wiki/Stack_(data_structure)">stack</a>. We haven’t yet popped the stack, so we’re still talking about properties of the Organization.
<p>In fact, we’re going to add a third vocabulary onto the stack: an Address for the Organization for the Event.
<pre><code>
<span <mark>itemprop="address"</mark> <mark>itemscope</mark>
<mark>itemtype="http://data-vocabulary.org/Address"</mark>></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/event.html>event.html</a>, after: <a href=examples/event-plus-microdata.html>event-plus-microdata.html</a>]
<p>Once again, we want to mark up every piece of the address as a separate microdata property, so we need a slew of dummy <code><span></code> elements to hang our <code>itemprop</code> attributes onto. (If I’m going too fast for you here, go back and read about <a href=#address>marking up the address of a Person</a> and <a href=#organization-address>marking up the address of an Organization</a>.)
<pre><code> <span <mark>itemprop="street-address"</mark>>5th května 65</span><br>
<span <mark>itemprop="postal-code"</mark>>140 21</span>
<span <mark>itemprop="locality"</mark>>Praha 4</span><br>
<span <mark>itemprop="country-name"</mark>>Czech Republic</span></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/event.html>event.html</a>, after: <a href=examples/event-plus-microdata.html>event-plus-microdata.html</a>]
<p>There are no more properties of the Address, so we close the <code><span></code> element that started the Address scope, and pop the stack.
<pre><code> </span></code></pre>
<p>There are no more properties of the Organization, so we close the <code><p></code> element that started the Organization scope, and pop the stack again.
<pre><code> </p></code></pre>
<p>Now we’re back to defining properties on the Event. The next property is <code>geo</code>, to represent the physical location of the Event. This uses the same Geo vocabulary that we used to <a href=#geo>mark up the physical location of an Organization</a> in the previous section. We need a <code><span></code> element to act as the container; it gets the <code>itemtype</code> and <code>itemscope</code> attributes. Within that <code><span></code> element, we need two <code><meta></code> elements, one for the <code>latitude</code> property and one for the <code>longitude</code> property.
<pre><code>
<span <mark>itemprop="geo"</mark> <mark>itemscope</mark> <mark>itemtype="http://data-vocabulary.org/Geo"</mark>>
<meta <mark>itemprop="latitude"</mark> content="50.047893" />
<meta <mark>itemprop="longitude"</mark> content="14.4491" />
</span></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/event.html>event.html</a>, after: <a href=examples/event-plus-microdata.html>event-plus-microdata.html</a>]
<p>And we’ve closed the <code><span></code> that contained the Geo properties, so we’re back to defining properties on the Event. The last property is the <code>url</code> property, which should look familiar. Associating a <abbr>URL</abbr> with an Event works the same way as <a href=#person-url>associating a <abbr>URL</abbr> with a Person</a> and <a href=#organization-url>associating a <abbr>URL</abbr> with an Organization</a>. If you’re using <abbr>HTML</abbr> correctly (marking up hyperlinks with <code><a href></code>), then declaring that the hyperlink is a microdata <code>url</code> property is simply a matter of adding the <code>itemprop</code> attribute.
<pre><code> <p>
<a <mark>itemprop="url"</mark>
href="http://code.google.com/intl/cs/events/developerday/2009/home.html">
GDD/Prague home page
</a>
</p>
</article></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/event.html>event.html</a>, after: <a href=examples/event-plus-microdata.html>event-plus-microdata.html</a>]
<p>The <a href=examples/event.html>sample event page</a> also lists a second event, my speaking engagement at the ConFoo conference in Montréal. For brevity, I’m not going to go through that markup line by line. It’s essentially the same as the event in Prague: an Event item with nested Geo and Address items. I just mention it in passing to reiterate that a single page can have multiple events, each marked up with microdata.
<h3 id=event-rich-snippets>The Return of Google Rich Snippets</h3>
<p><a href="http://www.google.com/webmasters/tools/richsnippets?url=http://diveintohtml5.org/examples/event-plus-microdata.html">According to Google’s Rich Snippets Testing Tool</a>, this is the information that Google’s crawlers will glean from <a href=examples/event-plus-microdata.html>our sample event listing page</a>:
<pre><samp>Item
<b>Type:</b> http://data-vocabulary.org/Event
summary = Google Developer Day 2009
eventType = conference
photo = http://diveintohtml5.org/examples/gdd-2009-prague-pilgrim.jpg
description = Google Developer Days are a chance to learn about Google developer products from the engineers who built them. This one-day conference includes seminars and office hours on web technologies like Goo...
startDate = 2009-11-06T08:30+01:00
endDate = 2009-11-06T20:30+01:00
location = Item(__1)
geo = Item(__3)
url = http://code.google.com/intl/cs/events/developerday/2009/home.html
Item
Id: __1
<b>Type:</b> http://data-vocabulary.org/Organization
name = Congress Center
address = Item(__2)
Item
Id: __2
<b>Type:</b> http://data-vocabulary.org/Address
street-address = 5th května 65
postal-code = 140 21
locality = Praha 4
country-name = Czech Republic
Item
Id: __3
<b>Type:</b> http://data-vocabulary.org/Geo
latitude = 50.047893
longitude = 14.4491</samp></pre>
<p>As you can see, all the information we added in microdata is there. Properties that are separate microdata items are given internal <abbr>IDs</abbr> (<code>Item(__1)</code>, <code>Item(__2)</code> and so on). This is not part of the microdata specification. It’s just a convention that Google’s testing tool uses to linearize the sample output and show you the grouping of nested items and their properties.
<p>Here is how Google might choose to represent this sample page in its search results. (Again, I have to preface this with the disclaimer that this is just an example. Google may change the format of their search results at any time, and there is no guarantee that Google will even pay attention to your microdata markup. Sorry to sound like a broken record, but our lawyers make me say these things.)
<blockquote class=fakeresults>
<p><a href=examples/event-plus-microdata.html>Mark Pilgrim’s event calendar</a><br>
<span class=fakeexcerpt>Excerpt from the page will show up here.<br>
Excerpt from the page will show up here.</span><br>
<table class=faketable>
<tr><td class=padright><a href=http://code.google.com/intl/cs/events/developerday/2009/home.html>Google Developer Day 2009</a><td class="fakeinfo padright">Fri, Nov 6<td class=fakeinfo>Congress Center, Praha 4, Czech Republic
<tr><td class=padright><a href=http://confoo.ca/en>ConFoo.ca 2010</a><td class="fakeinfo padright">Wed, Mar 10<td class=fakeinfo>Hilton Montreal Bonaventure, Montréal, Québec, Canada
</table>
<p><span class=fakeurl>diveintohtml5.org/examples/event-plus-microdata.html</span> - <span class=fakelink>Cached</span> - <span class=fakelink>Similar pages</span>
</blockquote>
<p>After the page title and auto-generated excerpt text, Google starts using the microdata markup we added to the page to display a little table of events. Note the date format: “Fri, Nov 6.” That is not a string that appeared anywhere in our <abbr>HTML</abbr> or microdata markup. We used two fully qualified <abbr>ISO</abbr>-formatted strings, <code>2009-11-06T08:30+01:00</code> and <code>2009-11-06T20:30+01:00</code>. Google took those two dates, figured out that they were on the same day, and decided to display a single date in a more friendly format.
<p>Now look at the physical addresses. Google chose to display just the venue name + locality + country, not the exact street address. This is made possible by the fact that we split up the address into five subproperties — <code>name</code>, <code>street-address</code>, <code>region</code>, <code>locality</code>, and <code>country-name</code> — and marked up each part of the address as a different microdata property. Google takes advantage of that to show an abbreviated address. Other consumers of the same microdata markup might make different choices about what to display or how to display it. There’s no right or wrong choice here. It’s up to you to provide as much data as possible, as accurately as possible. It’s up to the rest of the world to interpret it.
<p class=a>❧
<h2 id=review>Marking Up Reviews</h2>
<p>Here’s another example of making the web (and possibly search result listings) better through markup: business and product reviews.
<p>This is a short review I wrote of my favorite pizza place near my house. (This is a real restaurant, by the way. If you’re ever in Apex, NC, I highly recommend it.) Let’s look at <a href=examples/review.html>the original markup</a>:
<pre><code><article>
<h1>Anna’s Pizzeria</h1>
<p>★★★★☆ (4 stars out of 5)</p>
<p>New York-style pizza right in historic downtown Apex</p>
<p>
Food is top-notch. Atmosphere is just right for a “neighborhood
pizza joint.” The restaurant itself is a bit cramped; if you’re
overweight, you may have difficulty getting in and out of your
seat and navigating between other tables. Used to give free
garlic knots when you sat down; now they give you plain bread
and you have to pay for the good stuff. Overall, it’s a winner.
</p>
<p>
100 North Salem Street<br>
Apex, NC 27502<br>
USA
</p>
<p>— reviewed by Mark Pilgrim, last updated March 31, 2010</p>
</article></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/review.html>review.html</a>, after: <a href=examples/review-plus-microdata.html>review-plus-microdata.html</a>]
<p>This review is contained in an <code><article></code> element, so that’s where we’ll put the <code>itemtype</code> and <code>itemscope</code> attributes. The namespace <abbr>URL</abbr> for this vocabulary is <code>http://data-vocabulary.org/Review</code>.
<pre><code><article <mark>itemscope</mark> <mark>itemtype="http://data-vocabulary.org/Review"</mark>></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/review.html>review.html</a>, after: <a href=examples/review-plus-microdata.html>review-plus-microdata.html</a>]
<p>What are the available properties in the Review vocabulary? I’m glad you asked.
<table class=st>
<caption>Review vocabulary</caption>
<tr class=ho><th>Property<th>Description
<tr class=zebra><td><code>itemreviewed</code><td>The name of the item being reviewed. Can be a product, service, business, <i class=baa>&</i>c.
<tr><td><code>rating</code><td>A numerical quality rating for the item, on a scale from 1 to 5. Can also be a nested <code>http://data-vocabulary.org/Rating</code> vocabulary to use a nonstandard scale.
<tr class=zebra><td><code>reviewer</code><td>The name of the author who wrote the review
<tr><td><code>dtreviewed</code><td>The date that the item was reviewed in <a href=http://www.iso.org/iso/date_and_time_format>ISO date format</a>
<tr class=zebra><td><code>summary</code><td>A short summary of the review
<tr><td><code>description</code><td>The body of the review
</table>
<p>The first property is simple: <code>itemreviewed</code> is just text, and here it’s contained in an <code><h1></code> element, so that’s where we should put the <code>itemprop</code> attribute.
<pre><code> <h1 <mark>itemprop="itemreviewed"</mark>>Anna’s Pizzeria</h1></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/review.html>review.html</a>, after: <a href=examples/review-plus-microdata.html>review-plus-microdata.html</a>]
<p>I’m going to skip over the actual rating and come back to that at the end.
<p>The next two properties are also straightforward. The <code>summary</code> property is a short description of what you’re reviewing, and the <code>description</code> property is the body of the review.
<pre><code> <p <mark>itemprop="summary"</mark>>New York-style pizza right in historic downtown Apex</p>
<p <mark>itemprop="description"</mark>>
Food is top-notch. Atmosphere is just right for a “neighborhood
pizza joint.” The restaurant itself is a bit cramped; if you’re
overweight, you may have difficulty getting in and out of your
seat and navigating between other tables. Used to give free
garlic knots when you sat down; now they give you plain bread
and you have to pay for the good stuff. Overall, it’s a winner.
</p></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/review.html>review.html</a>, after: <a href=examples/review-plus-microdata.html>review-plus-microdata.html</a>]
<p>The <code>location</code> and <code>geo</code> properties aren’t anything we haven’t tackled before. (If you’re just tuning in, check out <a href=#address>marking up the address of a Person</a>, <a href=#organization-address>marking up the address of an Organization</a>, and <a href=#geo>marking up geolocation information</a> from earlier in this chapter.)
<pre><code> <p <mark>itemprop="location"</mark> <mark>itemscope</mark>
<mark>itemtype="http://data-vocabulary.org/Address"</mark>>
<span <mark>itemprop="street-address"</mark>>100 North Salem Street</span><br>
<span <mark>itemprop="locality"</mark>>Apex</span>,
<span <mark>itemprop="region"</mark>>NC</span>
<span <mark>itemprop="postal-code"</mark>>27502</span><br>
<span <mark>itemprop="country-name"</mark>>USA</span>
</p>
<span <mark>itemprop="geo"</mark> <mark>itemscope</mark>
<mark>itemtype="http://data-vocabulary.org/Geo"</mark>>
<meta <mark>itemprop="latitude"</mark> content="35.730796" />
<meta <mark>itemprop="longitude"</mark> content="-78.851426" />
</span></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/review.html>review.html</a>, after: <a href=examples/review-plus-microdata.html>review-plus-microdata.html</a>]
<p>The final line presents a familiar problem: it contains two bits of information in one element. The name of the reviewer is <code>Mark Pilgrim</code>, and the review date is <code>March 31, 2010</code>. How do we mark up these two distinct properties? <a href=#title-and-affiliation>Wrap them in their own elements</a> and put an <code>itemprop</code> attribute on each element. In fact, the date in this example should have been marked up with a <code><time></code> element in the first place, so that provides a natural hook on which to hang our <code>itemprop</code> attribute. The reviewer name can just be wrapped in a dummy <code><span></code> element.
<pre><code> <p>— <span <mark>itemprop="reviewer"</mark>>Mark Pilgrim</span>, last updated
<<mark>time</mark> <mark>itemprop="dtreviewed"</mark> <mark>datetime="2010-03-31"</mark>>
March 31, 2010
</time>
</p>
</article></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/review.html>review.html</a>, after: <a href=examples/review-plus-microdata.html>review-plus-microdata.html</a>]
<p>OK, let’s talk ratings. The trickiest part of marking up a review is the rating. By default, ratings in the Review vocabulary are on a scale of 1–5, 1 being “terrible” and 5 being “awesome.” If you want to use a different scale, you can definitely do that. But let’s talk about the default scale first.
<pre><code> <p>★★★★☆ (<span <mark>itemprop="rating"</mark>>4</span> stars out of 5)</p></code></pre>
<p class=follow>[Follow along! Before: <a href=examples/review.html>review.html</a>, after: <a href=examples/review-plus-microdata.html>review-plus-microdata.html</a>]
<p>If you’re using the default 1–5 scale, the only property you need to mark up is the rating itself (4, in this case). But what if you want to use a different scale? You can do that; you just need to declare the limits of the scale you’re using. For example, if you wanted to use a 0–10 point scale, you would still declare the <code>itemprop="rating"</code> property, but instead of giving the rating value directly, you would use a nested vocabulary of <code>http://data-vocabulary.org/Rating</code> to declare the worst and best values in your custom scale and the actual rating value within that scale.
<pre><code><p <mark>itemprop="rating"</mark> <mark>itemscope</mark>
<mark>itemtype="http://data-vocabulary.org/Rating"</mark>>
★★★★★★★★★☆
(<span <mark>itemprop="value"</mark>>9</span> on a scale of
<span <mark>itemprop="worst"</mark>>0</span> to
<span <mark>itemprop="best"</mark>>10</span>)
</p></code></pre>
<p>In English, this says “the product I’m reviewing has a rating value of 9 on a scale of 0–10.”
<p>Did I mention that review microdata could affect search result listings? Oh yes, it can. Here is the “raw data” that the <a href="http://www.google.com/webmasters/tools/richsnippets?url=http://diveintohtml5.org/examples/review-plus-microdata.html">Google Rich Snippets tool extracted from my microdata-enhanced review</a>:
<pre><samp>Item
<b>Type:</b> http://data-vocabulary.org/Review
itemreviewed = Anna’s Pizzeria
rating = 4
summary = New York-style pizza right in historic downtown Apex
description = Food is top-notch. Atmosphere is just right ...
address = Item(__1)
geo = Item(__2)
reviewer = Mark Pilgrim
dtreviewed = 2010-03-31
Item
Id: __1
<b>Type:</b> http://data-vocabulary.org/Organization
street-address = 100 North Salem Street
locality = Apex
region = NC
postal-code = 27502
country-name = USA
Item
Id: __2
<b>Type:</b> http://data-vocabulary.org/Geo
latitude = 35.730796
longitude = -78.851426</samp></pre>
<p>And here (modulo the whims of Google, the phase of the moon, and so on and so forth) is what my review might look like in a search result listing:
<blockquote class=fakeresults>
<p><a href=examples/review-plus-microdata.html>Anna’s Pizzeria: review</a><br>
<span class=fakeinfo><span class=fakestar>★★★★☆</span> Review by Mark Pilgrim - Mar 31, 2010</span><br>
<span class=fakeexcerpt>Excerpt from the page will show up here.<br>
Excerpt from the page will show up here.</span><br>
<span class=fakeurl>diveintohtml5.org/examples/review-plus-microdata.html</span> - <span class=fakelink>Cached</span> - <span class=fakelink>Similar pages</span>
</blockquote>
<p>Angle brackets don’t impress me much, but I have to admit, that’s pretty cool.
<p class=a>❧
<h2 id=further-reading>Further Reading</h2>
<p>Microdata resources:
<ul>
<li><a href=http://foolip.org/microdatajs/live/>Live microdata playground</a>
<li><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#microdata><abbr>HTML5</abbr> microdata specification</a>
</ul>
<p>Google Rich Snippets resources:
<ul>
<li><a href="http://www.google.com/support/webmasters/bin/answer.py?hl=en&answer=99170">About rich snippets and structured data</a>
<li><a href="http://www.google.com/support/webmasters/bin/answer.py?hl=en&answer=146646">Marking up contact and social networking information</a>
<li><a href="http://www.google.com/support/webmasters/bin/answer.py?hl=en&answer=146861">Businesses <i class=baa>&</i> organizations</a>
<li><a href="http://www.google.com/support/webmasters/bin/answer.py?hl=en&answer=164506">Events</a>
<li><a href="http://www.google.com/support/webmasters/bin/answer.py?hl=en&answer=146645">Reviews</a>
<li><a href="http://www.google.com/support/webmasters/bin/answer.py?hl=en&answer=172705">Review ratings</a>
<li><a href=http://www.google.com/webmasters/tools/richsnippets>Google Rich Snippets Testing Tool</a>
<li><a href=http://knol.google.com/k/google-rich-snippets-tips-and-tricks>Google Rich Snippets Tips and Tricks</a>
</ul>
<p class=a>❧
<p>This has been ‘“Distributed,” “Extensibility,” & Other Fancy Words.’ 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–MMX <a href=about.html>Mark Pilgrim</a>
<form action=http://www.google.com/cse><div><input type=hidden name=cx value=014021643941856155761:6jgee_nxreo><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=Search></div></form>
<script src=j/jquery.js></script>
<script src=j/dih5.js></script>