2012/04/05

Android 標準ブラウザの a 要素バグ? a の display:block は気をつけよう!

一昔前に HTML をかじった人ならば
"インライン要素の中にブロック要素を入れてはいけない"
と記憶してると思う。
僕もそうだった。

しかし時代は HTML5 。
それは過去のものでした。
っていうか、a > div しないといけないケースまである。
それが今回の現象。
っていうか人の HTML ソースを見て
「a > div って書くなよ・・・」って最初思いましたすいませんすいません。
勉強不足でした。

まず、先述の
"インライン要素の中にブロック要素を入れてはいけない"
は、ここが出展。
HTML 4.01 Specification - 12.2 The A element
<!ELEMENT A - - (%inline;)* -(A)       -- anchor -->
という記述。
これは、「A要素が内包できるのはA要素を除くインライン要素です。閉じタグ省略できません。」ということ。
なので

となる。
よくある "a 要素をボタンっぽく見せてかっこ良くしてみよう" というのも
<a style="display:block;width:100px;height:100px;border:1px solid #DDDDDD;text-align:center">
ボタンっぽくなるよ
</a>
という具合にしていました。
ここまでが HTML4.01 のお話。

ここからが HTML5 (W3C Working Draft 29 March 2012) のお話。
世の中に完全ではないにしろ HTML5 対応のブラウザが出てきて、
問題にしたい「Android 標準ブラウザ」もその中の一つ。

まずは同じように a 要素の仕様を見てみる。
Content model:
Transparent, but there must be no interactive content descendant.
-- snip --
The a element may be wrapped around entire paragraphs, lists, tables, and so forth, even entire sections, so long as there is no interactive content within (e.g. buttons or other links).
となっています。
子要素(子孫要素)にインタラクティブコンテント(interactive content)を内包できないけど後は全部オーケーみたいですね。随分と偉くなったもんです。
では、先ほどの "a 要素をボタンっぽく見せてかっこ良くしてみよう" を HTML5 で書いてみよう。
HTML5 であれば a 要素の中に div を書くことができます。
有無で比べてみましょう。


こんなカンジで表示されると思う。div 有無でも見た目は一緒。
スタイルシートで hover を定義してるので、タップすると背景色が変わるようになっている。
Mac の Chrome (18.0.1025.142) で確認しても hover は正常に動作する。

ここで登場 Android 標準ブラウザ。
"div無しボタンだよ"(の文字列がない場所)をタップすると、"div有ボタンだよ"の背景色が変わる。
「いや、そこタップしてないし」って突っ込みたくなるレベル。
もしかしたら div有ボタンだよの背景色変わらないかも・・・?
試した感じだと、「表示が何もない場所をタップすると、なんかやばい」です。
試しに"div無しボタンだよ"の文字列をタップすると正常(期待)動作が確認できます。

ちょっと言葉で説明しづらいので出来れば実際に Android 端末で確認してほしい。
僕が試したのは Galaxy S (Android 2.3) の標準ブラウザ。2.2 の頃からこの動作変わってないと思う。ちなみに、iPhone の Safari とかは確認してない・・・。あと他のブラウザも未確認。IE の如く普通の人はデフォルトブラウザを使うと思う・・・。

この div 一つ内包するだけでこうも挙動がかわるので、HTML4.01 でスマートフォンサイトを作成するのは結構危険かも!?(大げさ)
バグなのか仕様なのかちょっとイマイチわかりませんが、
a でコジャレた装飾のボタンを作るときはちょっと覚えておきたいとこです。

結論: a の中に div を書いてもいい。※HTML5