エンジニアをリングする

プログラをミングしたり。

my web site twitter

absolute + tableの謎が解けた!!!!

一昨日こんな記事を書きました。

yoshiko.hatenablog.jp

そして今日「WWW WATCH」さんからこんなアンサーエントリを頂きました。

hyper-text.org

ありがとうございます!!!感謝です🙏

エントリの中で、テーブルの視覚整形モデルについての仕様にリンクがはられていました。
その中に答えと思われる仕様の記述を見つけて「なるほど!!」って思ったので書いてみます!

Tables in the visual formatting model
日本語訳: 視覚整形モデルにおけるテーブルの扱い

この参照すべき仕様の場所が見つけられなかったので教えていただけてとてもありがたいです><

WWW WATCHさんでは、

「table の 'width' と 'height' にパーセンテージ値が指定された場合は、"table wrapper box" 自身ではなく、"table wrapper box" の包含ブロックを基準にする。」

となっていますので、display: table; した要素の包含ブロックに高さ指定がなければ height: auto と同じ扱いになるのが仕様ということで、想定された挙動ではないかと思います。

とありました。

たしかにそれは通常フローのheightと同じ動作で、通常はそうなのだと思います。
ただ、その仕様に対する例外が「絶対配置の要素は包含ブロックに高さ指定がなくてもheightを%指定できる」(以降"絶対配置の例外ルール"と呼びます)という仕様なので、通常フローのheightの仕様よりも絶対配置の例外ルールが優先されるように、やっぱりtableでも絶対配置の例外ルールが優先されるのが自然ではないかな?と思いました。

で、気になったのが "table wrapper box" です。これは初めて聞きました。
WWW WATCHさんのエントリの中でも解説がありますが、テーブルは「キャプションボックス」と「テーブルボックス」、そしてその2つを包含する「テーブルラッパーボックス」から成るようです。

そして、仕様書の中のこの1文。

テーブル要素のプロパティー'position'、'float'、'margin-*'、'top'、'right'、'bottom'、'left'の算出値は、テーブルボックスではなく、テーブルラッパーボックスで使用される。非継承プロパティーのその他の値は、テーブルラッパーボックスではなく、テーブルボックスで使用される。

ほう!!!
テーブルに指定したCSSは、プロパティによって適用される要素がわけられるんですね!!
positionfloatmargin-*toprightbottomleftはテーブルラッパーボックスに、それ以外のプロパティはテーブルボックスに適用されると書いてあります。

つまり、前述した絶対配置の例外ルールは「positionで絶対配置を指定した要素はheightを%指定できる」でしたが、テーブルにその2つのプロパティを指定した場合には実際に適用される要素がpositionとheightでバラけてしまうんですね。
positionはテーブルラッパーボックスに適用され、heightはテーブルボックスに適用されていたので、絶対配置になっていないテーブルボックスのheightの%指定は効かないというわけです。

ここでまだわかっていないのが、display: table;を指定した要素は「テーブルボックス」になるのか「テーブルラッパーボックス」になるのかというところです。
もしdisplay: table;を指定した要素が「テーブルボックス」を指すなら、「テーブルラッパーボックス」はその外側に暗黙的に生成される要素ということになるのでしょう。
逆にdisplay: table;を指定した要素が「テーブルラッパーボックス」を指すなら、「テーブルボックス」はその中のtbodyなどにあたる要素(無ければ暗黙的に生成される?)になるのでしょう。
個人的には前者のほうが理解しやすいです。

どちらにしろテーブルラッパーボックスとテーブルボックスは違う要素を指しており、display: table;を指定した要素にpositionとheightを指定するとpositionはテーブルラッパーボックスに適用され、heightはテーブルボックスに適用されるので、合わせ技となる絶対配置の例外ルールは効かないということで自分の中で納得できました。

最初の問題提起ブログには書いてなかったのですが、height指定は無しでtop: 0;bottom: 0;を指定した場合にもdisplay: block;なら包含ブロックと同じ高さに伸びるのにdisplay: table;にすると伸びない、という挙動も確認していてこれも謎でした。これも↑の仕様を踏まえると説明がつきますね。 positionとtopとbottomはテーブルラッパーボックスに指定されているので伸びているけど、それ以外のプロパティが適用されるテーブルボックスは伸びないということですね。

すっきり!!
インターネットって素晴らしいですね。

WWW WATCHさん、ありがとうございました!