解 説

包含ブロックとは

ボックスモデルは次の図で表すことができます。
boxmodel
ボーダーを境界にしてマージンとパディングがあり、パディングの内側にコンテンツ(内容領域)が存在します。
これは例えると自分から見た地球のイメージです。
では神の目から見た地球はどんな感じでしょうか。

宇宙があって、その中に太陽系があって地球が存在する。そんなイメージが包含ブロックの考え方です。CSSにおける視覚整形モデルは宇宙ほど複雑で神秘的ではありません。それは実にシンプルで有限のものです。

ちょうど宇宙にあたるものがルート要素(html)の包含ブロックです。それは初期包含ブロックといいます。

初期包含ブロックはビューポートの寸法を持ち、キャンバスの原点で固定される。 初期包含ブロックはページメディアのページ領域となる。

と定義されていますが、簡単に言ってしまうとそれはブラウザの表示領域のことです。

たとえばブロックレベル要素のdivで通常フローさせる要素を作成した場合、ルート要素が作成している包含ブロック、つまりブラウザの表示領域いっぱいにdivのボックスモデルを形成することになります。
(実際にはブラウザが独自のCSSでbodyにマージンを付けていますのでわずかな空白ができます)

次の例では簡単なボックス生成要素と包含ブロックとなる要素の関係を表したものです。
サンプルページ
.p2内ではem要素がインラインボックスを作成しています。さらに、strong要素がインラインボックスを作成しています。em要素以外のテキスト部分は匿名インラインボックスと呼ばれる特殊なインラインボックスが作成されたことになります。

ボックス生成と包含ブロックの関係
ボックスを生成する要素 包含ブロックを設定する要素
html 初期包含ブロック(UA依存)
body html
div1 body
p1 div1
p2 div1
em1 p2
strong1 p2

幅の算出

初期値

ただdivを作成しただけなら初期設定では包含ブロックいっぱいに広がります。ルート要素(html)が包含ブロックですからブラウザいっぱいに広がることになります。
幅の決定
幅の設定はwidthプロパティを使用します。非置換インライン要素、テーブル列と列グループを除く全要素に設定することができます。非置換インライン要素とはimg要素とinput要素textarea要素以外のインライン要素のことです。
widthを数値やパーセントで指定することで幅を決めることができます。
autoは特別な働きをします。それは他のプロパティに依存して大きさを調整します。

通常フローのブロック要素

‘margin-left’ + ‘border-left-width’ + ‘padding-left’ + ‘width’ + ‘padding-right’ + ‘border-right-width’ + ‘margin-right’ = 包含ブロックの幅

この計算式を見るとボックスモデルの計算式と同じです。つまり、地球側から見た、積み上げ方式の計算で算出できると思えてしまいますが、それは間違いです。
その証拠に、width.margin,padding,border-widthのすべてに値を設定することはできません。
通常の横書きのページで、すべてに値を設定した場合、margin-rightの値が無視されて調整値が入ります。
margin1
包含ブロックの場合は、宇宙の広さ(包含ブロックの幅)が先に決まっているのです。だから、いずれかの値をautoで調整する必要があります。

ここが包含ブロックの考え方のポイントです。

widthがautoに設定される場合、それ以外のautoの値は0になります。つまり幅がいっぱいに広がります。
ただし、border-left-width、border-right-widthにはautoの値がありません。この値を省略した場合は初期値はmediumになります。また、paddingにもautoの値がありません。
つまり、幅の自動設定はwidthかmarginで調整するしかありません。

dog_margin
‘margin-left’と’margin-right’の両方の値が’auto’の場合には両方とも同じ値が入ります。それはつまりブロック要素の中央揃えに利用されます。

包含ブロック計算での例外

非置換インライン要素

img要素とinput要素textarea要素以外のインライン要素です。
‘width’プロパティとheightプロパティは使用できません。左右のマージンはインライン要素にも設定できますが上下のマージンはありません。
margin-leftまたはmargin-rightをautoにすると0になります。

置換インライン要素

margin-leftまたはmargin-rightをautoにすると0になります。
heightおよびwidthがautoの場合、imgなどの要素が固有の幅を持つ場合、その固有の幅がwidthの値となります。

フロートさせた場合

margin-leftまたはmargin-rightがautoの場合、値は0になります。
また、widthがautoの場合、値は内容に依存した幅になります。 そして、imgなどの置換要素の場合は置換要素自信(画像など)の幅になります。

固定配置の場合

固定配置要素の包含ブロックはビューポートの代わりに初期包含ブロックとなります。
固定配置要素の包含ブロック幅の算出は以下のようにします。

‘left’ + ‘margin-left’ + ‘border-left-width’ + ‘padding-left’ + ‘width’ + ‘padding-right’ + ‘border-right-width’ + ‘margin-right’ + ‘right’ = 包含ブロックの幅

leftとrightの指定は通常同時に行いませんが、両方指定した場合は以下のような扱いになります。
参考サンプル(下記リスト5の例)

  1. leftとwidthがautoでありrightに固定値を指定したならwidthは伸縮して調整されます。そしてleftのautoは無視されます。
  2. leftとrightがautoでありwidthに固定値を指定したなら、directionプロパティが通常位置のleftに設置されるltrであるなら、通常フローの位置にそのまま設定されます。
  3. widthとrightがautoでありleftに固定値を指定したならwidthは伸縮して調整されます。そしてrightのautoは無視されます。
  4. leftがautoでwidthとrightがautoでないなら、leftのautoは無視されます。
  5. widthがautoで、leftとrightがautoでないなら、widthが伸縮して幅が調整されます。
  6. rightがautoで、leftとwidthがautoでないなら、rightのautoは無視されます。