absolute, fixed, sticky, relativeの奥深さ
それぞれ概ね以下のように理解している人は多いと思います
- fixed: 画面を基準とした配置
- absolute: 親要素を?基準とした絶対位置
- relative: 親要素からの相対位置(???)
- sticky: 画面にひっついてくる
しかし、このように理解していても、postion: aboslute
や、position: fixed
を行うとすぐにレイアウトが崩れてしまい訳が分からなくなるという人は多いのではないでしょうか。
なぜそのような事が起きるかというと、absolute
.sitcky
,fixed
,relative
などを設定した要素に適用されるPositioned要素という概念と、Positioned要素の基準位置となるContaining Block、そしてPositioned要素の親要素のサイズ計算への影響について正しく理解していないためです。
少し難しいですが、Positioned 要素とContaining Block,そしてPositioned要素のサイズ計算について確認していきましょう。
Positioned Element(要素)
Positioned要素とは、HTMLの通常の配置フローから外れる要素です。
absolute
などを利用するとPositioned要素となり、他の配置フローとは異なった考え方をする必要が出てきます。
どのような場合にPositioned ELementとなるのかは正確に把握しましょう。
Positioned要素に該当する要素
positionプロパティーが以下の値の時、要素はPositioned要素となります。
fixed
absolute
relative
-
sticky
Positioned要素でないのはデフォルトのstatic
だけです。
それ以外の場合は通常の配置フローと異なった考え方をする必要があります。
Containing Block
Positioned要素の配置フローの基準位置となる場所(仮想の箱)が「Containing Block」です。
それぞれのPositioned要素ごとに、どこがContaining Blockとなるかは異なります。
Containing Blockを正しく把握しない事が混乱の元なので、正確に把握する必要があるでしょう。
それぞれのContaining Block
それぞれのpositionプロパティーに対応するContaining Blockがどれかは以下の通りです。
relative, staticの場合
この二つは通常通りの場所が基準となります。直近の親要素の上部(手前に兄弟要素がある場合、その要素を除いた部分)がContaining Blockとなります。
relativeがstaticと違うのは以下の2点です。
- 1.topやleftなどの値を設定できる。基準位置はContaining Block
- 2.子要素のPositioned要素のContaining Blockとして基準位置となる
2の特徴は特に重要で、relative要素は自身の配置をずらす目的よりも、absolute
の子要素の位置を調整するために使う事の方が多いように思います。
stickyの場合
stickyは非常に紛らわしいのですが、こちらもrelative
,static
と同様、直近の親要素がContaining Blockとなり、通常の配置フローにしたがって配置されます。
しかし、topなどの基準位置は、直近の親要素のうち,overflow
が「hidden
,auto
もしくはscroll
」となっているものとなり、親要素のoverflowがvisible
(default)となっているとstickyは機能しなくなります。** overlowが設定されている要素が存在しない場合はviewportが基準**となります。
かなり複雑ですが、relativeとfixedの両方の要素+アルファの性質があるといった感じです。
例えば以下の場合、id=3
のdiv
はid=1
の上から50px
の距離を取るように配置されます。
id=1
の上枠から50pxに引っかかるように挙動し、**id=2
(container block。Container Blockと固定の基準位置は異なる)**の下枠にぶつかるまで画面にくっついてきます。
<div id="1" style="position: overflow: hidden;">
<div id="2">
<div id="3" style="position: fixed; top: 50px;"></div>
</div>
</div>
画面の枠が基準となると理解している人も多いように思いますが、違うパターンになることも非常に多いです。
absoluteの場合
absolute
の場合、直近の親のPositioned要素がContaining Blockです。
例えば以下の場合、id=3
のdiv
の基準となるのは、2個上の親である id=1
のdiv
です。
id=1
のdivの上の枠から50pxの位置に配置されます。
id=1
のpositionがrelative
やabsolute
, fixed
でも同様の結果となります。
<div id="1" style="position: fixed">
<div id="2">
<div id="3" style="position: absolute; top: 50px;"></div>
</div>
</div>
fixedの場合
Viewport(ブラウザの枠)が基準となります。
下の場合、id=1やid=2の要素は無視され、ブラウザの上の枠から50pxの位置に配置されます。
<div id="1" style="position: relative">
<div id="2">
<div id="3" style="position: fixed; top: 50px;"></div>
</div>
</div>
Positioned要素の親要素のサイズの計算
HTMLにおいて、親要素のwidth, heightは指定しなければ内側の要素のサイズを計算してボトムアップ式に決定されます。しかし、子要素がabsolute, もしくはfixedの場合は親要素のサイズに影響を与えません。
まとめ
以上をまとめると以下のようになります。
position | Positioned | Container Block | 親要素のサイズ計算に含むか |
---|---|---|---|
static | × | 親要素 | 含む |
relative | ○ | 親要素 | 含む |
sticky | ○ | 親要素: 固定の基準位置はviewport(もしくは直近のoverflowが設定された親要素) | 含む |
fixed | ○ | viewport | 含まない |
absolute | ○ | 親のPositioned要素 | 含まない |
CSSがうまく機能しない理由の大半はこのへんの理解が深まれば解消するのではないかと思います。
しかし、ここまででも十分複雑ですがここにも記述しきれなかった例外規則なども多数あります。
困った時はちゃんとドキュメントに当たるようにしましょう。
参考