position: absoluteの基準位置は最も近いposition指定祖先で決まる
公開日: 執筆:佐藤
position: absoluteの基準位置は、単純に親要素で決まるわけではありません。祖先を近い順にたどり、positionがstatic以外の要素を最初に見つけます。その祖先が作る包含ブロックを基準に、top、right、bottom、leftで位置を決めます。
配置したい範囲の親要素へposition: relativeを指定し、その子要素へposition: absoluteを指定するのが基本です。位置指定された祖先が一つもなければ、初期包含ブロックが基準になります。
absoluteの基準位置は直近の親要素とは限らない
CSS 2.1の包含ブロックの定義では、絶対配置された要素の包含ブロックを、positionがabsolute、relative、fixedのいずれかである最も近い祖先が作ります。
ブロック要素の祖先なら、その祖先のpadding edgeが包含ブロックになります。すぐ上の親要素がposition: staticのままなら、さらに上の祖先を探します。
| 祖先の指定 | absolute要素が使う基準 |
|---|---|
親要素がposition: relative |
親要素が作る包含ブロック |
親要素はstatic、その上の祖先がrelative |
その上の祖先が作る包含ブロック |
| 位置指定された祖先がない | 初期包含ブロック |
HTMLの入れ子が、そのまま位置の基準になるとは限りません。HTML上の親子関係と、CSSで決まる包含ブロックを分けて確認します。
親にrelativeを指定して子をabsoluteで配置する
次の例では、カードの右上へ「新着」を配置します。商品名と説明は、配置関係を示すための仮例です。
<section class="product-card">
<h2>商品名</h2>
<p>商品の説明をここへ入れます。</p>
<span class="product-card__badge">新着</span>
</section>
.product-card {
position: relative;
padding: 24px;
border: 1px solid #999;
}
.product-card__badge {
position: absolute;
top: 8px;
right: 8px;
}
.product-cardは、position: relativeによって位置指定された要素になります。この例ではtopなどを親へ指定していないため、親自身の位置は動きません。子の.product-card__badgeにとっては、この親が最も近い位置指定祖先です。
top: 8pxは、子要素の上側のmargin edgeを包含ブロックの上端から8px下へ置きます。right: 8pxは、子要素の右側のmargin edgeを包含ブロックの右端から8px左へ置きます。
topとrightとbottomとleftは基準にする辺を選ぶ
CSS 2.1のbox offsetsは、四つのプロパティを包含ブロックの辺からの距離として定義しています。
| プロパティ | absolute要素の位置 |
|---|---|
top |
包含ブロックの上端から下へ置く |
right |
包含ブロックの右端から左へ置く |
bottom |
包含ブロックの下端から上へ置く |
left |
包含ブロックの左端から右へ置く |
右上へ置くならtopとright、左下へ置くならbottomとleftというように、基準にする二辺を選びます。四辺を何となく指定するのではなく、幅と高さを含めて、どの辺から位置を決めるかを先に決めます。
relativeは通常フローの位置を残したまま基準を作る
position: relativeとposition: absoluteは、同じtopやleftを使っても役割が違います。
CSS 2.1のpositionプロパティでは、relativeの要素を通常フローで配置したあと、その通常位置からずらします。後続要素の位置は、ずらす前の位置を使って計算します。元の場所に確保された空間も残ります。
一方、absoluteの要素は通常フローから外れます。後続要素の配置へ影響せず、元の場所に空間を残しません。親へrelativeを指定する例では、この違いを利用しています。親は通常フローへ残し、子だけを親の内側へ絶対配置します。
absolute要素の高さだけでは親の高さを確保できない
絶対配置された要素は通常フローから外れるため、その高さを頼りに親要素の高さは確保できません。前のカード例では、通常フローにある見出しと段落がカードの高さを作り、絶対配置した印を右上へ重ねています。
カードの本文までabsoluteにすると、後続するカードは、その本文が通常フローにいないものとして配置されます。内容の長さが変われば、重なりやはみ出しが起こり得ます。文章、画像、フォームなど、前後の要素を押し広げる必要がある内容は通常フローへ残します。
absoluteは、基準と寸法を決められる部品へ使います。印、アイコン、閉じるボタンなどを既存の内容へ重ねる用途なら、親の余白も含めて場所を確保します。
位置指定祖先がなければ初期包含ブロックが基準になる
次のように、カードへposition: relativeを指定し忘れると、.product-card__badgeはカードを基準にしません。
.product-card__badge {
position: absolute;
top: 0;
right: 0;
}
先に、さらに上の祖先にrelative、absolute、fixedがないかを確認します。該当する祖先があれば、その要素が基準です。一つもなければ、連続媒体ではビューポートと同じ寸法を持ち、キャンバスの原点に固定された初期包含ブロックが基準になります。
「親の右上へ置いたつもりなのに離れた場所へ移る」ときは、数値を増減する前に包含ブロックを特定します。対象要素から祖先を一つずつたどり、最初に見つかるstatic以外のpositionを確認してください。
CSS 2.1では、位置指定されたinline要素が複数行に分かれる場合、その子の包含ブロックは未定義です。配置の基準にする祖先は、前の例のようなブロック要素にすると、基準の四辺を追いやすくなります。
まず、意図した位置から外れているabsolute要素を一つ選びます。祖先を近い順に調べ、基準にしたい要素へposition: relativeを指定したうえで、top、right、bottom、leftを調整してください。
関連記事

