以下斜め読んだ内容

pseudo translation of useful posts, book reviews, remarks,etc. twitter: feeddict

table要素のレンダリングの速度

2009.04.01更新

はじめに

といわれる件について。自分で調べたメモ。

ここで書くことに関係のある要素

  • html
    • table要素
  • css
    • displayプロパティの値に「table」「inline-table」のいずれかが指定されたセレクタ

関係のあるcssdisplayプロパティのブラウザ実装状況全般については前のエントリで書いたが、情報が古い。

固定レイアウトアルゴリズムと自動レイアウトアルゴリズム

table要素(および"display:table"か"display:inline-table"のいずれかが指定された要素)のレンダリングに関係してくるのが次の2つのアルゴリズム

  • 固定レイアウトアルゴリズム
  • 自動レイアウトアルゴリズム
HTMLの仕様

「HTML 4.01仕様書」の翻訳のtable要素部分より。強調部分は自分が引用時に追加したもの

参考情報として、次に、ユーザエージェントが表のレンダリングを行なう際にどんな作業を実行しているかの説明を列記する。

  • 表のsummary(要約)をユーザが得られるようにする。著者は、非視覚系ユーザエージェントのユーザにも理解しやすいよう、表の内容と構造に関する要約を提供する必要がある。
  • もし表題が指定されていれば、レンダリングする。
  • もし表ヘッダが指定されていれば、レンダリングする。もし表フッタが指定されていれば、レンダリングする。ユーザエージェントは、ヘッダとフッタをどこにレンダリングするかを理解していなければならない。例えば、ページ単位の出力メディアについては、ユーザエージェントは各ページ冒頭にヘッダ、各ページ末尾にフッタを配置してよい。同様に、ユーザエージェントが行をスクロールする機構を提供する場合、ヘッダはスクロール領域の冒頭に、またフッタは領域の末尾に出現するであろう。
  • 表中の列数を算出する。 表の行数はTABLE要素中のTR要素の数に等しいことに注意されたい。
  • 列グループ指定があれば、そのすべてに従って列をグループ化する。
  • ヘッダとフッタの間で、1行1行、適切な列グループ化を行いながら、各コマをレンダリングする。視覚系ユーザエージェントは、HTMLの属性とスタイルシート指定とに従って、表の整形を行なう必要がある。

HTMLの表モデルは、著者の助けを借りることで、ユーザエージェントが、表のデータ全体が到着するのを待つのではなく、行単位でデータが届く毎に、表を逐次的にレンダリングできるように設計されている。
Tables in HTML documents (ja)

CSSの仕様

次にCSS2.0の仕様書の翻訳の「17 表について」より。同じく強調部分は自分が引用時に追加したもの

このアルゴリズムでは、表の水平方向のレイアウトがセルの内容量に依存しない。
その代わり、表全体の幅、列幅、ボーダー、そしてセル間距離の影響を受ける。

表全体の幅は'width'を用いて指定するとよい。
この値が'auto'である場合は('display: table'、'display: inline-table'のどちらであっても)自動レイアウトアルゴリズムを使用する。

固定レイアウトアルゴリズムでは、各列幅を以下の様にして決める:

  1. 'width'の値が'auto'以外である列要素は、指定された値をそのまま列幅として用いる。
  2. 列要素の'width'の値が'auto'である場合、1行目のセル要素の'width'の値に着目し、その値が'auto'以外であれば列幅として用いる。
    該当するセル要素が複数列に渡る場合、その値は複数列分の幅を表す。

  3. 以上で幅が決まらない列は、残りの水平幅を公平に等分する(もちろんボーダーとセル間距離を考慮して計算する)。


最終的には、表要素の'width'の値と、列幅(ボーダー、セル間距離込み)の合計のうち、大きい方を表の幅にする。
列幅の合計より表の幅の方が大きい場合、余った幅は各列へと適当に配分すべきである。


この方式だと、UAは1行目を受け取ってすぐに表のレイアウトを始められる。
以降に続く行が列幅に影響しないからである。
セルから内容がはみ出す場合は、'overflow'の値に従って処理する。

表について 固定レイアウト

またこの引用部分の直前部分には、固定レイアウト/自動レイアウトの選択をcssのtable-layoutプロパティを使って指定できると書かれている。

  • 値が「fixed」なら、固定レイアウト
  • 値が「auto」なら、自動レイアウト

htmlとcssの各仕様からは言えそうなこと

「table要素は中身が全部到着してからレンダリングされる」というのは正確ではない。
table要素全体が到着しないとレンダリングされない場合はある。だが同様に、逐次的に(tr要素が揃うたびに)レンダリングされる場合もある。
つまり、htmlとcssが適切にマークアップされれば行単位でレンダリングされるようになる
・・・・・という仕様になっている。
2つ目の引用の直後に固定レイアウトの反対の「自動レイアウト」が書かれている。
「自動レイアウト」においては、table要素に適切な属性を指定しない場合は、table要素全体のデータを受け取ってからレイアウトの計算を始めることになる。「自動レイアウト」はこちらについては相対的に遅いと言えるかな、と思う。
いわゆるテーブルレイアウトは、属性を指定しまくりなので固定レイアウトでレンダリングだろう。
テーブルレイアウトは入れ子になりやすいだろうが、CSSレイアウトでもdivの入れ子になってるケースはある。
この辺は、テーブルレイアウトでもvalidateをパスするマークアップが可能であるし。

仕様ではなく各ブラウザの実装では・・・

とはいえ、ここまで書いたことは「仕様ではこうなってる」というはなしで、ブラウザの実装ではどうなっているかについては情報がない。ブラウザが仕様どおりに「表のレンダリング」や「固定レイアウト」を実装しているかどうかについては、ここまで書いたことからは引き出せない。
仕様からはテーブルレイアウトが遅いことは導き出せないというだけ。
ブラウザの実装におけるtable要素のレンダリングについては、これから調べてわかったら追記したいが、自分のスキルを超えてる気がする。

table要素のレンダリングを高速化させるためには・・・

  • 「固定レイアウト」でレンダリングされるようにする。
  • 「固定レイアウト」の指定方法
    • CSSを使う場合
      • table要素に対して、table-layoutプロパティの値を「fixed」にする。
        • 初期値は「auto」になってる。「auto」だと自動レンダリングが採用される。
        • tabl-layoutプロパティはIEも5.5以降でサポートされた、主要ブラウザでサポート済みのプロパティ
        • table-layout
        • Mac版IEではダメ
      • 更にtable要素にwidthプロパティの値を指定する。
    • HTMLだけを使う場合
      • 物理属性(width、border、etc..)を使って、table要素だけでなく、tr要素、td要素の幅を指定する。
      • table要素の子要素の幅に依存せずに、tableの幅を確定できることが固定レンダリングの条件であるため。
      • オススメでない。

仕様に基づけば・・という話。
自動レンダリングから固定レンダリングへ変更したことによる速度の比較はいつか調べる。

cssのtable-layoutプロパティがIEでもサポートされてる理由

IEBlog : Table Rendering
IE5が最初に実装したプロパティだから。
その後CSS2/2.1に採用されたプロパティだから。