XHTMLの最適化手法

XHTML+CSSというと、どうしてもCSSのほうが強調されがちである。特にレイアウトテクニックを扱う場合、CSSが話題の中心になってしまう。

しかし、効率的なCSS設計には最適化されたXHTMLが欠かせない。このことは、CSSが一定レベルに達している人は薄々気づいているはずで、でも結局どうしたらよいかわからず放っておいてしまいがちなポイントである。

以下では、上記のような問題意識に基づいて、XHTMLの最適化手法を考えてみたい。

div/span要素を少なくする

div/span要素は固有の意味/役割をもたない無色透明な存在だ。そのニュートラルさゆえ、純粋なスタイルコンテナ(style container)として利用することができ、われわれも実際にCSSレイアウトでその恩恵に浴している。

しかし、div/span要素は構造的には不要な存在であることに変わりはない。次の2つのマークアップ例でいえば、グローバルナビゲーションを定義するのに、必ずしもdiv要素でul要素をラップする必要はなく、ul要素に直接idをつけたほうがよいわけだ。

[悪い例]
<div id="globalnav"> <ul> <li><a href="...">項目1</a></li> <li><a href="...">項目2</a></li> <li><a href="...">項目3</a></li> </ul> </div>
[よい例]
<ul id="globalnav"> <li><a href="...">項目1</a></li> <li><a href="...">項目2</a></li> <li><a href="...">項目3</a></li> </ul>

もちろん、デザインをちょっと複雑にしたい場合は、div要素でラップする必要があるかもしれない。しかし、不要なdiv要素はないに越したことはない、という意識が大切だ。

別のケースを考えてみよう。(X)HTMLとアフォーダンスで「div要素の直下にテキストやインライン要素を含めるのは正しくない(書式上は認められていても)」と書いた。次の2つのマークアップ例を見てみると、div要素という役割のない要素でマークアップせず、シンプルにp要素でマークアップしたほうがよい。

[悪い例]
div#navskip { display: none; } : : <div id="navskip"> <a href="#maincontent">ナビゲーションをスキップする</a> </div>
[よい例]
p#navskip { display: none; } : : <p id="navskip"> <a href="#maincontent">ナビゲーションをスキップする</a> </p>

一方、span要素はdiv要素ほど複雑ではない。まず意味的なインライン要素(em/strong要素など)でマークアップできないかどうか考え、どうしてもできない場合にだけspan要素を使う、というのが大原則である。

id/classを少なくする

id/classdiv/span要素と組み合わせてスタイル適用のためのトリガーとして使う(スクリプトの参照先などにも利用するが、ここではひとまず置いておく)。id/classも少ないに越したことはない。

これは特に、効率的なCSS設計と関係する。id/classセレクタではなく子孫セレクタが利用できないか考えるのが、CSSの効率化に不可欠だからだ。なぜならid/classづけはCSSだけで完結する作業ではなく、XHTMLid/class属性を追加・修正するという手間が発生するからである。

作業効率を考えると、CSSだけで作業が完結する子孫セレクタを利用したほうがよい。何よりXHTMLがクリーンになるというメリットもある。

次の2つの例を見てみよう。li要素にスタイルを適用する場合、classセレクタを利用するとli要素ひとつひとつにclass属性をつけなければならないが、子孫セレクタを使えばXHTML側での追加的な作業は全く必要ない。

[悪い例]
li.items { display: inline; ... } : : <ul id="globalnav"> <li class="items"><a href="...">項目1</a></li> <li class="items"><a href="...">項目2</a></li> <li class="items"><a href="...">項目3</a></li> </ul>
[よい例]
ul#globalnav li { display: inline; ... } : : <ul id="globalnav"> <li><a href="...">項目1</a></li> <li><a href="...">項目2</a></li> <li><a href="...">項目3</a></li> </ul>

ここで、「li.items」よりも「ul#globalnav li」のほうが長く、CSSのファイルサイズが大きくなってしまうと思う人もいるかもしれない。確かにそのとおりだが、何十何百とあるXHTMLのファイルサイズが小さくなることを考えれば、おそらくは取るに足らないぐらいのことである。

このような子孫セレクタの積極利用は、スケルトンの各部位(ページ内の主要パーツ)にidづけしておくことが前提だ。もちろん、そのidも少ないほうがよいが、これもトータルバランスで考えるべきである。スケルトンの各部位にidづけしておくことで、無駄なid/classの発生を結果的に防ぐことができるのだから、そのメリットを生かさない手はないだろう。

子孫セレクタには次のようなメリットもある。

ちなみに、子セレクタも利用できればよいのだが、よく知られているようにWin IEが対応していないので仕方がない。

Strictな要素/属性であっても、視覚表現に関するものは使わない

文書構造と視覚表現の厳密な分離には、XHTML 1.0 Strict(またはXHTML 1.1)を採用し、そのボキャブラリの範囲でマークアップするのが基本だが、それだけでよいというわけではない。

まずマークアップの使い方の問題がある。最近ではほとんど見かけなくなったが、たとえばblockquote要素をインデント目的で使うのは書式上のエラーではなく使い方のエラーである。このへんはやはり(少なくとも現時点では)マシンには解析できない点であり、人間による適切な判断が必要とされる部分である。

当然、テーブルレイアウトの問題も絡んでくる。XHTML+CSSだがテーブルレイアウトを採用しているケース、つまり「ハイブリッドレイアウト」も書式上のエラーではなく使い方のエラーである。決められたボキャブラリと書式を守っていても、使い方が間違っていることになる。

次の問題は、XHTML 1.0 Strict(またはXHTML 1.1)で認められているボキャブラリのなかにも、まだ視覚表現に関する要素/属性が残されていることだ。具体的には次の要素/属性が該当する。

モダンブラウザで、これらの要素/属性を使わないことで支障が出るケースはほぼない。あるいは、ちょっとしたハックで対応可能だろう。XHTML 2.0草案(2005年5月27日改訂版)では、これらの要素/属性はすべて廃止されている。

なお、XHTML 1.1(また、その前提となるModularization of XHTML)では、bibigsmallttに加えて、hrsupsubの各要素がプレゼンテーションモジュール(Presentation Module)に分類されているが、これら3つの要素は構造的な意味を備えるため、使用しても問題ないだろう。

実際に、XHTML 2.0草案でも、hr要素は構造モジュール(Structural Module)のseparator要素として生まれ変わり、sup要素とsub要素はテキストモジュール(Text Module)に分類しなおされている。

まとめ

以上の説明は、ページ内のテキスト/パーツそれぞれに正しい役割が割り当てられているのが前提だ。それこそ何でもかんでもdiv要素でマークアップしているようなページは取り入れられる段階になく、まず正しいマークアップにリビルドしなければならない。

その次にスタイルの適用のためにdiv/span要素、id/classを利用し、最後にここで説明したような最適化を図る、というステップになるだろう。

(Firefox 1.5で先行実装されている、W3C草案「CSS3 module: Multi-column layout」に基づいてスタイリングしています。)