CSS positionの使い方|relative・absolute・fixed・stickyを比べる
※本記事にはPRを含む場合があります。
こんにちは。『脱会社員』脱サラを応援し続けるブログ、運営者の『なかびー』です。
CSSのpositionは、要素をどの仕組みで配置するかを決めるプロパティです。最初に「通常の流れに場所を残すか」「何を基準に位置を決めるか」「スクロールするとどう動くか」の三つを分けると理解しやすくなります。topやleftの数値を動かす前に、配置の基準を確かめましょう。
この記事ではカードのバッジ、少しずらした文字、枠内の見出し、ページ先頭へのリンクを作り、relative・absolute・fixed・stickyの違いを比較します。ページ全体を座標で固定する練習ではなく、小さな部品を適した方法で置くための例です。重なりの順番と、文字拡大や狭い画面での確認も扱います。
仕様は2026年10月4日に確認したMDNの現行CSS資料に基づきます。掲載コードは自己完結したHTML/CSSで、ローカルでは要素の親子関係、指定値、リンク、条件の対応を照合しました。検証環境のブラウザー起動制約により、実際の配置、スクロール、キーボード操作は未検証です。コードの点検と描画結果は区別して説明します。画像は実際の画面ではない説明用の生成イメージです。
五つのpositionを、通常の流れと配置基準で見分ける

通常の流れは、ほかの要素が場所を決める基礎
HTMLの要素は、通常、文書の順序やレイアウトの規則に沿って並びます。段落を一つ増やせば後ろの段落が下へ動くように、要素同士が場所を分け合う仕組みがあります。この通常の流れを理解せず、見た目の座標だけを合わせると、文章が増えたときに重なりやはみ出しが起こりやすくなります。
position: staticは、位置指定を特に行わない基本の状態です。一般的な通常フローの要素へtop: 20pxだけを書いても、期待したように下へ移動しません。まずpositionの値とレイアウトの種類を確認します。なお、z-indexにはGridやFlexの項目で使えるケースもあるため、staticという言葉だけで重なりのすべてを判断しないようにします。
positionを変える必要があるかも、先に考えます。横並びや余白調整が目的なら、Grid、Flexbox、margin、paddingなどで自然に配置できることがあります。文章の量に合わせて伸びるべき領域をabsoluteで固定してしまうと、後からの更新が難しくなります。用途に合う小さな範囲から使いましょう。
relativeは、元の場所を残してずらす
relativeは、通常の位置を基にtop、right、bottom、leftなどで見た目をずらせます。移動しても元の配置上の場所は残り、後ろの要素がその空間へ自動で詰めてくるわけではありません。そのため、少しの調整には使えても、大きく動かすと空白や重なりが生まれる場合があります。
もう一つ重要なのは、子のabsolute要素の基準を作る用途です。relativeを指定しても、topなどを設定しなければ見た目の位置を動かさず、基準として利用できます。今回のカードはこの方法で、カード内の右上にバッジを配置する例にします。
absoluteとfixedは、通常の流れから外れる
absoluteは通常の流れから外れ、その要素のための場所が通常の配置に確保されません。一般的には近くにある位置指定された祖先などを基準に置かれますが、transformなど別の指定が基準を作る場合もあります。「必ず直上の親が基準」と暗記せず、どの祖先が基準を作っているかを見ます。
fixedも通常の流れから外れ、一般的な画面表示ではビューポートを基準に置く用途で使います。ただし、祖先のtransformなどで基準が変わる場合があります。スクロールしても画面の端に置きたい要素で便利ですが、本文を覆って読めなくしないように設計する必要があります。
stickyは、スクロール領域の中で位置を保つ
stickyは通常の流れに参加しながら、指定した位置に達したとき、スクロール領域の中で位置を保つ用途で使います。上側へとどめたいならtopのような基準値が必要です。スクロールする祖先や包含ブロックの範囲に制約されるので、fixedのようにいつでも画面全体へ固定されると考えないでください。
五つの値の基本は、MDNのposition資料で確認できます。以下の表は、今回の単純な構成で役割を覚えるための整理です。祖先の指定やレイアウトによる例外は、後の章で補足します。
※表は横にスクロールできます。
| 値 | 通常の配置に場所が残るか | 主な基準の考え方 | 今回の役割 |
|---|---|---|---|
| static | 残る | 通常の流れ | 普通の段落 |
| relative | 残る | 元の自分の位置、子の基準にも使う | カードと少しずらす文字 |
| absolute | 通常は残らない | 基準を作る祖先など | カード右上のバッジ |
| fixed | 通常は残らない | 一般にはビューポート、祖先による例外あり | 広い画面の先頭リンク |
| sticky | 残る | スクロールする祖先と包含ブロック | 枠内の見出し |
relativeの親とabsoluteの子で、カードのバッジを配置する

一つのHTMLファイルで、四つの違いを並べる
次のコードを、専用の練習フォルダーにpractice.htmlなどの名前で保存します。UTF-8を使い、既存のサイトのファイルへ直接上書きしないでください。外部画像やJavaScriptを使わず、配置だけを比較できる構成です。リンクは同じページの先頭へ戻るためのもので、外部への送信はありません。
コードには、relativeのカード、absoluteのバッジ、relativeで少しずれる文字、stickyの見出し、fixedの先頭リンクを含めています。480px以下では先頭リンクを通常の流れへ戻し、狭い幅では固定表示に頼らない例にしています。実際に表示したときの安全性は、文字の大きさと操作環境を変えて確認します。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>positionの練習</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; padding: 24px 24px 110px; color: #172c3b; font-family: sans-serif; }
main { max-width: 720px; margin: auto; }
.card { position: relative; padding: 72px 20px 20px; border: 2px solid #526f83; border-radius: 8px; }
.badge { position: absolute; top: 14px; right: 14px; padding: 8px 12px; background: #164e74; color: white; }
.offset { position: relative; top: 4px; left: 8px; display: inline-block; background: #fff1b5; }
.scroll-box { height: 280px; overflow: auto; border: 2px solid #526f83; margin-top: 24px; scroll-padding-top: 80px; }
.scroll-title { position: sticky; top: 0; z-index: 1; margin: 0; padding: 16px; background: #dcebf4; font-size: 1.2rem; }
.step { min-height: 80px; margin: 0; padding: 20px 16px; border-top: 1px solid #718796; line-height: 1.6; overflow-wrap: anywhere; }
.to-top { position: fixed; right: 16px; bottom: 16px; z-index: 2; padding: 12px 16px; color: white; background: #183f69; }
a:focus-visible, .scroll-box:focus-visible { outline: 3px solid #a04e00; outline-offset: 3px; }
@media (max-width: 480px) {
.to-top { position: static; display: inline-block; margin-top: 24px; }
}
</style>
</head>
<body>
<main id="top">
<h1>配置基準とスクロールを比べる</h1>
<section class="card" aria-labelledby="card-title">
<span class="badge">練習用</span>
<h2 id="card-title">カードのバッジ</h2>
<p>バッジは、このカードを基準に配置します。</p>
<p><span class="offset">少しだけ移動する文字</span>の元の場所は通常の流れに残ります。</p>
</section>
<div class="scroll-box" tabindex="0" role="region" aria-labelledby="steps-title">
<h2 class="scroll-title" id="steps-title">枠の中の作業手順</h2>
<p class="step">1. 対象と目的を確認します。</p>
<p class="step">2. 小さな練習用データを準備します。</p>
<p class="step">3. 変更前の状態を記録します。</p>
<p class="step">4. 一つの指定だけを変えます。</p>
<p class="step">5. 位置と重なりを確認します。</p>
<p class="step">6. 狭い画面でも読めるか調べます。</p>
</div>
<p>枠の内側とページ全体を、それぞれ別にスクロールして比較してください。</p>
<p>実際の閲覧環境では文字を拡大し、固定リンクが内容を隠さないかも確認します。</p>
<a class="to-top" href="#top">ページの先頭へ</a>
</main>
</body>
</html>
保存したファイルを手元のブラウザーで開き、まずカード右上の「練習用」と、その下の見出しや文章を見ます。バッジがカードの基準で置かれ、本文と重ならないことを期待する例です。カード幅や文章量を変えたら、同じ指定のままで読めるかを確かめてください。
親のrelativeは、位置を動かさなくても意味がある
.cardにはposition: relativeを指定し、topなどは付けていません。カード自体を動かすのではなく、内側の.badgeが位置を決める基準にするためです。子の.badgeにはposition: absolute、top: 14px、right: 14pxを指定しています。
この構成でrelativeを外した場合、バッジは別の祖先や初期の包含ブロックを基準にする可能性があります。カード内にあるようにHTMLを書いていても、必ずそのカードが配置基準になるわけではありません。見た目が急に離れた場所へ移ったときは、数値を大きく調整する前に基準を調べます。
配置基準となる領域は、CSSで包含ブロックと呼ばれます。条件によって、要素の余白領域や祖先のプロパティが関係します。詳しくはMDNの包含ブロックの解説を確認してください。初心者の段階では、まず自分が基準にしたい箱と、その箱へ付けた指定を明確にします。
absoluteのバッジ用の空間は、別に確保する
バッジは通常の流れから外れているため、本文はバッジの高さを自動で避けません。今回のカードは上側のpaddingを72pxにし、短いバッジと本文が重ならないための空間を用意しています。ただし、この値は練習用の短い文に合わせたものです。文字を拡大したり、バッジを長い文章へ変えたりすれば、足りなくなる可能性があります。
「おすすめ」「新着」のような短い補助ラベルならabsoluteが候補になりますが、重要な注意文や長い説明を浮かせると、内容量によって重なりやすくなります。その場合は、通常の流れに置く設計も検討してください。位置を固定することより、情報が読めることを優先します。
topやrightの値を変えて見た目を合わせるときは、親のpaddingやborderも見ます。たとえばバッジが枠線へ近すぎる場合、子の位置だけでなく、カード内の余白設計を見直した方がよいことがあります。一つの数値だけを大きくして、別の幅で無理が出ないかを確認しましょう。
relativeの移動は、余白を増やす操作ではない
.offsetにはtop: 4pxとleft: 8pxを指定しています。これは元の場所から見た目を少し下と右へずらす例です。元のレイアウト上の場所が残るため、前後の文章との関係を見てください。marginやpaddingで実際の間隔を変える操作とは異なります。
追加練習では、まずtopを0へ戻し、次にleftを0へ戻すなど、一つずつ変えます。見た目が動いた部分と、周囲の文章の位置が変わらない部分を比べると、relativeの性質を理解しやすくなります。大きなずれを使ってページの配置全体を作る必要はありません。
※表は横にスクロールできます。
| 変更する箇所 | 期待する変化 | 確認すること |
|---|---|---|
| バッジのrightを大きくする | 基準の右端から離れる | カードを基準にしているか |
| カードのrelativeを外す | 別の基準に変わる可能性 | 近い祖先の指定を調べる |
| カードの上paddingを減らす | 本文とバッジが近付く | 重なりや文字の隠れ |
| offsetのtopを戻す | 見た目の縦ずれが減る | 元の配置上の空間との違い |
| バッジを長文にする | 大きさと折り返しが変わる | 固定余白で収まるか |
fixedとstickyを、ページと枠のスクロールで比較する

fixedは、本文の空間を自動では空けない
広い幅では、先頭へ戻るリンクをposition: fixedで右下に置いています。rightとbottomの指定が、一般的なビューポート基準で位置を決める例です。本文の最後には余白を用意していますが、それだけですべての拡大率や画面高さで安全になるとは限りません。
固定された要素は、表示中の本文や操作ボタンに重なる可能性があります。サイトで固定の案内、チャット、同意バナーなどが複数あると、画面の使える領域はさらに狭くなります。先頭リンク一つでも、下にある文字を隠していないか、キーボードのフォーカスが見えなくならないかを確認します。
今回の例は480px以下でposition: staticへ戻します。狭い幅では本文の後へ普通に並べる設計です。この切り替えも、すべての機種を正確に分類するものではありません。480pxを超える狭い高さの画面や文字拡大でも、必要なら固定をやめる判断ができます。
fixedの基準が変わる祖先の指定に注意する
fixedは常にブラウザー画面そのものへ固定される、と言い切るのは正確ではありません。祖先にtransformなど、包含ブロックを作る指定があると、その祖先を基準にする場合があります。見た目の動きを付けるための指定が、子の位置にも影響することがあります。
固定リンクがページと一緒に動くように見えるときは、親や祖先のtransform、filterなど関連する指定を調べます。position: relativeがあるかだけを探しても、原因が見つからない場合があります。MDNの包含ブロックの資料で、どの指定が基準を変えるかを確認してください。
問題を直すために、祖先の装飾を全部削除する必要はありません。固定要素を置く場所を見直す、通常の流れへ戻す、別のレイアウトで目的を満たすなど、影響の小さい方法を検討します。既存サイトでは、祖先の指定がほかの部品にも使われている可能性があるため、変更範囲を確認します。
stickyの見出しは、280pxの枠の中で確認する
.scroll-boxには高さ280pxとoverflow: autoを設定し、中に六つの手順を入れています。手順一つの最低の高さは80pxなので、六つだけで480px分あり、見出しを含めると枠の高さより長くなる設計です。このように、枠の内側にスクロールが生じる条件を用意しています。
見出し.scroll-titleはposition: sticky、top: 0です。枠の内側をスクロールしたとき、見出しが枠の上側に残り、下の手順が動くことを期待します。ページ全体をスクロールすると、この枠自体はページの一部として動きます。画面全体に固定した先頭リンクとの違いを比べてください。
ページ全体に縦スクロールがない場合は、ブラウザーの高さを小さくする、文字を拡大するなど、内容が画面を超える条件で比較します。例のために意味のない長文を大量に足す必要はありません。どちらをスクロールしているか、マウスやキーボードの対象が枠内かページかを確認します。
stickyが効かないときは、スクロールする祖先を見る
stickyで上へ残したいのに変化がない場合は、まずtopなどの位置の基準が指定されているかを見ます。次に、要素が動く余地のある高さか、親の中に十分な内容があるかを確認します。要素と親の高さがほぼ同じなら、期待した動きが見えにくいことがあります。
祖先のoverflowも確認します。overflow: autoやscrollだけでなく、hiddenなどがスクロールの仕組みを持つ祖先になることで、想定と違う基準になる場合があります。見えているページのスクロールとは別の祖先が関係するため、「一番近くで実際に動いている場所だけが基準」と考えないようにします。
具体的なoverflowの動作は、MDNのoverflow資料を参照してください。単に角を切りたい、はみ出しを隠したいという理由で付けた指定が、stickyの動きへ影響する場合があります。問題の要素から外側へ順にたどると、見落としを減らせます。
z-indexと重なりのまとまりを、数字だけで判断しない

z-indexは、どのまとまりの中で比べるかが重要
要素がほかの要素の下に隠れると、z-indexを大きな数字にしたくなることがあります。しかし、数字はページ内のすべての要素と一列に比較されるわけではありません。重なりの文脈、つまりスタッキングコンテキストというまとまりがあり、その内側と外側で比較の段階が変わります。
positionがrelativeやabsoluteでz-indexがauto以外の場合、fixedやsticky、transform、opacityなど、さまざまな条件で新しいまとまりが作られます。詳細はMDNのスタッキングコンテキストで確認できます。何がまとまりを作るかを調べることが、単に数値を上げるより重要になる場面があります。
今回の見出しにはz-index: 1、先頭リンクにはz-index: 2を指定しています。この数字は、今回の単純な構造の中で役割を分けるための例です。既存サイトへ移した場合に、必ずすべての要素より前に出る保証はありません。サイト側のヘッダー、モーダル、ほかのスタッキングコンテキストを確認する必要があります。
親のまとまりを越えられない例を考える
たとえば同じ親の下にAとBという二つの箱があり、どちらも重なりのまとまりを作っているとします。Aのz-indexが1、Bが2なら、Aの内側のラベルだけを999にしても、通常はAのまとまり全体を越えてBより前へ出せません。ラベルの999は、Aの内側での比較として考える必要があります。
※表は横にスクロールできます。
| 例の対象 | z-indexの例 | 比べる段階 | 読み取り方 |
|---|---|---|---|
| 親の箱A | 1 | AとBの外側の関係 | Bより後ろのまとまり |
| Aの中のラベル | 999 | Aの内側 | Aの内部で前へ出す指定 |
| 親の箱B | 2 | AとBの外側の関係 | Aより前のまとまり |
| Bの中の文字 | auto | Bの内側 | Bのまとまりの中で配置 |
この表は仕組みを説明する仮の構造で、実際のページへ999を追加する推奨ではありません。ラベルをどうしても前へ出したいなら、親のまとまりの順序、要素を置く場所、表示の設計を見直します。ほかの要素が押せなくなるほど前へ出すのではなく、必要な範囲の重なりにとどめます。
背景と透明部分も、重なりの読みやすさに影響する
sticky見出しに背景色がないと、後ろの本文が透けて読みにくくなる場合があります。今回の見出しは背景を付け、動く手順と区別しやすくしています。前に出す順番が正しくても、文字が透けたり境界が分からなかったりすれば、読みやすさは十分ではありません。
反対に、大きな透明要素が前面を覆うと、見た目では何もない場所に見えても、下のリンクを押せないことがあります。重なりを調べるときは、見えている色だけでなく、要素の実際の幅と高さを確認します。不要な大きいabsolute領域や、画面を覆う固定要素が残っていないかを見ます。
z-indexの値や適用対象の基本は、MDNのz-index資料で確認できます。数値を増やした後は、目的の部品が見えることだけでなく、ほかの操作を邪魔していないことまで点検してください。
位置の見た目と、読む順番・操作順番を分ける
absoluteやfixedで見た目の位置を変えても、HTMLの意味や読み順がその位置へ自動で移るわけではありません。キーボードで移動したときの順序や、読み上げでたどる順序が見た目と離れると、使いにくくなる場合があります。重要な説明は、できるだけ自然な文書順序の中へ置きます。
今回のバッジは短い補助情報、先頭リンクは本文の最後にある補助的な移動です。主要な説明文を画面の別の位置へ飛ばす例にはしていません。実務で操作ボタンを浮かせる場合は、フォーカスが見えるか、ボタンのラベルが分かるか、狭い画面で内容を覆わないかを確認します。
画面いっぱいのメニューやダイアログを作る場合は、positionとz-indexだけで完成するものではありません。フォーカス管理、閉じる操作、背景との関係など別の設計が必要になります。今回の小さな配置練習を、そのまま高度な操作部品の完成例として扱わないようにしましょう。
崩れたときは、基準・余白・スクロール・操作の順に調べる

一度に動かさず、現在の指定を記録する
位置がずれたときは、対象要素のpositionとtop・right・bottom・leftを確認します。次に、基準を作っている親や祖先を調べます。どちらも分からないまま負の値を大きくしたり、z-indexを桁違いに増やしたりすると、別の画面幅で修正が必要になりやすくなります。
変更する前の値を控え、まず一つの指定だけを変えます。カードのrelativeを外したら何が変わるか、stickyのtopを変えたら枠内でどう動くか、というように目的を絞ります。自分の予想を書いてから結果を見ると、偶然合った位置と、仕組みを理解して決めた位置を区別できます。
※表は横にスクロールできます。
| 症状 | 先に調べること | 避けたい対処 |
|---|---|---|
| topを書いても動かない | positionと対象の要素 | 理由なく!importantを増やす |
| バッジがカード外へ飛ぶ | 包含ブロックを作る祖先 | 大きな座標で見た目だけ戻す |
| 本文と部品が重なる | 通常フローと必要な余白 | 文字を隠して整ったように見せる |
| stickyがとどまらない | top・祖先overflow・高さ | fixedへ無条件に置き換える |
| z-indexを上げても前へ出ない | 親のスタッキングコンテキスト | 巨大な数字を足し続ける |
| リンクが押せない | 前面要素の範囲と重なり | 下のリンクだけを作り直す |
狭い幅と文字拡大で、固定した前提を崩してみる
通常の画面で見えることを確認したら、幅を狭くし、文字を大きくして試します。バッジの文字が二行へ折り返したとき、カードの上余白は足りるでしょうか。sticky見出しが高くなったとき、枠の中で本文を読める高さは残るでしょうか。このように、固定値の前提が変わる場面を調べます。
例の480pxの境界では、479、480、481の前後を確認する方法があります。480px以下は先頭リンクがstatic、481pxではfixedのルールが使われるという設計です。条件だけは計算できますが、実際に読めるか、操作できるかはブラウザーで確認する必要があります。
ページ末尾に付けた余白も、すべての場面の解決策ではありません。固定リンクが途中の本文を覆う場合や、画面の高さが極端に小さい場合は、固定表示自体をやめる方がよいことがあります。無理に同じ見た目を保たず、必要な情報へ到達できる方を選びます。
枠内のキーボード操作と、先頭への移動を確認する
スクロール枠にはtabindex=”0″を付け、roleとaria-labelledbyで領域の名前を示しています。手元の環境では、Tabで枠へ移れるか、フォーカスの枠線が見えるか、内側の手順を最後まで確認できるかを試してください。マウスホイールで動いたことだけでは、キーボード操作の確認にはなりません。
先頭リンクはhref=”#top”で、mainのid=”top”へ対応させています。ページ内リンクの参照先が存在するかをコードで確認し、実際に選んだときの移動もブラウザーで確認します。固定表示にするときも、リンクの意味が分かる文字を残し、見た目だけの無名アイコンにしないようにします。
sticky見出しが移動先やフォーカスのある内容を覆う場合もあります。コードにはスクロール位置の余白を考える指定を含めていますが、それだけで全環境の操作が保証されるわけではありません。支援技術やキーボードを含む必要な環境で、対象が隠れないかを確認します。
このコードで確認したことと、未検証のこと
ローカルの構造チェックでは、バッジがrelative指定のカードの中にあること、sticky見出しがスクロール枠の中にあること、六つの手順、ページ内リンクとIDの対応を照合しました。固定リンクを480px以下でstaticへ戻す記述と、掲載コードが練習ファイルと一致することも確認しています。
これはCSSを描画した結果の検証ではありません。カード内の実際の座標、fixedのスクロール挙動、stickyの見え方、フォーカスの移動、実機の拡大表示は未検証です。検証環境でブラウザーを起動できなかったため、構造と指定の確認を、動作確認済みという表現へ広げていません。
実務の引き渡しでは、利用したブラウザーと版、確認した幅、高さ、拡大率、入力方法を記録します。「レスポンシブ対応済み」「position確認済み」という短い言葉だけでは、どこまで見たかが伝わりません。未確認の条件があれば、それも一緒に残すと次の担当者が判断しやすくなります。
小さな変更を、説明できる練習成果にする
練習のまとめとして、カードの幅を変える、バッジの文字を少し長くする、枠の高さを変えるという三つを別々に試してみましょう。それぞれについて、基準は何か、通常の空間はどうなるか、ほかの要素へ何が起きるかを説明できれば、数値を暗記するより応用しやすくなります。
制作過程を作品へまとめるなら、プログラミングのポートフォリオとREADMEの作り方も参考になります。学習支援を比較する場合は、副業向けプログラミングスクールの比較で、費用や支援の範囲を確認する方法もあります。受講や小さな配置例の完成だけで、仕事や収入が保証されるわけではありません。
CSS positionは、見た目の座標を動かす前に、通常の流れと配置基準を理解することが近道です。relativeで基準を作り、absoluteの空間を考え、fixedとstickyのスクロールの違いを確かめ、重なりと操作を点検する。まずは一つのカードと一つの枠で、変化を説明しながら練習していきましょう。