map

1. 基本情報

説明 リンクをグループ化する
語源 client-side image MAP
所属モジュール Client-side Image Map
所属コンテントセット Inline, InlineFormattable
内容 Heading, Block, area
内容の書式 ( Heading | Block | area )+
関連項目 object, input, img
公式な実装 DTD

2. 属性

2-1. 一般属性

属性 属性値の型 説明
xmlns URI (CDATA)

XMLネームスペースを指定します。XHTML 1.1では、常にhttp://www.w3.org/1999/xhtmlです。

id [必須] ID

この要素を識別する為の識別子を指定します。識別子は同一文書中で重複する事は許されません。

class NMTOKENS

XHTMLに用意された要素では表しきれないものを分別する為に指定します。普通のユーザーエージェントはこの属性によって要素の意味を分別する事はできませんが、スタイルシートなどは処理する事ができるものもあります。

title Text (CDATA)

タイトルを付けたり、補足説明を加えたりします。要素やブラウザによっては、ポイントされるとこの属性がツールチップなどとして表示される事もあります。

I18N [属性コレクション]

国際化(Internationalization)に関する属性を集めたコレクションです。

Events [属性コレクション]

基本的な組み込みイベントを処理する為の属性を集めたコレクションです。

2-2. 固有属性

固有属性はありません。

3. 解説

3-1. 概要

map要素は、リンクをグループ化します。特に、クライアントサイドイメージマップのリンクをグループ化しますクライアントサイドイメージマップ (クリックされた画像の座標から、リンク先をクライアント側で判断してジャンプする機構)に似たような機構にサーバーサイドイメージマップ (クリックされた画像の座標を送信し、リンク先をサーバ側で判断してジャンプする機構)がありますが、その詳細はServer-side Image Mapモジュールを参照して下さい。

クライアントサイドイメージマップは、サーバーサイドイメージマップよりも好まれます。理由は少なくとも二つ挙げる事ができます。

  • アクセシビリティが高い。グラフィカルブラウザ以外のユーザーエージェントにも、等価な選択肢を同時に提供できる。一方、サーバーサイドイメージマップは同時には不可能である。
  • どこにジャンプするのかをすぐ判断する事ができる。グラフィカルブラウザは、ポインタが有効なリンク領域の上に乗っている場合、ジャンプ先をステータスバーなどに表示する事ができる。一方、サーバーサイドイメージマップではどこにジャンプするのか、そもそもジャンプできる位置を指しているのかがすぐには判らない。

ジャンプ先をクライアント側で判断できないというサーバーサイドイメージマップの欠点は、必ずしも欠点であるとは限りませんが、ジャンプ先を意図的に隠す理由が無いのであれば、クライアントサイドイメージマップを使った方が良いでしょう。

3-2. 最もスマートなクライアントサイドイメージマップ

クライアントサイドイメージマップを実現するには、幾つか手段がありますが、最もスマートに実現するのがこれです。object要素の子にmap要素を持たせ、map要素はa要素を孫に持つ事で領域を定義するというものです。

[プログラムコード開始]

<object data="/image/valid-xhtml11" type="image/png" width="440" height="155" usemap="smart-map">
<map id="smart-map">
<div>
<a href="http://www.w3.org/" shape="rect" coords="0,0,185,155">W3C</a>,
<a href="http://www.w3.org/TR/xhtml11" shape="rect" coords="185,0,440,155">XHTML<sup>&trade;</sup> 1.1 - Module-based XHTML</a>
</div>
</map>
</object>

[プログラムコード終了]

順を追って説明しましょう。まず、イメージマップとして使う画像はobject要素で表します。そして、その内容としてイメージマップのリンクを内包するmap要素を書きます。map要素は直接a要素を持てないので、Blockコンテントセットなどの要素(上記の例ではdiv要素)を使って一枚噛ませます。map要素の孫のa要素は、内容でラベル、href属性でリンク先を指定する他、 shape属性で領域の形状を、coords属性でその座標を指定します。map要素をobject要素の子にしただけではクライアントイメージマップとみなされないので、最後に usemap属性でmap要素のid属性値を参照します(つまり、必要があればmap要素をobject要素の外に出しても構いません)。

この方法は、アクセシビリティに関する問題を同時に解決します。

  • グラフィカルブラウザでは、object要素の内容が描画されない。つまり、クライアントサイドイメージマップを正しく理解して閲覧者に提供できる場合に不要となるアンカーテキストが展開されずに済む。
  • 非グラフィカルブラウザでは、object要素の内容が描画される。つまり、テキストブラウザや音声合成ユーザーエージェントなどでは、等価な内容のアンカーテキストが展開される。

この方法は、object要素やmap要素、area要素を全く理解しないユーザーエージェントにすら等価な内容を提供できます。ユーザーエージェントは未知の要素を見つけた場合はただ単にその内容を展開しますから、a要素href属性さえ知っていれば良いのです。

しかし、このmap要素の子にdiv要素などを噛ませ、孫のa要素でリンク領域を示す方法は、下方互換性がいい代わりに、少なくともIE7が対応していません(object要素の代わりにimg要素でやっても同じ)。

3-3. 従来のクライアントサイドイメージマップ

IE7がスマートな方法に対応していないのは、恐らく比較的新しい方法だからです。と言っても初出はHTML 4.0で、1998年に既に勧告になっているものです。

では(IEを重視してきた場合)従来はどうしていたかと言うと、HTML 3.2時代からあるimg要素area要素を使って領域を指定する方法を用いていました。下記は、それをXHTML 1.1の文法に則って書き直してみたものです。

[プログラムコード開始]

<img src="/image/valid-xhtml11" width="440" height="155" usemap="traditional-map"/>
<!-- …… -->
<map id="traditional-map">
<area href="http://www.w3.org/" alt="W3C" shape="rect" coords="0,0,185,155"/>
<area href="http://www.w3.org/TR/xhtml11" alt="XHTML&trade; 1.1 - Module-based XHTML" shape="rect" coords="185,0,440,155"/>
</map>

[プログラムコード終了]

大体同じですが、map要素の子のarea要素alt属性でラベルを提供します。しかし、この方法にはアクセシビリティに問題があります。非グラフィカルブラウザには、等価な内容を提供できないのです。尤も、area要素href属性alt属性から等価な内容のテキストアンカーをユーザーエージェントが自動的に生成できればいいのですが、今の所、文書の記述側がユーザーエージェントの開発側にそこまで求める事は難しいようです。

img要素の代わりにobject要素を使う事は、この問題に対する一つの答えになるでしょう。

[プログラムコード開始]

<object data="/image/valid-xhtml11" type="image/png" width="440" height="155" usemap="improved-traditional-map">
<map id="improved-traditional-map">
<area href="http://www.w3.org/" alt="W3C" shape="rect" coords="0,0,185,155"/>
<area href="http://www.w3.org/TR/xhtml11" alt="XHTML&trade; 1.1 - Module-based XHTML" shape="rect" coords="185,0,440,155"/>
</map>
<a href="http://www.w3.org/">W3C</a>,
<a href="http://www.w3.org/TR/xhtml11">XHTML<sup>&trade;</sup> 1.1 - Module-based XHTML</a>
</object>

[プログラムコード終了]

ただ、このような書き方をするくらいなら折衷案を採るべきでしょう。

3-4. 折衷クライアントサイドイメージマップ

将来的にはスマートな方法に移行するのが望ましいでしょう。下方互換性もいいですし、冗長にもなりません。しかしシェアの大半はスマートな方法を解さないIEによって占められていますので、それだけにすると大半の人がクライアントサイドイメージマップにアクセスできません。

こういう過渡的な段階を想定してか、map要素の内容には両者を混在させる事ができます

[プログラムコード開始]

<object data="/image/valid-xhtml11" type="image/png" width="440" height="155" usemap="mixed-map">
<map id="mixed-map">
<div>
<a href="http://www.w3.org/" shape="rect" coords="0,0,185,155">W3C</a>,
<a href="http://www.w3.org/TR/xhtml11" shape="rect" coords="185,0,440,155">XHTML<sup>&trade;</sup> 1.1 - Module-based XHTML</a>
</div>
<area href="http://www.w3.org/" alt="W3C" shape="rect" coords="0,0,185,155"/>
<area href="http://www.w3.org/TR/xhtml11" alt="XHTML&trade; 1.1 - Module-based XHTML" shape="rect" coords="185,0,440,155"/>
</map>
</object>

[プログラムコード終了]

map要素の内容にBlockコンテントセットなどの要素とarea要素を混在させた場合、area要素は全て無視されます。

この方法は、アクセシビリティを高め、同時にIE7などの古い (実際に古いもしくは対応が遅い)グラフィカルブラウザでも正しく解釈できるようにします。area要素が不要になれば、その行を消すだけで済むので、自動化も容易でしょう。

3-5. 領域の優先順位

クライアントサイドイメージマップの領域が被った場合、文書中で先に現れた方が優先されます

[プログラムコード開始]

<object data="/image/valid-xhtml11" type="image/png" width="440" height="155" usemap="smart-map">
<map id="smart-map">
<div>
<a href="http://www.w3.org/" shape="rect" coords="0,0,340,120">W3C preceded</a>,
<a href="http://www.w3.org/TR/xhtml11" shape="rect" coords="100,35,440,155">XHTML<sup>&trade;</sup> 1.1 receded</a>
</div>
</map>
</object>

[プログラムコード終了]

上記の例では、まずW3C precededが( 0, 0 )から( 340, 120 )までの矩形(長方形)を占めます。XHTML 1.1 recededは( 100, 35 )から( 440, 155 )までの矩形を占めようとしますが、その中で( 100, 35 )から( 340, 120 )までの矩形は既にW3C precededが占有しているので、XHTML 1.1 recededが取れるのは残りの部分(窪んだ六角形)となります。

3-6. 非アクティブ領域

href属性を持たないa要素や、代わりにnohref属性を持つarea要素非アクティブ領域 (Inactive Zone)を作ります。非アクティブ領域はリンクを持たず、ポインタが上に乗っている状態でクリックなどをされても反応しません。

非アクティブ領域は、優先順位を考えて他のリンク領域に被せないと意味がありません。

[プログラムコード開始]

<object data="./circle.png" type="image/png" width="300" height="300" usemap="circle-map">
<map id="circle-map">
<a href="./center.html" shape="circle" coords="50%,50%,20">中心</a>,
<a shape="circle" coords="50%,50%,100">無効</a>,
<a href="./out-of-circle.html" shape="default">外</a>
</map>
</object>

[プログラムコード終了]

まず、画像の中心に半径20ピクセルのリンク領域があります。その周りに半径100ピクセルの非アクティブ領域があり、更に画像全体を含むリンク領域があります。

順番に気を付けて下さい。優先順位は先に現れた方が高くなります。つまり、画像の中心から距離が20ピクセルまでの領域と、100ピクセル以上の領域はそれぞれ「中心」「外」というリンク領域になり、20ピクセルから100ピクセルまでの領域は「無効」という非アクティブ領域になります。

3-7. クライアントサイドイメージマップでないリンクのグループ化

map要素は、必ずしもクライアントサイドイメージマップと結び付ける必要は無く、ナビゲーション用のa要素をグループ化する目的にも使えます。むしろ、この使用法が転じてクライアントサイドイメージマップになると考えた方が自然でしょう(実際にはこの用法はHTML 4.01からの後付ですが)。

2007-02-16現在、W3Cも好んでこの使い方をしているようです。

3-8. ユーザーエージェント固有の問題

3-8-1. Internet Explorer

前述の通り、Windows Internet Explorer 7.0はスマートな方法をサポートしていないので、折衷案を使うのが現実的です。しかし、The page author is responsible for implementing the functionality defined in HTML 4.0 for a objects, if desired.(Quoted from coords )なんて言ってますが、Microsoft側で実装する気は無いんでしょうか。

また、画像を表すobject要素が無視されます。代わりに中身は描画してくれるので、img要素で代用します。この時、map要素の内容はarea要素だけにするといいかも知れません。

しかも、object要素Blockコンテントセットを内包できない要素の子にすると、そのobject要素がブロックレベル(HeadingコンテントセットBlockコンテントセットListコンテントセット)の要素を子孫に持った場合、内容の描画すら失敗します。回避するには、Flowコンテントセットを内包できる要素の子にするといいようです。

そして、恐らく全てをHTML 4.01 Transitionalと見なしているのだろうと思いますが、usemap属性の値の型がURIデータタイプでないとクライアントサイドイメージマップが有効になりません。という事は#に続けて断片識別子を書かなければならないのですが、 IDREFデータタイプでは文字'#'は許されません。つまり、XHTML 1.1の文法に違反します。

その他、coords="default"などにも対応していません。

3-8-2. Opera

Opera 9でも全てHTML 4.01 Transitionalと見なしているのか、usemap属性の値の型がURIデータタイプでないとクライアントサイドイメージマップが有効になりません。やはり#に続けて断片識別子を書かなければならないのですが、勿論 IDREFデータタイプでは文字'#'は許されません。そしてXHTML 1.1の文法に違反します。

また、map要素の内容にBlockコンテントセットなどとarea要素を混在させると、area要素を無視するのではなく、現れたのが遅いものを無視します(先に現れたものを優先しているとも言えます)。

3-8-3. Mozilla Firefox

Mozilla Firefox 2では、殆ど問題ありません。

が、Opera 9と同じように、map要素の内容にBlockコンテントセットなどとarea要素を混在させると、area要素を無視するのではなく、現れたのが遅いものを無視します。

3-8-4. 結論

完全にXHTML 1.1に適合した文書を書きたいなら、XHTML 1.1でクライアントサイドイメージマップはやるべきではありません。それでもXHTML 1.1を使って、IEやOperaなどでも認識されるクライアントサイドイメージマップを作りたいなら、文法違反を自覚しながら次のようなコードを書くと良いでしょう。

[プログラムコード開始]

<!-- このobject要素の親はdiv要素やtd要素など、Flowコンテントセットを内容に持つ要素にする事 -->
<object data="./map.png" type="image/png" width="400" height="300" usemap="#image-map">
<!-- このimg要素はIE7用 -->
<img src="./map.png" alt="地図" width="400" height="300" usemap="#image-map"/>
<map id="image-map">
<!-- このdiv要素はIEでは消すべきかも知れない -->
<div>
<a href="./top-left.html" shape="rect" coords="10,10,50,40">左上</a>,
<!-- …… -->
<a href="./background.html" shape="rect" coords="0,0,400,300">背景</a>
</div>
<area href="./top-left.html" alt="左上" shape="rect" coords="10,10,50,40"/>
<!-- …… -->
<area href="./background.html" alt="背景" shape="rect" coords="0,0,400,300"/>
</map>
</object>

[プログラムコード終了]

XSLT (XSL Transformations)を使うなら、IEの場合に限ってmap要素の子のdiv要素を消す事ができます。即ち、このdiv要素を出力する所を

[プログラムコード開始]

<xsl:if test="system-property( 'xsl:vendor' ) != 'Microsoft'">
<div>
<!-- ……a要素の羅列…… -->
</div>
</xsl:if>

[プログラムコード終了]

としてやれば良いのです。これを使うと、同時にobject要素の親がFlowコンテントセットを内包できない要素になっても描画が失敗しなくなります。尤も、サーバーサイドでもXSLTプロセッサを用意しなければならないでしょう。

ちなみに、XSLTも使えず、どうしてもobject要素の親をFlowコンテントセットを内包できない要素にしなければならない時、しかもIE7の面倒を見てやらないといけない時は、map要素の子として、BlockコンテントセットにもInlineコンテントセットにも所属し、なおかつ他の要素を内包できる要素──即ちnoscript要素を噛ませるという奥の手もあります……。

[プログラムコード開始]

<!-- このobject要素の親はFlowコンテントセットを内包できなくても構わない -->
<object data="./map.png" type="image/png" width="400" height="300" usemap="#image-map">
<img src="./map.png" alt="地図" width="400" height="300" usemap="#image-map"/>
<map id="image-map">
<script type="unknown/must-not-be-parsed"> </script>
<noscript>
<div>
<!-- ……a要素の羅列…… -->
</div>
</noscript>
<!-- ……area要素の羅列…… -->
</map>
</object>

[プログラムコード終了]

どうやらIE7は、親がInlineコンテントセットしか持てない要素でも、自分のInlineコンテントセットとして評価できれば満足するようです。つまりこのnoscript要素はIE7にしてみればInlineコンテントセットに見えているのです。勿論正しいユーザーエージェントはこれをBlockコンテントセットに評価する(map要素の内容にはInlineコンテントセットは無い)ので、Validatorでもエラーになりません。

しかし、これは本当に文法違反でないだけという感じです。自分で調べておいて何ですが、小手先の技巧です。こんな事をするくらいなら、area要素だけにするなり、テキストアンカーは別に用意するなりした方がいいでしょう。

3-9. 使用例

解説を参照して下さい。

[map]
Published : 2006-03-26T09:00:00+09:00
Last Modified : 2007-07-27T17:40:27+09:00
Table of Contents : 要素目次
Index : 要素索引
Verified with : Valid XHTML 1.1
Copyright © 2006 - 2007  E+X.