Shiki’s Weblog

ESウェブブラウザ通信 - テーブルの自動レイアウトの改善等

2012/08/11 #ESウェブブラウザ通信

今回は、今日リリースしたescort 0.2.2で新たに実装した機能について紹介します。escort 0.2.2では、CSS 2.1の実装の改善を主な目的として開発を進めきました。CSS2.1 Conformance Test Suiteの達成率は90.8%とescortではこれまででベストの結果となっています。

link要素のmedia属性

r2870では、link要素のmedia属性が未サポートだったので、

<link href="/includes/deed3-print.css" media="print" rel="stylesheet" type="text/css">

といった印刷メディア用のスタイルシートも一緒にスクリーン上で処理してしまっていました。 下図は r2870でCreative Commons のライセンスの要約のページを表示した際のスクリーンショットです。

r2870 (link要素のmedia属性未対応)r2870 (link要素のmedia属性未対応)

r2871,r2872でlink要素のmedia属性に対応しています。

r2871 (対応済み)r2871 (対応済み)

なお、今回の実装は CSS 2.1 のメディア リストの仕様に基づいています。メディア リストは CSS 3では、メディア クエリーとなって強化されている部分ですが、escortではいまのところ未対応です。

テーブルの自動レイアウト

テーブルの自動レイアウト アルゴリズムは、CSS 2.1の仕様書17.5.2.2では、

UAs are not required to implement this algorithm to determine the table layout in the case that 'table-layout' is 'auto'; they can use any other algorithm even if it results in different behavior.

となっています(≒未定義)。現状ではCSS標準のレイアウト アルゴリズムがないので、何か特定の動作に期待して'table-layout'プロパティが'auto'に設定されている表をレイアウトに使わないこと、というのがよく言われているお約束の趣旨かな、と思います。そのためこれまでのescortのテーブルの自動レイアウト アルゴリズムはかなり手を抜いたものになっていて、Google CodeのES operating systemのページはr2872では以下のような描画になってしまっていました。

r2872r2872

Google Codeのこのページでは、左側のリンクばかりのカラムの幅はautoに、右側のカラムの幅は100%(表全体の幅に対して100%という意味)に設定されています。ですのでnon-normative(参考)としてCSS 2.1の仕様書に載っているアルゴリズムに倣うと、左側のカラムは最小限必要な幅だけを取って、残りを右側のカラムが(幅がなるべく100%に近づくように)全部専有する感じになります。このとき『最小限必要な幅』というのはとりあえずレイアウトしてみないことにはわからないので、参考アルゴリズムではレイアウト処理が1パスでは終わらなくて、仕様書にも"This algorithm may be inefficient"と記載されています。escort 0.2.2では、CSS 2.1の参考アルゴリズムを参考に、Google Codeのページくらいはそれなりにレイアウトできるように実装を改良することにしました。

r2873r2873

r2873では、自動レイアウトのテーブルに2パスのレイアウト処理を取り入れました。1パス目では従来と同じように、テーブルを包含ブロックとして各セルをレイアウトしつつ(このとき算出されたセルの幅を"maximum" cell widthとしています)、参考アルゴリズムに記述されている各セルのminimum content width (MCW)を合わせて計算しています。MCWは行の途中で折り返すことのできない単語の最大幅などから計算できます。2パス目では、まずMCWをもとにMIN(最低限必要なテーブル全体の幅)を計算します。テーブル自体に指定された幅(W)がautoの場合は、簡略レイアウトで求めた幅から計算される値から参考アルゴリズムのMAXを計算しています(r2875)。またMIN < Wの場合などには余った幅を参考アイルごリズムでは、

If the used width is greater than MIN, the extra width should be distributed over the columns.

と、各カラムに分配するように記述されています。ところがこの1文の解釈が実は結構大変なところでした。r2873では、ひとまず幅が明示的に固定値で指定されているカラムには分配しないようにしてありました。このようにして各カラムの幅がきまったら、各セルをカラムの幅に合わせて再度レイアウトしていきます。すこしリビジョンが進んで、r2888ではinput要素のsize属性に対応しています(右上の方にあるテクストボックスの幅が広がっています)。

r2888r2888

r2888では、テキストボックスの幅が広がった分、es-operating-systemというテキストを含んでいるセルの幅が不足してテキストが途中で折り返されるようになってしまいました。

r2889r2889

r2889では、自動テーブルレイアウトのアルゴリズムを改良して、余った幅は、まだmaximum column widthに達していないカラムに優先して分配して、それでも余っていたら各カラムに均等に分配、という2段階で分配するようにしました。これで"es-operating-system"の部分も無駄に改行されずに済むようになりました。ただr2889では『各カラムに均等に分配』という処理のために、Summary Peopleというリンクがあるセルの右隣にあるMCWが0のセルの幅も増やしてしまっていました。この点については、幅0のセルは0のままにしておく、というのが各メジャー ブラウザでの暗黙のルールの様子です。

r2890r2890

r2890では、幅0のセルは0のままにしておくように修正しました。Summary Peopleというリンクがあるセルの下線がウィンドウ幅いっぱいに広がっているのに気づくでしょうか? CSS 3では、 標準のテーブル自動レイアウト アルゴリズムの策定が期待されるところですが(*)、escortブラウザでは、当面は更に凝ったテーブルの自動レイアウト処理が必要かどうか他のサイトなども見ながら確認していきたいと思います(David Baronさんも詳細を検討されている途中のようです)。(*)CSS3 BOXに、

[CSS3TBL] Bert Bos; David Hyatt. CSS3 Tables Module. (forthcoming). W3C Working Draft. (Work in progress.)

という記載が見られます。

ドキュメント タイトルの空白のつぶし

r2873のウィンドウのタイトルバーを見てみると、"es-operating-system -     ES operating system..." のように余分な空白が見えます。

r2873r2873

HTMLファイル中ではこの部分は改行コードなどが入っていたりするのですが、それがそのまま表示されてしまっていました。HTML Living Standardの3.1.4では、documentからtitleを取得するときは、

Replace any sequence of one or more consecutivespace charactersin value with a single U+0020 SPACE character.

と規定されているので、r2874で対応しています。

r2874r2874

ちなみに、HTMLTitleElement要素のtext属性を取得する場合は、文字列の前後以外の空白のつぶしは行わないのが仕様のようです。

テーブルの絶対配置

escort 0.2.1以前はテーブルの絶対配置に未対応だったのですが、r2879からr2884にかけてCSS2.1 Conformance Test Suiteを使ってテストしつつ対応しました。

table-percent-width-001 (r2879)table-percent-width-001 (r2879)

r2879ではテーブルの高さの処理に問題があって、テストスイートのabspos-006などで問題がありました。 PASS という文字はページの右下に表示されないといけないのですが、テーブルの高さがビューポートの高さに設定されてしまっていました。

abspos-006 (r2879)abspos-006 (r2879)

r2880で問題点を修正しています。

abspos-006 (r2880)abspos-006 (r2880)

r2881では、仕様書14.2のキャンバス全体をルート要素の背景色で塗りつぶすという処理にバグがありました。

abspos-containing-block-initial-004c (r2881)abspos-containing-block-initial-004c (r2881)

r2882で修正しています。

abspos-containing-block-initial-004c (r2882)abspos-containing-block-initial-004c (r2882)

abspos-containing-block-initial-004eは、ルート要素のスタイルに"display:table"が設定されているという嫌な感じのテストです。

abspos-containing-block-initial-004e (r2882)abspos-containing-block-initial-004e (r2882)

r2882の段階では、匿名のセルに誤ってスタイルを設定してしまっていたので、セルが絶対配置されているようなおかしな状態になってしまっていました。

r2883r2883

r2883でその点を修正していますが、背景色が黄色になっていません。キャンバスの色はbody要素から来ているので、rootで再計算した値をそのまま使ってしまうとデフォルトの色になってしまっていたのでした。

r2884r2884

r2884でひとまず修正しましたが、この処理は想像よりも面倒でr2912でようやく実装が落ちつきました。

リグレッションの修正

テーブルの自動レイアウトでは各セルについて2パスでリフローを実行したり、といったこともあってリグレッションがいろいろと発生して、一時的にCSS 2.1 Conformance Test Suiteの達成率も3月末の90.1%から84%くらいまで落ちてしまっていました。r2890以降r2919までリグレッションの修正を続けて達成率を90.8%まで復旧させました。修正内容については、escort 0.2.2のTODOリストChangeLogを参考にしてください。

まとめ

今回は、escort 0.2.2で新規に実装した下記の機能について紹介しました。

特に自動テーブルレイアウトアルゴリズムの実装では、まだ標準仕様がないために実装にあたっては他のブラウザのレイアウトと見比べながら改良していくということで結構手間取りました。自動テーブルレイアウトはもうあまりにも多く(レイアウト目的に)使われすぎてしまっていて、今後は標準仕様を詰めていくしかないのだろうと思います。けれどもロンドン オリンピックの開会式にも登場されていたTim Berners-Leeさんの"Principles of Design"でも引用されているKISSの原則

" Keep it simple, stupid! "

には自動テーブルレイアウトは合ってない感じがします。特定のブラウザだけに非常に複雑な機能を実装してみて、他のベンダーも合わせて、と言うのではなくて、ものすごい単純だけどこれ便利だね、ということで他のベンダーもすぐにコピーしていくような発展の仕方の方がウェブらしいかな、と。次回のESウェブブラウザ通信では、harnessコマンドを使ったescortブラウザのテスト方法について紹介したいと思います。またescortの方は、今後レンダーツリーの部分リフロー処理の実装をはじめて行く予定です(今回も実はテーブルの各セルについては部分リフローとほぼ同じ処理を行なっているわけですけれども)。部分リフローまでできるようになれば、escortのCSSレイアウトエンジンの骨格部分は固まってくる感じになると思います。というわけで、今回はここまでです。