CSSのpositionプロパティ完全ガイド|static・relative・absolute・fixed・stickyの使い分けを徹底解説


はじめに

前回の記事ではCSSの !important の正しい使い方と注意点・代替手段を解説しました。その中で「詳細度を正しく理解すること」の大切さに触れましたが、今回はCSSのレイアウトを制御するうえで欠かせない position プロパティを改めて整理します。staticrelativeabsolutefixedsticky の5種類はそれぞれ動作が大きく異なり、使い分けを誤ると「要素が消えた」「重なりがおかしい」「スクロールしたらズレた」といったトラブルの原因になります。一つずつ丁寧に解説します。


1. positionプロパティの基本

1.1 positionとは何か

position プロパティは要素をどのように配置するかを決めるCSSプロパティです。通常のドキュメントフロー(HTMLの記述順に上から下へ要素が並ぶ状態)から要素を「切り離す」かどうか・どの基準点に対して位置を決めるかを制御します。

通常フローからの切り離し基準点
staticなし(デフォルト)通常フロー
relativeなし自分自身の元の位置
absoluteあり直近の positionstatic の祖先要素
fixedありビューポート(画面)
sticky条件付きスクロールコンテナ

1.2 top・right・bottom・leftとの関係

positionstatic 以外に設定すると toprightbottomleft プロパティで位置を調整できます。

.element {
    position: relative;
    top:  20px;   /* 元の位置から20px下にずらす */
    left: 10px;   /* 元の位置から10px右にずらす */
}

⚠️ position: static(デフォルト)の要素には topleft などが効きません: デフォルトの static では位置調整プロパティが無視されます。位置を動かしたい場合はまず position の値を変更する必要があります。


2. position: static(デフォルト)

2.1 動作の仕組み

static はすべての要素に適用されるデフォルト値です。通常のドキュメントフローに従って配置され、toprightbottomleftz-index は効きません。

/* 以下の2つは同じ意味 */
.element {
    position: static; /* デフォルト値なので書かなくても同じ */
}

.element {
    /* positionを指定しない=staticと同じ */
}

2.2 staticを明示的に使うケース

/* 親要素のpositionをリセットしたいとき */
.parent {
    position: relative; /* 他の場所でrelativeが設定されている */
}

.child-reset {
    position: static; /* positonをデフォルトに戻す */
}

💡 position: static を明示的に書くケースは「上書きのリセット」がほとんどです: 継承や他のCSSで position: relative などが設定されている要素をデフォルトに戻したいときに使います。


3. position: relative(相対配置)

3.1 動作の仕組み

relative自分自身の元の位置を基準にして topleft などで位置をずらします。重要なのは「元の場所のスペースは保持される」という点です。

.box {
    position: relative;
    top:  20px;  /* 元の位置から20px下に移動 */
    left: 30px;  /* 元の位置から30px右に移動 */
}
通常フロー:
┌──────────┐
│  Box A   │  ← 元の位置のスペースは残る
└──────────┘
      ↓ 実際の表示位置(20px下・30px右にずれている)
         ┌──────────┐
         │  Box A   │
         └──────────┘

3.2 relativeの最も重要な役割

relative の最大の使いどころは位置をずらすことよりも、子要素の absolute の基準点を作ることです。

/* 親要素にrelativeを設定して基準点にする */
.card {
    position: relative;  /* ← これが重要 */
    width: 300px;
    height: 200px;
}

/* 子要素のabsoluteはこの.cardを基準にする */
.card__badge {
    position: absolute;
    top:   12px;
    right: 12px;
}

💡 「absoluteを使いたいときは親にrelativeを付ける」と覚えましょう: この組み合わせはCSSレイアウトの基本パターンで、バッジ・ツールチップ・オーバーレイなど幅広い場面で使います。


4. position: absolute(絶対配置)

4.1 動作の仕組み

absolute は通常のドキュメントフローから完全に切り離されます。周囲の要素は absolute 要素の存在を無視して配置されます。基準点は「直近の positionstatic 以外の祖先要素」です。

.parent {
    position: relative;  /* absoluteの基準点 */
    width: 400px;
    height: 300px;
}

.child {
    position: absolute;
    top:   0;     /* parentの上端から0px */
    right: 0;     /* parentの右端から0px */
    width: 80px;
    height: 80px;
}

4.2 基準点の探し方

absolute 要素は親を遡って最初に見つかった position: static 以外の要素を基準にします。

<div class="grandparent">          <!-- position: static(デフォルト) -->
    <div class="parent">           <!-- position: relative ← ここが基準! -->
        <div class="child"></div>  <!-- position: absolute -->
    </div>
</div>
/* 基準点が見つからない場合はbody(またはhtml)が基準になる */
.child-no-anchor {
    position: absolute;
    top:  0;
    left: 0;
    /* → 祖先にpositionが設定されていなければページ全体の左上が基準 */
}

⚠️ absolute を使ったのに想定外の場所に表示される場合は、基準点となっている祖先要素を確認しましょう: Chrome DevToolsのElementsタブで祖先要素を確認し、意図しない position が設定されていないかチェックします。

4.3 absoluteの実践的な使用例

/* カードの右上にバッジを配置する */
.product-card {
    position: relative;
}

.product-card__new-badge {
    position: absolute;
    top:   16px;
    right: 16px;
    padding:          4px 12px;
    background-color: #E24B4A;
    color:            white;
    border-radius:    4px;
    font-size:        1.2rem;
    font-weight:      600;
}

/* 画像の上にオーバーレイを重ねる */
.image-wrapper {
    position: relative;
    overflow: hidden; /* absoluteがはみ出ないようにする */
}

.image-wrapper__overlay {
    position: absolute;
    inset: 0;   /* top:0; right:0; bottom:0; left:0; の短縮形 */
    background: rgba( 0, 0, 0, 0.4 );
    display:    flex;
    align-items: center;
    justify-content: center;
    opacity:    0;
    transition: opacity 0.3s ease;
}

.image-wrapper:hover .image-wrapper__overlay {
    opacity: 1;
}

💡 inset: 0top: 0; right: 0; bottom: 0; left: 0; の短縮形です: 要素を親要素いっぱいに広げたいときに便利なCSS論理プロパティです。


5. position: fixed(固定配置)

5.1 動作の仕組み

fixedabsolute と同じくドキュメントフローから切り離されますが、基準点が**ビューポート(ブラウザの表示領域)**になります。スクロールしても画面上の同じ位置に表示され続けます。

/* ページ右下に固定されるトップへ戻るボタン */
.back-to-top {
    position: fixed;
    bottom: 32px;
    right:  32px;
    width:  48px;
    height: 48px;
    background:    var( --color-primary );
    border-radius: 50%;
    cursor:        pointer;
    z-index:       100;
    display:       flex;
    align-items:   center;
    justify-content: center;
    box-shadow: 0 4px 12px rgba( 0, 0, 0, 0.2 );
    transition: opacity 0.3s ease, transform 0.3s ease;
}

/* スクロール前は非表示 */
.back-to-top.is-hidden {
    opacity:   0;
    transform: translateY( 8px );
    pointer-events: none;
}

5.2 fixedの主な使用場面

用途実装例
固定ヘッダーtop: 0; left: 0; width: 100%;
チャットボタンbottom: 24px; right: 24px;
クッキー同意バーbottom: 0; left: 0; width: 100%;
モーダルの背景オーバーレイinset: 0;(全画面)
トップへ戻るボタンbottom: 32px; right: 32px;

5.3 fixedを使うときの注意点

/* 固定ヘッダーの高さ分だけbodyにpaddingを追加する */
body {
    padding-top: 64px; /* ヘッダーの高さと合わせる */
}

.site-header {
    position: fixed;
    top:    0;
    left:   0;
    width:  100%;
    height: 64px;
    z-index: 100;
    background: white;
}

⚠️ 固定ヘッダーを使う場合はその高さ分だけ bodypadding-top を追加しましょう: fixed 要素はドキュメントフローから切り離されているため、ヘッダーの下にコンテンツが隠れてしまいます。


6. position: sticky(スクロール追従)

6.1 動作の仕組み

stickyrelativefixedハイブリッドです。通常は通常フローの中に存在しますが、スクロールが特定のしきい値に達すると fixed のように画面に固定されます。

.section-heading {
    position: sticky;
    top: 72px; /* スクロール時にビューポートの上端から72pxで固定される */
    background: white;
    z-index: 10;
    padding: 12px 0;
}
スクロール前:                スクロール中(しきい値を超えたとき):
┌──────────────────┐         ┌──────────────────┐
│  Section Title   │ ← 通常  │  Section Title   │ ← 画面上部に固定
│──────────────────│         │──────────────────│
│  content...      │         │  content...      │
│  content...      │         │  content...      │
└──────────────────┘         └──────────────────┘

6.2 stickyが効かない原因と解決策

sticky は正しく設定しないと機能しないことがあります。

原因解決策
topbottomなどが未指定必ず top: 0 などのしきい値を設定する
親要素に overflow: hidden がある親要素の overflowvisible または auto にする
親要素の高さが子要素と同じ固定される余地がないため効かない。親の高さを確保する
親要素に overflow: auto があるsticky はスクロールコンテナを基準にするため意図した動作にならない場合がある
/* stickyが効かない例 */
.parent {
    overflow: hidden; /* ← これがあるとstickyが効かない */
}

.sticky-element {
    position: sticky;
    top: 0;
}

/* 解決策 */
.parent {
    overflow: visible; /* または overflow プロパティを削除する */
}

⚠️ position: sticky が効かない原因の大半は祖先要素の overflow: hidden です: Chrome DevToolsで祖先要素を一つずつ確認して overflow が設定されていないか確認しましょう。

6.3 stickyの実践的な使用例

/* テーブルのヘッダー行を固定する */
.data-table th {
    position: sticky;
    top:        0;
    background: var( --color-bg-sub );
    z-index:    1;
    border-bottom: 2px solid var( --color-border );
}

/* サイドバーを本文スクロールに追従させる */
.sidebar {
    position: sticky;
    top:       96px; /* ヘッダーの高さ + 余白 */
    max-height: calc( 100vh - 96px - 32px );
    overflow-y: auto;
}

/* セクションごとのラベルをスクロール中に上部に固定する */
.timeline__label {
    position: sticky;
    top:        64px;
    background: white;
    font-weight: 600;
    padding:    8px 0;
    z-index:    5;
}

7. z-indexとの関係

7.1 z-indexが効く要素・効かない要素

z-index は要素の重なり順を制御するプロパティですが、position: static の要素には効きません

/* ❌ z-indexが効かない */
.element {
    position: static; /* デフォルト */
    z-index:  100;    /* 効かない */
}

/* ✅ z-indexが効く */
.element {
    position: relative; /* または absolute / fixed / sticky */
    z-index:  100;
}

7.2 重なり順の管理

/* z-indexの設計例(大きな数値は使わない) */
:root {
    --z-base:    0;
    --z-raised:  10;
    --z-dropdown: 20;
    --z-sticky:  30;
    --z-fixed:   40;
    --z-modal:   50;
    --z-toast:   60;
}

.site-header    { z-index: var( --z-fixed ); }
.dropdown-menu  { z-index: var( --z-dropdown ); }
.modal-overlay  { z-index: var( --z-modal ); }
.toast-message  { z-index: var( --z-toast ); }

💡 z-index はCSS変数で段階管理すると秩序が保てます: z-index: 9999 のような値を使い始めると管理が崩壊します。変数で段階を定義しておくと、どの要素がどのレイヤーにいるかが一目でわかります。


8. 5種類の使い分けまとめ

8.1 どれを使えばよいか判断フロー

要素を動かしたい・位置を調整したい
              ↓
スクロールしても画面に固定したい?
  → はい → fixed
  → いいえ
              ↓
スクロールに応じて途中から固定したい?
  → はい → sticky(必ずtopなどのしきい値を設定する)
  → いいえ
              ↓
通常フローから切り離して自由な位置に置きたい?
  → はい → absolute(親にrelativeを付けて基準点を作る)
  → いいえ
              ↓
子要素のabsoluteの基準点にしたい・または少しずらしたい?
  → はい → relative
  → それ以外 → static(デフォルト)

8.2 よくある組み合わせパターン

パターン実装
カードのバッジ親に relative・バッジに absolute
固定ヘッダーfixed + bodypadding-top
スクロールで固定されるサイドバーsticky + top: ヘッダー高さ
モーダルの背景fixed + inset: 0
画像ホバーオーバーレイ親に relative・オーバーレイに absolute + inset: 0
テーブルヘッダー固定sticky + top: 0

9. 実践チェックリスト

position を設定する前に「何を基準に配置するか」を明確にしたか

absolute を使う場合、意図した祖先要素に relative が設定されているか確認したか

fixed を使う場合、その要素の高さ分だけ body や直後の要素に余白を追加したか

sticky が効かない場合、祖先要素の overflow: hidden を確認したか

sticky には必ず topbottomleftright のいずれかのしきい値を設定したか

z-index を使う要素に position: static 以外が設定されているか確認したか

z-index の値をCSS変数で段階管理して大きな数値を使っていないか

Chrome DevToolsでレイアウトを確認して意図しない重なりがないか確認したか


まとめ

今回はCSSの position プロパティの5種類を使い分けの観点から解説しました。ポイントをまとめると:

  • static はデフォルト値でドキュメントフローに従って配置される。topleft などは効かない
  • relative は元の位置を基準にずらせる。より重要な役割は子要素の absolute の基準点を作ること
  • absolute はドキュメントフローから切り離され「直近の positionstatic 祖先要素」を基準にする。使うときは親に relative を付けることがセット
  • fixed はビューポートを基準にしてスクロールしても固定される。ヘッダー・モーダル背景・チャットボタンに使う
  • sticky は通常フローにありながらスクロールのしきい値を超えると固定される。必ずしきい値を設定し祖先の overflow: hidden に注意する
  • z-indexstatic 以外の要素にしか効かない。CSS変数で段階管理すると秩序が保てる

次の記事では、Webフォームのユーザビリティを高めるCSSとJavaScriptのテクニックを解説します。お楽しみに!

コメント

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