附録:CSS2.1の視覚整形モデル詳細

この文書はCSS 2.1 Spec. W3C CR-20070719の,section 10.3およびsection 10.6を個人的な動機に基いて飜訳したものです。唯一の公式文書はhttp://www.w3.org/TR/2007/CR-CSS21-20070719/visudetに在ります。

この文書は飽くまで参考資料に過ぎません。この邦訳には多くの誤訳が含まれている可能性があります。参考にする際には原文と併読するようにしてください。もし誤訳などを発見されましたら,管理者までご聯絡くさだい。

CSS2.1の詳細は,セオリー・オブ・スタイルシート; 技術評論社 編/刊でとても精しく解説されております。

目次

参考情報:私的なまとめ 第10章にかかわる主な変更点

プロパティ値のわりあて過程の変更

CSS2.1では,プロパティ値のわりあて過程このサイトでの解説)がひとつ増えて四段階に変更された; (1)まづ指定された値そのものがあり(指定値:specified value),(2)次に継承のために使用される値(算出値:computed value)に変換し,(3)それから必要に応じて絶対値への変換を行い(使用値:used value),(4)最終的にその場の環境制限に応じて実効値(actual value)を導き出す。

CSS2では使用値の過程がなく,プロパティ値のわりあて過程を三段階としていた; (1)まづ指定された値そのものがあり(指定値),(2)次に必要ならば絶対値への変換を行い(算出値),(3)最終的にその場の環境制限に応じて実効値を導き出す。

新たに追加された'inline-block'要素

'display'プロパティの値として 'inline-block' が追加され,整形モデルに新しく'inline-block'要素の概念ができた。

不明確な幅である非置換フロート要素

非置換フロート要素の幅が 'auto' である場合,その値は "内容にフィットした幅"("shrink-to-fit" width)になる。この計算は,自動レイアウトアルゴリズムを使用しているテーブルのセル幅の計算と類似している。CSS2ではこの事例を 0 として算出していた。

絶対位置決めにおける 'auto' の計算

絶対位置決めの要素は "内容にフィットした幅"("shrink-to-fit" width)になる事もある: 'width' および 'right' (もしくは 'width' および 'left')が共に 'auto' である場合,その幅は内容にフィットされる(自動レイアウトアルゴリズムを使用しているテーブルのセル幅の計算と類似)。そしてそれにより 'right' (もしくは 'left')が決る。CSS2ではこの事例を 'right' (もしくは 'left')に 0 をセットし,そして幅が決るとしていた。

絶対位置決め要素の静的な高さは,通常フローのブロックレヴェル要素のごとく内容に基かれる。たとえば 'height' と 'bottom' が共に 'auto' なら,高さは内容に基かれ,それにより 'bottom' が決る。CSS2ではこの事例を 'bottom' に 0 をセットして,高さが決るとしていた。

通常フローの非置換ブロック要素の高さ

通常フローの非置換ブロックレヴェル要素における高さの計算方法は正しくなかった。

10.3 内容領域の幅と水平マージンを計算する

要素のレイアウトに使用される 'width','margin-left','margin-right','left','right' の値は,その要素が生成するボックスの種類および互いの値に依存する。(これらの計算には使用値を参照することがある。) 原則として 'auto' を適切な値に置き換えて使用値と算出値が同じになる様に,そしてパーセント値を包含ブロックに基いて計算するのだが,それだけではない。要素の種類によって次のように状況を区別する必要がある:

  1. 非置換インライン要素
  2. 置換インライン要素
  3. 通常フローの非置換ブロックレヴェル要素
  4. 通常フローの置換ブロックレヴェル要素
  5. 非置換フロート要素
  6. 置換フロート要素
  7. 絶対位置決めの非置換要素
  8. 絶対位置決めの置換要素
  9. 通常フローの非置換'inline-block'要素
  10. 通常フローの置換'inline-block'要素

1〜6および9〜10については,レイアウトに使用される 'left' と 'right' の値を section 9.4.3. の規則で決定する。

10.3.1 非置換インライン要素

'width'プロパティは適用されない。'left', 'right', 'margin-left', 'margin-right' の算出値が 'auto' なら,その使用値は '0' になる。

10.3.2 置換インライン要素

'margin-left' または 'margin-right' の算出値が 'auto' なら,それら値は '0' になる。

'height' および 'width' の算出値が両方とも 'auto' であり,その要素が内在幅を有するなら,それが 'width' の使用値になる。

'height' および 'width' が両方とも算出値に 'auto' を持ち,要素が内在幅を有しないが,内在高および内在比は有するなら; もしくは 'width' の算出値に 'auto' を持ち,'height' が他の算出値を持つなら,そして要素が内在比を有するなら; その 'width' 使用値は:

(heightの使用値) * (内在比)

'height' および 'width' が両方とも 'auto' を算出し,要素が内在比を有するが,内在高か内在幅を有しないなら; そして包含ブロックの幅が置換要素の幅それ自身に依存しないなら; その 'width' の使用値は通常フローの非置換ブロックレヴェル要素での等式から導かれる。

上記以外で 'width' の算出値に 'auto' を持つなら,上述の条件を満たさない。そして 'width' の使用値は300pxになる。もし300pxがデヴァイスにフィットするには餘りに広いなら,UAはその代りに2:1の比率でデヴァイスにフィットする最大矩形の幅を使用すべきである。

Percentage intrinsic widths are first evaluated with respect to the containing block's width, if that width doesn't itself depend on the replaced element's width. If it does, then a percentage intrinsic width on that element can't be resolved and the element is assumed to have no intrinsic width.

10.3.3 通常フローの非置換ブロックレヴェル要素

次の制約は,他のプロパティの使用値との間で常に成立させなければならない:

'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + (もし在ればスクロールバーの幅) = 包含ブロックの幅

'width' が 'auto' 以外で,'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + (もし在ればスクロールバーの幅)(さらに 'margin-left' または 'margin-right' が 'auto' 以外のとき)が包含ブロックの幅より大きいなら,'margin-left' または 'margin-right' の 'auto' は以下の規則によりゼロとして見做される。

上に挙げたすべてのプロパティが算出値として 'auto' 以外の値を採るとき,それらの値は「制限しすぎ(over-constrained)」であると謂う。そして,それらのプロパティのうち一つは算出値とは異る使用値を採る必要が生じる。包含ブロックの 'direction' の値に 'ltr' を持つなら 'margin-right' の指定値が無視され,上述の等式を満たすように計算される。'direction' の値が 'rtl' なら,代りに 'margin-left' に生じる。

上に挙げたプロパティの指定値のうち一つだけが 'auto' なら,その使用値は上述の等式から導かれる。

'width' に 'auto' が設定されたなら,それ以外の 'auto' は '0' になる。結果として 'width' は上述の等式から導かれる。

'margin-left' と 'margin-right' が両方とも 'auto' なら,両者の使用値は等しくなる。これは包含ブロック辺に対して要素をセンタリングする。

"スクロールバー幅" の値は,UAがスクロール機構を用いる場合にだけ評価される。'overflow'プロパティの定義を参照。

10.3.4 通常フローの置換ブロックレヴェル要素

'width' の使用値は置換インライン要素のごとく決める。そしてマージンは非置換ブロックの規則を適用して決める。

10.3.5 非置換フロート要素

'margin-left' または 'margin-right' の算出値が 'auto' なら,その値は '0' になる。

'width' の算出値が 'auto' なら,その使用値は "内容にフィットした幅"("shrink-to-fit" width)になる。

shrink-to-fit widthの計算は,自動テーブルレイアウトアルゴリズムを使用しているテーブルのセル幅の計算と類似している。概略:明示的に行区切りが生じるところ以外では行を区切らずに内容を整形化する事によって,望ましい幅(preferred width)を計算する。さらに,可能な限りの行区切りを試みるなどして,望ましい最小限(minimum)の幅を計算する。CSS2.1では正確なアルゴリズムを定めない。最後に,利用可能な幅(available width)を見つける:これは包含ブロックの幅から 'margin-left', 'border-left-width', 'padding-left', 'padding-right', 'border-right-width', 'margin-right' の使用値および関聯したスクロールバーの幅を差し引くことで見つかる。

そしてshrink-to-fit widthは,次のような公式で導き出す:

min( max(望ましい最小限の幅, 利用可能な幅), 望ましい幅)

10.3.6 置換フロート要素

'margin-left' または 'margin-right' の算出が 'auto' なら,それら使用値は '0'。'width' の使用値は置換インライン要素のごとく決める。

10.3.7 絶対位置決めの非置換要素

この節と次の節では,その趣旨のために「(要素の)静的な位置(static position)」という用語を参照する。大ざっぱには,要素が通常フローに属している場合の位置のことである。より正確には:

しかしUser Agentはその仮定ボックスを実際には計算せずに,確からしい位置を推測してもよい。

静的な位置を計算するために,固定配置された要素の包含ブロックは,表示域(viewport)の代りに初期包含ブロックを用いる。そして,すべてのスクロール可能なボックスは,それらの原点へスクロールされるものとして仮定すべきである。

絶対位置決めの要素は,次の制約を満たさなければならない:

'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + 'right' + (もし在ればスクロールバーの幅) = 包含ブロックの幅

'left','width','right' のうちすべてが 'auto' の場合: まづ 'margin-left' と 'margin-right' を 0 にセットする。次に,包含ブロックの 'direction' の値が 'ltr' なら 'left' を静的な位置にセットし,下記の規則3項を適用する。さもなければ,'right' を静的な位置にセットし,下記の規則1項を適用する。

これら三つの値が何れも 'auto' ではない場合: 'margin-left' と 'margin-right' が両方とも 'auto' なら,両側のマージンが等しくなるよう上述の等式を解く。これらが負になるのなら,包含ブロックの書字方向によって 'ltr' ('rtl') なら 'margin-left' ('margin-right') をゼロにセットして,'margin-right' ('margin-left') を解く。'margin-left' または 'margin-right' のうちの一つが 'auto' ならば,そのプロパティについて上述の等式を解く。値が「制限しすぎ」の状態ならば,'left' (包含ブロックの 'direction' の値が 'rtl' である場合)または 'right' (同様に 'direction' が 'ltr' である場合)の値を無視する。そして,その無視したプロパティについて上述の等式を解く。

さもなければ,'margin-left' と 'margin-right' の 'auto' を 0 にセットして,次の六つの規則のうち一つを選んで適用する:

  1. 'left' と 'width' が 'auto' であり,'right' が 'auto' でないなら,その幅は内容にフィットされる(shrink-to-fit)。そして上述の等式から 'left' を解く。
  2. 'left' と 'right' が 'auto' であり,'width' が 'auto' でないなら,包含ブロックの 'direction' の値が 'ltr' ならば 'left' を,'rtl' ならば 'right' を静的な位置にセットする。そして,上述の等式から 'left' ('direction' が 'rtl' の場合),'right' ('direction' が 'ltr' の場合)を解く。
  3. 'width' と 'right' が 'auto' であり,'left' が 'auto' でないなら,その幅は内容にフィットされる(shrink-to-fit)。そして上述の等式から 'right' を解く。
  4. 'left' が 'auto' であり,'width' と 'right' が auto' でないなら,上述の等式から 'left' を解く。
  5. 'width' が 'auto' であり,'left' と 'right' が auto' でないなら,上述の等式から 'width' を解く。
  6. 'right' が 'auto' であり,'left' と 'width' が auto' でないなら,上述の等式から 'right' を解く。

shrink-to-fit widthの計算は,自動テーブルレイアウトアルゴリズムを使用しているテーブルのセル幅の計算と類似している。概略:明示的に行区切りが生じるところ以外では行を区切らずに内容を整形化する事によって,望ましい幅(preferred width)を計算する。さらに,可能な限りの行区切りを試みるなどして,望ましい最小限(minimum)の幅を計算する。CSS2.1では正確なアルゴリズムを定めない。最後に利用可能な幅(available width)を計算する: これは 'left' (規則1項の場合)または 'right' (規則3項の場合)を 0 にセットした後に,上述の等式から 'width' を解くことで見つかる。

そしてshrink-to-fit widthは,次のような公式で導き出す:

min( max(望ましい最小限の幅, 利用可能な幅), 望ましい幅)

"スクロールバー幅" の値は,UAがスクロール機構を用いる場合にだけ評価される。'overflow'プロパティの定義を参照。

10.3.8 絶対位置決めの置換要素

この要素状況はひとつ前の節と類似している。違っているのは対象の要素に内在寸法が存在する点である。この相違点に基いて,前の節と同じ等式について以下の過程を実行する:

  1. 'width' の使用値は,置換インライン要素のごとく決める。
  2. 'left' および 'right' の両方が 'auto' という値を持ち,そのとき包含ブロックの 'direction' が 'ltr' なら,'left' を静的な位置にセットする。'direction' が 'rtl' なら,'right' を静的な位置にセットする。
  3. 'left' または 'right' の値が 'auto' であり,'margin-left' または 'margin-right' の値が 'auto' なら,そのマージンを '0' とする。
  4. この時点で 'margin-left' と 'margin-right' の値が両方とも 'auto' の儘なら,両側のマージンが等しくなるよう前述の等式を解く。これらが負になるのなら,包含ブロックの書字方向によって 'ltr' ('rtl') なら 'margin-left' ('margin-right') をゼロにセットして,'margin-right' ('margin-left') を解く。
  5. この時点でまだ 'auto' という値が残っていれば,そのプロパティについて前述の等式を解く。
  6. この時点で値が「制限しすぎ」の状態なら,'left' (包含ブロックの 'direction' の値が 'rtl' である場合)あるいは 'right' (同様に 'direction' の値が 'ltr' である場合)どちらかの値を無視する。そして,その無視したプロパティについて前述の等式を解く。

10.3.9 通常フローの非置換'inline-block'要素

'width' が 'auto' ならその使用値は,フロート要素のごとく内容にフィットした幅になる。

'margin-left' または 'margin-right' の算出値が 'auto' ならば,その使用値は '0' になる。

10.3.10 通常フローの置換'inline-block'要素

まさに置換インライン要素と同様。

10.6 内容領域の高さと垂直方向のマージンを計算する

'top','margin-top','height','margin-bottom','bottom' の値を計算するために,要素の種類によって次のような状況を区別する必要がある:

  1. 非置換インライン要素
  2. 置換インライン要素
  3. 通常フローの非置換ブロックレヴェル要素
  4. 通常フローの置換ブロックレヴェル要素
  5. 非置換フロート要素
  6. 置換フロート要素
  7. 絶対位置決めの非置換要素
  8. 絶対位置決めの置換要素
  9. 通常フローの非置換'inline-block'要素
  10. 通常フローの置換'inline-block'要素

1〜6および9〜10については,レイアウトに使用される 'top' と 'bottom' の値を section 9.4.3. の規則で決定する。

Note: these rules apply to the root element just as to any other element.

10.6.1 非置換インライン要素

'height'プロパティは適用されない。内容領域の高さはフォントに基かなければならないが,CSS2.1仕様ではその方法を規定しない。User Agentはたとえば,フォントのemボックスもしくは最大のアセンダおよびディセンダを用いるかもしれない。(後者はemボックスより上部または下部のグリフが内容領域に収まることを保證するが,異るフォントに依って異る大きさのボックスをもたらす; 前者は制作者が 'line-height' と関聯して背景スタイルを制禦できることを確実とするが,内容領域の外に描かれるグリフをもたらす。)

註:CSS3ではおそらく,フォントのどの基準を内容領域の高さに使うのか選択する為のプロパティを含むだろう。

非置換インラインボックスにおける垂直のパディング,ボーダーおよびマージンは,内容領域の上と下から開始されるのであり,'line-height' の上と下からではない。しかしながら 'line-height' だけが行ボックスの高さの計算に使用されるのである。

複数のフォントが使われている(これはグリフが異るフォントで見つかるときに起る)場合の内容領域の高さは,この仕様では定義しない。しかしながら,内容領域が十分な高さになるよう,次のどちらかを提案する; (1) emボックスまたは (2) 要素のあらゆるフォントの中で,最大のアセンダおよびディセンダ。フォントのベースライン揃えに依って関聯するフォントサイズのどれよりも大きくなるかもしれない点に注意すること。

10.6.2 置換インライン要素,通常フローの置換ブロックレヴェル要素,
通常フローの置換'inline-block'要素,および置換フロート要素

'margin-top' または 'margin-bottom' が 'auto' ならば,それらの使用値は 0 になる。

'width' および 'height' の算出値が両方とも 'auto' であり,その要素が内在高を有するなら,それが 'height' の使用値になる。

そうではなく 'height' の算出値に 'auto' を持ち,そして要素が内在比を持つなら,その 'height' の使用値は:

(widthの使用値) / (内在比)

そうではなく 'height' の算出値に 'auto' を持つなら,上記の条件を満たさない。 そして150pxより高くならないよう,デヴァイスの幅より広くならないよう,'height' の使用値を2:1の比率による最大矩形の高さにセットしなければならない。

Percentage intrinsic heights are evaluated with respect to the containing block's height, if that height is specified explicitly, or if the replaced element is absolutely positioned. If neither of these conditions is met, then percentage values on such replaced elements can't be resolved and such elements are assumed to have no intrinsic height.

'inline' または 'inline-block' の要素については,そのマージンボックスが行ボックスの高さの計算に使用される。

10.6.3 通常フローの非置換ブロックレヴェル要素('overflow' の算出値が 'visible' のとき)

この節は 'overflow' に 'visible' を算出しない時でも,その値が表示域(viewport)へ伝播されているなら適用される。

'margin-top' または 'margin-bottom' が 'auto' なら,それらの使用値は 0 になる。'height' が 'auto' なら,その高さは当該要素がブロックレヴェルの子供を含むかどうか,そしてそれがパディングまたはボーダーを持つかどうかに依存する:

もしインラインの子供のみを持つ場合,その高さは最上部にある行ボックスの上端から,最下部にある行ボックスの下端までの距離になる。

もしブロックレヴェルの子供を持つ場合,その高さは最上部にある子供ブロックボックスのボーダー上辺から,最下部にある子供ブロックボックスのボーダー下辺までの距離になる; 通り越して相殺された上下マージンは含まれない。ただし当該要素がゼロ以外の上パディングまたは上ボーダーを持っている場合か,ルート要素であるなら,内容は最上部にある子供ボックスのマージン上辺から始る。(最初の事例は,当該要素の上下マージンが最上部・最下部の子供との間で相殺する事実を表している。第二の事例は,パディングとボーダーの存在が上マージンの相殺を防ぐことになる。) 同様に,当該ブロックの下マージンが最後に流し込まれる子供の下マージンと相殺しないなら,内容は最下部にある子供ボックスのマージン下辺で終る。

これらは通常フローにおける子供のみで考える(つまりフロートボックスや絶対位置決めのボックスは無視する。そして相対配置されたボックスは位置指定されていない状態で考える)。また,匿名ブロックボックスも子供ボックスの一つとして考えることに注意すること。

10.6.4 絶対位置決めの非置換要素

この節と次の節では,その趣旨のために「(要素の)静的な位置(static position)」という用語を参照する。大ざっぱには,要素が通常フローに属している場合の位置のことである。より正確に言うと 'top' の静的な位置は,当該要素の 'position'プロパティが 'static' であり,'float' が 'none' であると仮定したときに,その要素が最初に生成するボックスとなる仮定ボックスのマージン上辺から,包含ブロックの上辺までの距離とする。仮定ボックスが包含ブロックより上にあれば,その値は負になる。

しかしUser Agentはその仮定ボックスを実際には計算せずに,確からしい位置を推測してもよい。

静的な位置を計算するために,固定配置された要素の包含ブロックは,表示域(viewport)の代りに初期包含ブロックを用いる。

絶対位置決めの要素は垂直寸法の使用値を決定するために,次の制約を満たさなければならない:

'top' + 'margin-top' + 'border-top-width' + 'padding-top' + 'height' + 'padding-bottom' + 'border-bottom-width' + 'margin-bottom' + 'bottom' + (もし在ればスクロールバーの高さ) = 包含ブロックの高さ

'top', 'height', 'bottom' のうちすべてが 'auto' なら,'top' を静的な位置にセットして,下記の規則3項を適用する。

これら三つの値が何れも 'auto' ではない場合:'margin-top' および 'margin-bottom' が 'auto' なら,上下マージンが等しくなるように上述の等式を解く。'margin-top' または 'margin-bottom' のうちの一つが 'auto' なら,そのプロパティについて上述の等式を解く。値が「制限しすぎ」の状態なら,'bottom' の値を無視する。そして,その無視したプロパティについて上述の等式を解く。

さもなければ,次の六つの規則のうち一つを選んで適用する:

  1. 'top' と 'height' が 'auto' であり,'bottom' が 'auto' でないなら,その高さは内容に基かれる。そして 'margin-top' と 'margin-bottom' を 0 にセットし,上述の等式から 'top' を解く。
  2. 'top' と 'bottom' が 'auto' であり,'height' が 'auto' でないなら,'top' を静的な位置にセットする。そして 'margin-top' と 'margin-bottom' を 0 にセットし,上述の等式から 'bottom' を解く。
  3. 'height' と 'bottom' が 'auto' であり,'top' が 'auto' でないなら,その高さは内容に基かれる。そして 'margin-top' と 'margin-bottom' を 0 にセットし,上述の等式から 'bottom' を解く。
  4. 'top' が 'auto' であり,'height' と 'bottom' が 'auto' でないなら,'margin-top' と 'margin-bottom' を 0 にセットし,上述の等式から 'top' を解く。
  5. 'height' が 'auto' であり,'top' と 'bottom' が 'auto' でないなら,'margin-top' と 'margin-bottom' を 0 にセットし,上述の等式から 'height' を解く。
  6. 'bottom' が 'auto' であり,'top' と 'height' が 'auto' でないなら,'margin-top' と 'margin-bottom' を 0 にセットし,上述の等式から 'bottom' を解く。

"スクロールバー高" の値は,User Agentがスクロール機構を用いる場合にだけ評価される。'overflow'プロパティの定義を参照。

10.6.5 絶対位置決めの置換要素

この要素状況はひとつ前の節と類似している。違っているのは対象の要素に内在寸法が存在する点である。この相違点に基いて,前の節と同じ等式について以下の過程を実行する:

  1. 'height' の使用値は,置換インライン要素のごとく決める。
  2. 'top' と 'bottom' の両方が 'auto' という値を持つなら,'top' の 'auto' を当該要素の静的な位置にセットする。
  3. 'bottom' が 'auto' であり,'margin-top' または 'margin-bottom' の値も 'auto' なら,そのマージンを '0' とする。
  4. この時点で 'margin-top' と 'margin-bottom' の値が両方とも 'auto' の儘なら,上下マージンが等しくなる様に前述の等式を解く。
  5. この時点でまだ 'auto' という値が一つだけ残っていれば,そのプロパティについて前述の等式を解く。
  6. この時点で値が「制限しすぎ」の状態なら,'bottom' の値を無視して前述の等式を解く。

10.6.6 そのほか雑多な事例

この節は,次の場合に適用される:

'margin-top' または 'margin-bottom' が 'auto' なら,その使用値は 0 になる。'height' が 'auto' なら,その高さは要素の子孫に依存する

'inline-block'要素については,そのマージンボックスが行ボックスの高さの計算に使用される。

10.6.7 ブロック整形文脈ルートにおける 'auto' の高さ

特定の事例(先述の節を参照のこと)では,要素の高さを以下のように算出する:

もしインラインの子供のみを持つ場合,その高さは最上部にある行ボックスの上端から,最下部にある行ボックスの下端までの距離になる。

もしブロックレヴェルの子供を持つ場合,その高さは最上部にある子供ブロックボックスが持つマージン上辺から,最下部にある子供ブロックボックスが持つマージン下辺までの距離になる。

絶対位置決めの子供は無視する。そして相対配置されたボックスは位置指定されていない状態で考える。また,匿名ブロックボックスも子供ボックスの一つとして考えるという事に注意すること。

さらに,その要素がマージン下辺よりも下にある子孫フロートを持つなら,その高さはそれらフロートの辺を含むために拡げられる。これは,その要素自身あるいは通常フローの子孫要素が持つ子供フロートのみで考える。たとえば絶対位置決めの子孫または他フロートの内側では該当しない。