Hatena::Groupweb

vantguarde

 | 

4.16

リストの横並びで不思議な空白ができるアレ、をスマートに解決する

| 00:01

まあ全然不思議でもなんでもないんですが。そうそう、これ、一言で説明するマジックワードがほしいですよね。

さてこれ、対処方法として紹介されてるのが、改行しないだとか、コメントを工夫するとか、開始タグや終了タグの書き方を工夫するとかです。「リストをinlineで並べた時の余白」がよくまとまってるかなと思います。

ただ、やっぱりもやもやする人は多いのではないかと。というわけで、ちょっと方法が違ったりしますが、スマートに書ける解決方法を。まあ、別の方向でもやっとしたりするかもしれませんが。

まず、display: inlineではなくてinline-blockを利用します。

li {
  display: inline-block;
 *display: inline;
 *zoom: 1;
}

下のふたつはIE7以下の対策ですね。こちらは「IE 6, IE 7 の inline-block 考察」あたりを読んでいただけるといいかなと。

「Firefox 2.0は?」と思った方。Fx2はいらないこです。目を覚ましてください。

さて、これだけではIE7以下を除いて、空白が(たぶん)できてしまいます。なぜならみなさん、「ふつう」はこう書いてるはずだからです。

<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>

liの終了タグを取ってみると。はい、これで空白が消えます。わーわー

理由を説明する前に、今のふたつのDOMツリーを見てみましょう。ついでに今書いたソースの確認も出来ます。

「ふつう」に書いたソースは、次のようなツリーを構成します。

UL
  #text:
  LI
    A href="foo"
      #text: foo
  #text:
  LI
    A href="bar"

</li>のあとにある改行と次の行のインデントからなるテキストノードが、liの兄弟として生成されます。

で、終了タグを取ったほうは、次のようになります。

UL
  #text:
  LI
    A href="foo"
      #text: foo
    #text:
  LI
    A href="bar"

よく見る必要がありますが、さっきの改行とインデントからなるテキストノードが、liの兄弟ではなく、liの子として存在しています。

どのようなことかてきとーに説明すると、終了タグは明示的に要素の終了を表す区切り子です。なので、ブラウザーは終了タグを見つけたら、DOMツリー上で生成された要素ノードを閉じます。次の開始タグ(要素ノードを生成する)までに現れる何かは、要素ノードの兄弟ノードになります。

「ふつう」の例では、終了タグが書かれていたので、終了タグのあとにあった改行と、インデントのスペース二つがテキストノードとして新たに生成され、liの兄弟として存在していました。

<ul>
  <li><a href="foo">foo</a></li>←ここで要素終了|→ここからテキストノード
  ここまで←|こっから要素開始→<li>

さて、終了タグを省略したらどうなるでしょう。ブラウザーは別の方法から、要素ノードの終了を表す区切り子を見つける必要があります。その区切り子とは、この場合liの開始タグになります。

では、aの終了タグの後ろにある、改行とスペース二つはどうなるのでしょうか。さっきと同じくテキストノードにはなりますが、li要素が終了しているとこの時点では見なされてないので、これはliの子として存在するのです。

<ul>
  <li><a href="foo">foo</a>|←ここからテキストノード
  ここまで←|こっから要素開始、なので前の要素終了→<li>

てきとーと書いたわりには思ったより長くなりましたが、そんな感じの理由です(細かいところがいろいろ怪しいですが)。これにinline-blockが加わる事でインラインボックスではなくなり、末尾の空白類が無くなります。それで、変な空白がなくなると。なお、省略の条件とか説明は「HTML や SGML における開始タグ・終了タグの省略」が詳しいです。

今回はliの終了タグが省略可能ということ、またブラウザーの実装がうまい具合になってるので、それを利用して実現したというはなしです。IE7以下だとhasLayoutマジックで良い具合になってくれますが。

securecatsecurecat2009/04/17 14:01かつてはHTML4→XHTMLという時代の趨勢が感じられた時期があって、その頃以降そのように啓蒙されているからではないですか。そんなに不思議がるのとか、くたばれとかって煽る意味がわからないですね。

 | 
Contact: @vant / lepetitcroissant@gmail.com.