「リストの横並びで不思議な空白ができるアレ、をスマートに解決する」を読んでの自分用の再確認

http://hxxk.jp/2009/04/16/2316

記事データ

投稿者

真琴

投稿日時

2009-04-16T23:16+09:00

タグ
概要

ul 要素の直下に配置できる要素は何か、 DOM ツリーに空白や改行はどのように反映されるのか、開始タグや終了タグの省略について、の三本です。

リプライ

リプライはまだありません。

記事本文

そういえば仕様について色々と書いていた時期が僕にもありました

最近は本業が忙しかったり、サイクリングや筋トレなどの運動をするのが楽しかったりで Web に関する興味と割ける時間がめっきり減っているのですが、今日はリストの横並びで不思議な空白ができるアレ、をスマートに解決する - vantguarde - web:gHTML や 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 を用いており、かつ終了タグの省略といった話もしているので、 XHTMLDTD が云々と言ってもそれは関係ない話なのでは、というツッコミもできますが、そんないじわるよりも先に 「あれ、こんなコメントがあるってことは、 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">foo</a></li><li><a href="bar">bar</a></li><li><a href="baz">baz</a></li></ul> という書き方をしたものの DOM ツリーを見てみると、

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) の書き方の方が好きです。 記述コストや可読性は犠牲になるかもしれませんが。

リプライ

リプライはまだ送られていないか、管理者の承認待ち状態です。

この記事に対するご意見やご質問、ご感想などありましたらこのフォームに簡潔に記入して下さい。 簡潔に記入できない場合や、関連記事にてご意見をお寄せいただく場合は、ご自身の weblog にて記事を書かれた上で あてにトラックバックとして送信してください。

記入フォーム

補足情報

著作、講演、制作実績など