記事本文
そういえば仕様について色々と書いていた時期が僕にもありました
最近は本業が忙しかったり、サイクリングや筋トレなどの運動をするのが楽しかったりで Web に関する興味と割ける時間がめっきり減っているのですが、今日はリストの横並びで不思議な空白ができるアレ、をスマートに解決する - vantguarde - web:g で HTML や SGML における開始タグ・終了タグの省略が参考リソースとして取り上げられていたので、それっぽい話でも。
しかしアクセス解析のリンク元で web.g.hatena.ne.jp/vantguarde が上位に来ていると、どんな取り上げられ方をしているのか、開くまでちょっとどきどきですね。
あとこれから書くのはリストの横並びで不思議な空白ができるアレ、をスマートに解決する - vantguarde - web:g の内容についてではなくて、その記事への id:denchuinc のブックマークコメントについて、という名目の自分の知識の再確認行為です。 ブックマークして ID コールしたりメモを残したりするにも、 100 文字じゃ収まらないかなあと思ったので。
ul 要素の直下は li 要素だけ
まず、
XHTMLのDTDだと ul 要素の直下は li 要素だけでPCDATAは存在できないんじゃありませんでしたっけ。
という点について。
そもそも vantguarde - web:g の kota さんは、当該記事のサンプル DOM ツリーでは <!DOCTYPE html> という DOCTYPE を用いており、かつ終了タグの省略といった話もしているので、 XHTML の DTD が云々と言ってもそれは関係ない話なのでは、というツッコミもできますが、そんないじわるよりも先に
「あれ、こんなコメントがあるってことは、 HTML 4.01 だったら ul 要素の直下に #PCDATA を置けるようなことになっていたっけ」
と思ったので調べてみました。
- HTML 4.01 Transitional DTD
-
<!ELEMENT UL - - (LI)+ -- unordered list -->
- HTML 4.01 Strict DTD
-
<!ELEMENT UL - - (LI)+ -- unordered list -->
- XHTML 1.0 Transitional DTD
-
<!ELEMENT ul (li)+>
- XHTML 1.0 Strict DTD
-
<!ELEMENT ul (li)+>
- XHTML 1.1 DTD ( xhtml-list-1.mod )
-
<!-- ul: Unordered List (bullet styles) ................ --> <!ENTITY % ul.element "INCLUDE" > <![%ul.element;[ <!ENTITY % ul.content "( %li.qname; )+" > <!ELEMENT %ul.qname; %ul.content; > <!-- end of ul.element -->]]>
もし HTML 4.01 Transitional DTD あたりで
<!ELEMENT UL - - (LI|#PCDATA)+ -- unordered list -->
なんて定義になっていたらどうしようかと思いましたが、 HTML 4.01 でも XHTML 1.0/1.1 でも、 Transitional でも Strict でも ul 要素の直下に配置できるのはやっぱり li 要素だけでした。
改行や空白もテキストノードになる
さて HTML でも XHTML でも ul 要素の直下には li 要素しか配置できないということを確認したうえで。
なんでそんなDOMツリーになってるんだろう?
という部分ですが。
これは「なんで」も何も、 ul 要素の直下には li 要素以外の要素は配置できませんが、 #text となるテキストはそこに記述できるから、としか言えないかなと思います。
<ul> <li><a href="foo">foo</a></li> <li><a href="bar">bar</a></li> <li><a href="baz">baz</a></li> </ul> <ul> <li><a href="foo">foo</a> <li><a href="bar">bar</a> <li><a href="baz">baz</a> </ul>
先ほどのサンプルではこのようなソースが例示されていましたが、これを次のような形で考えてみましょう。
<ul>#xA
#x20#x20<li><a href="foo">foo</a></li>#xA
#x20#x20<li><a href="bar">bar</a></li>#xA
#x20#x20<li><a href="baz">baz</a></li>#xA
</ul>#xA
<ul>#xA
#x20#x20<li><a href="foo">foo</a>#xA
#x20#x20<li><a href="bar">bar</a>#xA
#x20#x20<li><a href="baz">baz</a>#xA
</ul>
#xA というのは制御文字の一種で改行を表し、 #x20 は空白を表します。 こう書くと、リストの横並びで不思議な空白ができるアレ、をスマートに解決する - vantguarde - web:g で
<ul> <li><a href="foo">foo</a></li>←ここで要素終了|→ここからテキストノード ここまで←|こっから要素開始→<li>
や
<ul> <li><a href="foo">foo</a></li>|←ここからテキストノード ここまで←|こっから要素開始、なので前の要素終了→<li>
と示されている部分が少し分かりやすくなるのではと思います。 (#xA も #20 もテキストであり、テキストノードにあたるので。 )
UL
LI
A href="foo"
#text: foo
LI
A href="bar"
#text: bar
LI
A href="baz"
#text: baz
のように、 li 要素と li 要素の間には #text は現れなくなります。 リストの横並びで不思議な空白ができるアレ、をスマートに解決する - vantguarde - web:g ではリストをinlineで並べた時の余白|CSS HappyLife という記事も紹介されているのですが、改行や空白を取り除いて一行で書く以外の方法でも同じような結果になります。
<ul>
<li><a href="foo">foo</a></li><!--
--><li><a href="bar">bar</a></li><!--
--><li><a href="baz">baz</a></li>
</ul>
のように、 li 要素の改行にコメントを挟む書き方をしたものの DOM ツリーを見てみると、
UL
#text:
LI
A href="foo"
#text: foo
#comment:
LI
A href="bar"
#text: bar
#comment:
LI
A href="baz"
#text: baz
#text:
という結果になりますし、
<ul>
<li><a href="foo">foo</a></li
><li><a href="bar">bar</a></li
><li><a href="baz">baz</a></li>
</ul>
のように、 li 要素の終了タグの > の前で改行する書き方をしたものの DOM ツリーを見てみると、
UL
#text:
LI
A href="foo"
#text: foo
LI
A href="bar"
#text: bar
LI
A href="baz"
#text: baz
#text:
という結果になります。
終了タグの > の前で改行する書き方ってオーケーなの ? と思われる方もいらっしゃるかもしれませんが、終了タグは
[42] ETag ::= '</' Name S? '>'
のように、 > の直前に
(#x20 | #x9 | #xD | #xA)
といった空白文字類を配置できるように定義されています。
( 今回の例では含めていませんが、 #x9 や #xD を記述してももちろん #text として DOM ツリー内に現れます。 )
まとめ
リストの横並びで不思議な空白ができるアレ、をスマートに解決する - vantguarde - web:g で紹介されている方法は、 (li 要素の終了タグを省略するという大ヒントがあるとは言え )XHTML を用いている場合には使えないということは明示されていません。
仕様を引っ張ってみたり DOM ツリーを確認してみたりしましたが、まとめとしては XHTML を用いている場合は、必然的にリストをinlineで並べた時の余白|CSS HappyLife の方法を採用する、ということになります。 XHTML を採用する weblog サービスや CMS の台頭、はたまた XHTML ブーム (?) もあり 「 XHTML では使えない方法じゃん ! 」 と思われるかもしれませんが、それに対するカウンターがその次の記事のでも、XHTMLじゃない件について - vantguarde - web:g に書かれてあるので、これも合わせて読んでみると良いと思います。
それとせっかく HTML や SGML における開始タグ・終了タグの省略が取り上げられたので、終了タグの省略についての私見をここで述べておくと、はてなブックマーク - リストを横並びにした時の空白 - ciqlie における id:vantguarde のブックマークコメントで
終了タグ省略すると可読性が結構上がる気がする
というくだりに同感を抱きつつも、
「省略条件を考えて書くよりも一律に終了タグを書くほうが学習コストが少なく、省略してはいけない場合に省略しちゃうというリスクを回避できる」
といった程度の理由で、開始タグ・終了タグの省略が許されない XHTML(XML) の書き方の方が好きです。
記述コストや可読性は犠牲になるかもしれませんが。

