要素の寸法や位置は、しばしば包含ブロック (containing block) に影響されます。多くの場合、包含ブロックは要素から見て直近のブロックレベルの祖先のコンテンツ領域ですが、常にそうとは限りません。この記事では、要素の包含ブロックが決まる要因を学びます。

ユーザーエージェント (ブラウザーなど) が文書をレイアウトする時、それぞれの要素にボックスを生成します。それぞれのボックスは4つの領域に分かれます。

  1. コンテンツ領域
  2. パディング領域
  3. 境界領域
  4. マージン領域

多くの開発者が、要素の包含ブロックは常に親要素のコンテンツ領域であると信じていますが、それは必ずしも正しくありません。要素の包含ブロックが何になるかを決定する要因を調べてみましょう。

包含ブロックの影響

何が要素の包含ブロックを決定するかを学習する前に、最初になぜそのようなことが起こるのかを知っておくと役立ちます。

要素の寸法と位置は、しばしば包含ブロックに影響されます。 width, height, padding, margin に適用されるパーセント値や、絶対位置指定要素 (つまり、 positionabsolute 又は fixed に設定されている要素) のオフセットプロパティは、要素の包含ブロックから計算されます。

包含ブロックの識別

包含ブロックを識別するプロセスは、要素の position プロパティの値に全面的に依存します。

  1. position プロパティが static 又は relative の場合、包含ブロックはブロックコンテナー (inline-block, block, list-item などの要素) 又は整形文脈を確立する要素 (表コンテナー、フレックスコンテナー、グリッドコンテナー、ブロックコンテナー自身など) である直近の祖先要素のコンテンツボックスの辺によって構成されます。
  2. position プロパティが absolute の場合、包含ブロックは position の値が static 以外 (fixed, absolute, relative, sticky) の直近の祖先要素におけるパディングボックスの辺によって構成されます。
  3. position プロパティが fixed の場合、包含ブロックはビューポート (連続的なメディアの場合) 又はページ領域 (ページメディアの場合) によって確立されます。
  4. position プロパティが absolute 又は fixed の場合、包含ブロックは以下の条件を持った直近の祖先要素におけるパディングボックスの辺によって構成されることがあります。
    1. transform 又は perspective の値が none 以外である
    2. will-change の値が transform 又は perspective である
    3. filter の値が none 以外、又は will-change の値が filter の場合 (Firefox のみで動作)。

メモ: ルート要素 (<html>) が包含ブロックである場合、初期包含ブロックと呼ばれる矩形になります。これはビューポート (連続的なメディアの場合) 又はページ領域 (ページメディアの場合) の寸法を持ちます。

包含ブロックからのパーセント値の計算

前述の通り、特定のプロパティがパーセント値を与えられた場合、計算値は要素の包含ブロックに依存します。このように動作するプロパティはボックスモデルプロパティ及びオフセットプロパティです。

  1. height, top, bottom の各プロパティは、包含ブロックの height からパーセント値を計算します。包含ブロックの高さが内容物に依存する場合、包含ブロックの positionrelative 又は static であれば、これらの値は 0 になります。
  2. width, left, right, padding, margin の各プロパティは、包含ブロックの width からパーセント値を計算します。

いくつかの例

すべての例の HTML コードは以下の通りです。

<body>
  <section>
    <p>This is a paragraph!</p>
  </section>
</body>

以下のそれぞれの例では、 CSS のみが異なります。

例 1

この例では、段落が静的に配置されているため、包含ブロックはブロックコンテナーである直近の祖先である <section> になります。

body {
  background: beige;
}

section {
  display: block;
  width: 400px;
  height: 160px;
  background: lightgray;
}

p {
  width: 50%;   /* == 400px * .5 = 200px */
  height: 25%;  /* == 160px * .25 = 40px */
  margin: 5%;   /* == 400px * .05 = 20px */
  padding: 5%;  /* == 400px * .05 = 20px */
  background: cyan;
}

例 2

この例では、 <section> が (display: inline であるため) ブロックコンテナーではなく、整形文脈を確立しないので、段落の包含ブロックは <body> 要素になります。

body {
  background: beige;
}

section {
  display: inline;
  background: lightgray;
}

p {
  width: 50%;     /* == half the body's width */
  height: 200px;  /* Note: a percentage would be 0 */
  background: cyan;
}

例 3

この例では、 <section>positionabsolute であるため、段落の包含ブロックは <section> になります。段落のパーセント値は、包含ブロックのパディングに影響されますが、 box-sizing の値が border-box である場合はそのようにはなりません。

body {
  background: beige;
}

section {
  position: absolute;
  left: 30px;
  top: 30px;
  width: 400px;
  height: 160px;
  padding: 30px 20px;
  background: lightgray;
}

p {
  position: absolute;
  width: 50%;   /* == (400px + 20px + 20px) * .5 = 220px */
  height: 25%;  /* == (160px + 30px + 30px) * .25 = 55px */
  margin: 5%;   /* == (400px + 20px + 20px) * .05 = 22px */
  padding: 5%;  /* == (400px + 20px + 20px) * .05 = 22px */
  background: cyan;
}

例 4

この例では、段落の positionfixed なので、包含ブロックは初期包含ブロック (画面の場合はビューポート) になります。従って、段落の寸法はブラウザーウィンドウの寸法に基づいて変化します。

body {
  background: beige;
}

section {
  width: 400px;
  height: 480px;
  margin: 30px;
  padding: 15px;
  background: lightgray;
}

p {
  position: fixed;
  width: 50%;   /* == (50vw - (width of vertical scrollbar)) */
  height: 50%;  /* == (50vh - (height of horizontal scrollbar)) */
  margin: 5%;   /* == (5vw - (width of vertical scrollbar)) */
  padding: 5%;  /* == (5vw - (width of vertical scrollbar)) */
  background: cyan;
}

例 5

この例では、段落の positionabsolute なので、包含ブロックは transform プロパティが none ではない直近の祖先である <section> になります。

body {
  background: beige;
}

section {
  transform: rotate(0deg);
  width: 400px;
  height: 160px;
  background: lightgray;
}

p {
  position: absolute;
  left: 80px;
  top: 30px;
  width: 50%;   /* == 200px */
  height: 25%;  /* == 40px */
  margin: 5%;   /* == 20px */
  padding: 5%;  /* == 20px */
  background: cyan;
}

関連情報

ドキュメントのタグと貢献者

このページの貢献者: mfuji09
最終更新者: mfuji09,