Shiki’s Weblog

ESウェブブラウザ通信 - CSS 2.1 Test Suite #19

2012/03/12 #ESウェブブラウザ通信

前回 インライン要素の背景やボーダーの描画処理を改善しました。今回は、 vertical-alignの処理で未対応の箇所を 実装していきます。 vertical-alignは、インライン要素に指定された場合と、テーブルのセルに指定された場合とで効果が異なります。 CSS 2.1の仕様書では 、それぞれ 10.8.117.5.3 に記載されています。今回はこの2つのセクションをCSS 2.1のテスト スイートを使ってテストしながら実装を進めていきます。

インライン レベル要素の'vertical-align'

vertical-align-115
このテストでは'sub'をテストしています。

r2456r2456

r2457でsub, superに対応しました。位置決めに必要な情報はTrueTypeフォントのOS/2テーブルから取り出しています。

r2457r2457

inlines-011

このテストはイメージをbaselineに合わせて表示してみるテストです。成功すれば猫の絵の下に緑色のバーが表示されます。

r2476r2476

このテストでは、なぜバーが表示されるのか不思議だったのですが、試しにイメージの左右にテキストを入れてみると、

試しにイメージの左右にテキストを入れてみる試しにイメージの左右にテキストを入れてみる

上図のように猫の下にバーが見えてきます。というわけで、ラインボックス内にテキストが一切ない場合でも、font-sizeプロパティーは有効で、ベースラインの計算にはそのフォントのメトリックも影響する、という解釈のようです。すこし無駄な処理のような気がしなくもありませんが、CSS 2.1のテストスイートの中にはこの動作に依存しているテストがいくつかあるようです。r2477で対応しています。

r2477r2477

vertical-align-114

このテストでは'middle'をテストしています。

r2477r2477

r2478でmiddleの指定に対応しました。

r2478r2478

inlines-001

このテストでは、テスト本来の問題ではなくて、r2478ではイメージが不正に拡大されて表示されていました。これは、img要素のイメージを簡易的にCSSの背景画像と同じように処理していたためです。そのため、img要素に余白やボーダーがある崩れてしまっていました。

r2478r2478

r2479でAcit2テストの時に用意したobject要素用のコードをベースにimg要素の処理を修正しています。

r2479r2479

vertical-align-boxes-001
このテストでは、いろいろなvertical-alignの指定をまとめて使っていて、成功すると青いボックスが横一列に並んでひとつのボックスのように見えます。r2480では、未対応のtext-topとtext-bottomを使用している部分がずれていました。

r2480r2480

r2481でひとまずtext-topとtext-bottomに対応させています。なお、 r2481の後、他のテストで見つかった細かい修正がr2484まで続いています:r2482(単純なバグ修正),r2483(ラインギャップの考慮し忘れ),r2484(ディセントの処理のバグ修正)。

r2481r2481

r2484までで、10.8.1に関してはテストスイートのテストにPASSするようになりました。ただtop, bottomの実装がまだ仕様通りでない部分があるので、今後まだ修正が必要になりそうです。今回は続いてテーブル セルのvertical-alignの処理に進みます。

テーブル セルの'vertical-align'

vertical-align-baseline-009
このテストに関しては、かなり初期に実装したESウェブ ブラウザのHTMLテーブルモデルの実装だと表をレイアウトすることができませんでした。

r2486r2486

r2487では、HTMLテーブル モデルの実装を修正するかわりに、この古いコードは破棄して、html要素で記述されたテーブルも#17でテストしながら実装したCSSテーブル モデルで処理するようにしています。そのため、JavaScriptからテーブルをDOMで操作したりすると、HTMLテーブル モデルと違う表示をする場合が出てくると思いますが、それはそういう事例が実際に問題になったときに対応することしておきます。

r2487r2487

table-height-algorithm-031その1
このテストは、仕様書17.5.3の、

In CSS 2.1, the height of a cell box is the minimum height required by the content.

という部分のテストにもなっています。

r2487r2487

r2487の段階ではこの仕様に未対応で、左側の列の外側のセルも内側のセルも height: 100pxの設定にそのまましたがって高さが100pxになってしまっています(内部で通常のブロック レベル ボックスと同じレイアウト処理しているため)。r2488で、まずこの点を修正しています。

r2488r2488

このテストでは本来はさらに画面上に見えている2つの"Filler Text"が垂直方向で揃うかどうかが問題なのですが、この点は今回あとで修正します。
table-height-algorithm-002
このテストではtable要素に設定されたheightもやはり高さの最小値として扱っているかどうかテストしています。

r2488r2488

r2489で対応しています。

r2489r2489

table-height-algorithm-003

このテストでは、table-rowに設定されたheightについても同様に最小値として扱っているかどうかテストしています。

r2489r2489

r2490で対応しています。

r2490r2490

table-height-algorithm-031その2
ここまででheightプロパティーの処理は直ってきました。r2491では、セルの'vertical-align'にひとまず対応しました。table-height-algorithm-031では、横一列に揃っていなかったテキストが揃うようになりました。

r2491r2491

table-height-algorithm-019
このテストは、本来はtable-cellのvertical-alignに指定された'sub'などは適用されずに'baseline'として扱う、という部分のテストです。

r2491r2491

r2491ではその部分ではなくて、単純にセルのbaselineの計算にバグがあって横に揃っていませんでした。r2492で修正しています。

r2492r2492

table-height-algorithm-032
このテストでは、inline-tableのベースラインとセルのベースラインと同じになっているかどうかテストしています。(r2492はWebKitと同じ崩れ方ですね。 )

r2492r2492

r2493で修正しました。

r2493r2493

table-height-algorithm-010
このテストでは、HTMLのrowspan属性を使っています。本来は黒と青のボックスが同じ高さにならないといけません。

r2494r2494

r2495でrowspanしているセルのbaselineを、他のセルと別に処理するようにして対応しました。

r2495r2495

table-height-algorithm-012
010と同様なのですが、vertical-alignに'baseline'が指定されています。

r2495r2495

セルのベースラインは1行目のベースラインと同じなので、この場合はrowspanしていないセルと同様にベースラインを処理するようにr2496で修正しました。

r2496r2496

inline-table-002b
このテストでは、未対応のvisibilityプロパティーを使っている部分で失敗していました。

r2496r2496

テーブル関連の要素以外のvisibilityプロパティーの処理は比較的単純なものなので、r2497で対応させました。

r2497r2497

inline-block-valign-001
このテストでは、インライン ブロックのベースラインの処理が正しいかどうかみています。

r2497r2497

r2498でインライン ブロックのベースラインの計算のバグを修正しました。この段階でCSS 2.1の実装としては問題ないと思うのですが、このテストではさらにレガシーなHTMLの属性を使っているので、一応対応していきます。

r2498r2498

r2499でtable要素のheight属性に対応しました。この属性についてはHTML 5でも記載がないようですが、メジャー ブラウザはすべて対応している属性なので合わせておきます。

r2499r2499

続いて、r2500でHTMLのvalign属性に対応しました。こちらはHTML 5では未定義ではありませんがobsoleteです。これでメジャーなブラウザと同じ表示になるようになりました。

r2500r2500

inline-block-valign-002
このテストは、インライン ブロック中にラインボックスが複数作られているような場合のテストになっています。

r2500r2500

r2501で残っていたバグを修正しています。

r2501r2501

inline-table-valign-001
このテストも崩れている原因はインライン テーブルのベースラインの計算のバグでした。

r2501r2501

r2502で、テーブル ボックスに余白などがあった場合にも正しく計算するように修正しました。

r2502r2502

inline-table-002a
このテストは本来はインライン テーブルのベースラインの計算のテストです。

r2502r2502

r2502では、匿名のセルが作られたときに対応するボックスが生成されないバグが残っていました。r2503で修正しています。

r2503r2503

マージンのつぶし、再び

リグレッションが発生していたので修正しておきます。
margin-collapse-145
いままで成功しているように見えていたこのマージンのつぶしのテストなのですが、セルのvertical-alignに対応したことで問題が見つかりました。

r2504r2504

r2504では、マージンのつぶしの処理の問題で、左側のセルの高さが本当の高さよりもクリアランス相当の16px分低く計算されてしまっていました。ボックスの配置自体は合っていたので、vertical-alignが効いていないときは、正しくレイアウトされているように見えていたのです。
それが、vertical-alignが効いてくると、セルの垂直位置を揃えようとして高さの足りない左側のセルの上に不要な余白が挿入されて細い マゼンタ 色のバーが見えてしまう結果になってしまっていました。

r2509r2509


r2509
でcollapse throughした最後の子ボックスが消費したクリアランス相当の高さを親の下マージンとして保存できるように修正しています。(collapse throughのマージンのつぶしは本当にややこしすぎだな、と。)

Acid2、14行目

Acid2テストも、セルのvertical-alignの処理に関するバグをひとつ見つけました。

r2506r2506

最後の14行目では、セルを一切含まないテーブルが作られているのですが、そのテーブルのベースラインの計算にバグがありました。r2507で修正しています。

r2507r2507

table-valign-002
このテストではテーブルをフローティング ボックスにしてテストしています。

r2509r2509

r2509では、テーブルにfloatが設定されている場合でもイン フローのボックスのように他のフローティング ボックスの高さを消費してしまっていたバグがあって、すべての要素に対応するボックスが表示できていませんでした。r2510で、まずこの問題を修正しています。

r2510r2510

続いて、テーブル セルをmiddleやbottomでvertical-alignするときに、セルに設定されているheightの値でレイアウトしてしまっていた問題をr2511で修正しています。CSS 2.1の仕様書からは読み取りにくいのですが、セルのvertical-alignに関しては、セルに設定されているheightの値は無関係ということになっています(参考:Issue 26)。

r2511r2511

これで黄色のストライプは横一列に揃いましたが、最後のテーブルの高さが正しくありません。これはbaselineでvertical-alignするときに、やはりセルに設定されているheightの値を見てしまっていたためでした。r2512で修正しています。

r2512r2512

これでやっとこのテストにPASSできました。現状ではGeckoやWebKitがまだr2511と同じ崩れ方をしています(IEとOperaはPASSしています)。Issue 26を見てみると、このあたりは勧告前のCSS 2.1の仕様書の記載があいまいだったことに原因がありそうです。

まとめ

以上でvertical-alignに関しては、インライン要素の場合、テーブル セルの場合、ともにテストにパスするようになりました。CSS 2.1テストスイート全体の成功率は前回から1%上がって約83%となりました。ただCSS 2.1の章別でみると成功率が80%に満たない章がまだ全体の1/3ほど残っています。次回以降は、このあたりを改善してどの機能も平均的により正しい動作になるように開発していきます。