CSSのレイアウトと包含ブロック

CSSで文書をレイアウトする際、その要素の位置や寸法は、【包含ブロック】というものに影響を受けます。

多くの場合では、包含ブロックはその要素から見て直近のブロックレベルの祖先要素になりますが、例外もあります。

前の記事のおさらいですが、CSSでは、領域を上のような長方形の領域で描画する、と紹介しましたが、このボックスがどこを基点にするのか?サイズが【相対的な値】で指定された場合は、どこに対しての相対的な値なのか?という点を理解するのに、【包含ブロック】への理解が必要となります。

包含ブロックの影響

包含ブロックの影響を受ける代表的なものは、要素の寸法や位置ですが、具体的には下記のプロパティ値の計算で包含ブロックの影響を受けています。

  • width, height, padding, margin のなどの【寸法】を指定する各プロパティ
    • % などの相対値が指定された場合、包含ブロックの寸法に対しての相対値が計算値となります。
  • position が absolute 又は fixed に設定されている要素に対してのオフセット値( top , bottom , left , right の各プロパティ)
    • 相対値が指定された場合は、包含ブロックの寸法に対しての相対値が計算値となります。
    • 相対値か絶対値かに関わらず、オフセットの【基点】は包含ブロックの位置になります。

相対値(%値)の計算方法

ボックスモデルプロパティ及びオフセットプロパティに対してパーセント値が指定された場合、以下のように計算されます。

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

包含ブロックの識別

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

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

サンプル

これからいくつかのサンプルを紹介しますが、いずれも下記の同じ HTML 文書を使用します。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <section>
        <p>ここに段落があります。</p>
    </section>
</body>
</html>

例1 

body { 
  background: aliceblue;
}
section {
  display: block;
  width: 400px;
  height: 160px;
  background: lemonchiffon; 
} 
p { 
  width: 50%; /* == 400px * 0.5 = 200px */ 
  height: 25%; /* == 160px * 0.25 = 40px */ 
  margin: 5%; /* == 400px * 0.05 = 20px */ 
  padding: 5%; /* == 400px * 0.05 = 20px */ 
  background: aquamarine; 
}

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

例2

body {
  background: aliceblue;
}
section {
  display: inline;
  background: lemonchiffon;
}
p {
  width: 50%;   /* <body>要素の幅の50% */
  height: 25%;  /* == 0px * 0.25 = 0 ??? */
  background: aquamarine;
}

この例では、段落の直近の親要素が inline になっていて、ブロックコンテナーでも整形文脈を確立する要素でも無いため、この場合の包含ブロックは <body> 要素になります。

ただし、この場合の <body> 要素は「包含ブロックの高さが内容物に依存する場合」に該当するので、高さを相対値で指定しようとしても上手くいきません。

この場合の包含ブロックの高さは”0px”と扱われるので、<p> 要素の高さも “0px”になってしまいそうですが、実際には行の高さの分だけ、高さが取られています。ただ、height の値を50%や100%に変えても高さは変わらないので、いずれにしても高さを相対値で指定することは出来ないようです。

例3

body {
    background: aliceblue;
}
section {
    position: absolute;
    left: 30px;
    top: 30px;
    display: block;
    width: 400px;
    height: 160px;
    padding: 30px 20px;
    background: lemonchiffon;
}
p {
    position: absolute;
    width: 50%;   /* == (400px + 20px + 20px) * 0.5 = 220px */
    height: 25%;  /* == (160px + 30px + 30px) * 0.25 = 55px */
    margin: 5%;   /* == (400px + 20px + 20px) * 0.05 = 22px */
    padding: 5%;  /* == (400px + 20px + 20px) * 0.05 = 22px */
    background: aquamarine;
}

この例では、段落の position が absolute で、直近の親要素も postion: absolute; なので、包含ブロックは <section> 要素になります。

ただ、例1と違って、包含ブロックの寸法は、<section> 要素の【パディング領域】となりますので、<p> 要素の大きさが若干変わります。

例4

body {
    background: aliceblue;
}
section {
    position: absolute;
    left: 30px;
    top: 30px;
    display: block;
    width: 400px;
    height: 160px;
    padding: 30px 20px;
    background: lemonchiffon;
}
p {
    position: fixed;
    width: 50%;   /* == 50vw (viewport幅の50%) */
    height: 25%;  /* == 50vh (viewport高さの50%) */
    margin: 5%;   /* == 5vw (viewport幅の5%) */
    padding: 5%;  /* == 5vw (viewport幅の5%) */
    background: aquamarine;
}

この例では、<p> 要素に position: fixed; が指定されているので、包含ブロックはビューポートとなります。

例5

body {
    background: aliceblue;
}
section {
    transform: rotate(0deg);
    display: block;
    width: 400px;
    height: 160px;
    background: lemonchiffon;
}
p {
    position: absolute;
    left: 80px;
    top: 30px;
    width: 50%;   /* == 400px * 0.5 = 200px */
    height: 25%;  /* == 160px * 0.25 = 40px */
    margin: 5%;   /* == 400px * 0.05 = 20px */
    padding: 5%;  /* == 400px * 0.05 = 20px */
    background: aquamarine;
}

この例では、要素に position: absolute; が指定されています。対して、直近の親要素の <section> 要素は、position プロパティが指定されていないので、初期値の static です。

これだけだと、包含ブロックは <body> 要素になってしまいそうですが、<section> 要素には、transform プロパティに none 以外が指定されているので、この場合の包含ブロックは <section> 要素になります。

 


このサイトでは、CSSのセレクタ・プロパティなどの定義は下記サイトを参考にしています。
MDN Web Docs: https://developer.mozilla.org/ja/
W3C仕様の正確な定義、最新情報は上記サイトをご覧ください。
CSSのプロパティがどのブラウザに対応しているのかは、下記のサイトで確認できます。
Can I Use?: https://caniuse.com/#home

コメント

タイトルとURLをコピーしました