はじめに
前回の記事ではCSSの !important の正しい使い方と注意点・代替手段を解説しました。その中で「詳細度を正しく理解すること」の大切さに触れましたが、今回はCSSのレイアウトを制御するうえで欠かせない position プロパティを改めて整理します。static・relative・absolute・fixed・sticky の5種類はそれぞれ動作が大きく異なり、使い分けを誤ると「要素が消えた」「重なりがおかしい」「スクロールしたらズレた」といったトラブルの原因になります。一つずつ丁寧に解説します。
1. positionプロパティの基本
1.1 positionとは何か
position プロパティは要素をどのように配置するかを決めるCSSプロパティです。通常のドキュメントフロー(HTMLの記述順に上から下へ要素が並ぶ状態)から要素を「切り離す」かどうか・どの基準点に対して位置を決めるかを制御します。
| 値 | 通常フローからの切り離し | 基準点 |
|---|---|---|
static | なし(デフォルト) | 通常フロー |
relative | なし | 自分自身の元の位置 |
absolute | あり | 直近の position 非 static の祖先要素 |
fixed | あり | ビューポート(画面) |
sticky | 条件付き | スクロールコンテナ |
1.2 top・right・bottom・leftとの関係
position を static 以外に設定すると top・right・bottom・left プロパティで位置を調整できます。
.element {
position: relative;
top: 20px; /* 元の位置から20px下にずらす */
left: 10px; /* 元の位置から10px右にずらす */
}
⚠️ position: static(デフォルト)の要素には top・left などが効きません: デフォルトの static では位置調整プロパティが無視されます。位置を動かしたい場合はまず position の値を変更する必要があります。
2. position: static(デフォルト)
2.1 動作の仕組み
static はすべての要素に適用されるデフォルト値です。通常のドキュメントフローに従って配置され、top・right・bottom・left・z-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 は自分自身の元の位置を基準にして top・left などで位置をずらします。重要なのは「元の場所のスペースは保持される」という点です。
.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 要素の存在を無視して配置されます。基準点は「直近の position が static 以外の祖先要素」です。
.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: 0 は top: 0; right: 0; bottom: 0; left: 0; の短縮形です: 要素を親要素いっぱいに広げたいときに便利なCSS論理プロパティです。
5. position: fixed(固定配置)
5.1 動作の仕組み
fixed も absolute と同じくドキュメントフローから切り離されますが、基準点が**ビューポート(ブラウザの表示領域)**になります。スクロールしても画面上の同じ位置に表示され続けます。
/* ページ右下に固定されるトップへ戻るボタン */
.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;
}
⚠️ 固定ヘッダーを使う場合はその高さ分だけ body に padding-top を追加しましょう: fixed 要素はドキュメントフローから切り離されているため、ヘッダーの下にコンテンツが隠れてしまいます。
6. position: sticky(スクロール追従)
6.1 動作の仕組み
sticky は relative と fixed のハイブリッドです。通常は通常フローの中に存在しますが、スクロールが特定のしきい値に達すると 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 は正しく設定しないと機能しないことがあります。
| 原因 | 解決策 |
|---|---|
top・bottomなどが未指定 | 必ず top: 0 などのしきい値を設定する |
親要素に overflow: hidden がある | 親要素の overflow を visible または 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 + body に padding-top |
| スクロールで固定されるサイドバー | sticky + top: ヘッダー高さ |
| モーダルの背景 | fixed + inset: 0 |
| 画像ホバーオーバーレイ | 親に relative・オーバーレイに absolute + inset: 0 |
| テーブルヘッダー固定 | sticky + top: 0 |
9. 実践チェックリスト
✓ position を設定する前に「何を基準に配置するか」を明確にしたか
✓ absolute を使う場合、意図した祖先要素に relative が設定されているか確認したか
✓ fixed を使う場合、その要素の高さ分だけ body や直後の要素に余白を追加したか
✓ sticky が効かない場合、祖先要素の overflow: hidden を確認したか
✓ sticky には必ず top・bottom・left・right のいずれかのしきい値を設定したか
✓ z-index を使う要素に position: static 以外が設定されているか確認したか
✓ z-index の値をCSS変数で段階管理して大きな数値を使っていないか
✓ Chrome DevToolsでレイアウトを確認して意図しない重なりがないか確認したか
まとめ
今回はCSSの position プロパティの5種類を使い分けの観点から解説しました。ポイントをまとめると:
staticはデフォルト値でドキュメントフローに従って配置される。top・leftなどは効かないrelativeは元の位置を基準にずらせる。より重要な役割は子要素のabsoluteの基準点を作ることabsoluteはドキュメントフローから切り離され「直近のposition非static祖先要素」を基準にする。使うときは親にrelativeを付けることがセットfixedはビューポートを基準にしてスクロールしても固定される。ヘッダー・モーダル背景・チャットボタンに使うstickyは通常フローにありながらスクロールのしきい値を超えると固定される。必ずしきい値を設定し祖先のoverflow: hiddenに注意するz-indexはstatic以外の要素にしか効かない。CSS変数で段階管理すると秩序が保てる
次の記事では、Webフォームのユーザビリティを高めるCSSとJavaScriptのテクニックを解説します。お楽しみに!
コメント