【html&css】positionの使い方とabsolute・fixed・relativeの使い分け

html-and-css-position

Webサイトのデザインを自由に操るためのプロパティがCSSのposition(ポジション)プロパティです。

positionを使えば、要素を重ねたり、画面の端に固定したりとHTMLの順番を無視して配置指定できます。

本記事では、positionプロパティの使い方とpositionに利用する値について解説します。

また、HTML&CSSに関するカテゴリーページから学びたい内容を決めたい人は、以下のHTML&CSSページをご確認ください。

目次

CSSのpositionとは?

positionプロパティは、HTML要素の配置方法(ポジション)を決めるプロパティです。

通常のWebページは、上から下へと順番に要素が積み重なっていきます。(「通常フロー」と呼びます。)

positionを使うことで、要素を通常フローから切り離し、上から〇〇px、左から〇〇pxというように座標を指定して配置できます。

positionについて
  • positionの書き方
  • positionの利用場面

positionの書き方

positionを使って要素を動かすには、「配置の基準(position)」と「動かす距離(top, bottom, left, right)」の2つをセットで記述します。

書き方の基本は以下の通りです。

  • position: 値;
    どんなルールで動かすかを決める
  • top: 値; / bottom: 値; / left: 値; / right: 値;
    基準からどれくらい動かすかを決める

positionに指定できる代表的な値は、以下の4つがあります。

  • static(初期値
    通常の配置です。
    topなどを指定しても動きません。
  • relative(相対位置)
    自身がいるはずだった場所」を基準にして動きます。
  • absolute(絶対位置)
    親要素(または画面全体)を基準にして動きます。
    ※元のスペースは無くなり、他の要素が上に詰まります。
  • fixed(固定位置)
    ブラウザの画面を基準にして動きます。
    スクロールしても固定されています。

positionの利用場面

Web制作の現場では、positionは以下のような特殊な配置をしたい場面で使われます。

  • 画像の上にテキストやアイコンを重ねる時
    例:商品のNEWバッジや50%OFFラベルなど。(absoluteを使用)
  • 画面の右下に「トップへ戻る」ボタンを固定する時
    スクロールしても常に見えている状態。(fixedを使用)
  • スクロールしても上部にヘッダーメニューを追従させる時
    いわゆる追従ヘッダー(fixedstickyを使用)
  • ハンバーガーメニュー(三本線のアイコン)やポップアップ画面を作る時
    画面の中央や端に浮かせる配置する。(absolutefixedを使用)
普通の箱 1
動く赤い箱
普通の箱 2(※動きに注目)
HTMLコード表示
<div class="pos-demo-wrapper">
  <input type="radio" name="pos-type" id="pos-static" class="pos-radio" checked>
  <input type="radio" name="pos-type" id="pos-relative" class="pos-radio">
  <input type="radio" name="pos-type" id="pos-absolute" class="pos-radio">

  <div class="pos-controls">
    <label for="pos-static" class="pos-btn">① static (初期値)</label>
    <label for="pos-relative" class="pos-btn">② relative (相対位置)</label>
    <label for="pos-absolute" class="pos-btn">③ absolute (絶対位置)</label>
  </div>

  <div class="pos-container">
    <div class="pos-box box-blue">普通の箱 1</div>
    
    <div class="pos-box box-red target-box">動く赤い箱</div>
    
    <div class="pos-box box-blue">普通の箱 2(※動きに注目)</div>
  </div>

</div>
CSSコード表示
/* 全体のラッパー */
.pos-demo-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
/* ラジオボタンは非表示 */
.pos-radio {
  display: none;
}
/* ボタンエリアのレイアウト */
.pos-controls {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}
/* ボタンのデザイン */
.pos-btn {
  background-color: #e9ecef;
  padding: 8px 16px;
  border-radius: 4px;
  cursor: pointer;
  font-weight: bold;
  color: #495057;
  border: 2px solid transparent;
  transition: 0.2s;
}
/* 選択されたボタンの色を変える */
#pos-static:checked ~ .pos-controls [for="pos-static"],
#pos-relative:checked ~ .pos-controls [for="pos-relative"],
#pos-absolute:checked ~ .pos-controls [for="pos-absolute"] {
  background-color: #0d6efd;
  color: #ffffff;
}
/* =========================================
  親要素(絶対配置の基準にするため relative を設定)
  ========================================= */
.pos-container {
  background-color: #ffffff;
  padding: 20px;
  border: 2px dashed #333333;
  border-radius: 4px;
  /* ★重要★ 中の absolute な要素の基準位置になる! */
  position: relative; 
  /* 高さが潰れないように最低限の高さを確保 */
  min-height: 250px; 
}
/* 箱の共通スタイル */
.pos-box {
  padding: 15px;
  margin-bottom: 10px;
  color: #ffffff;
  font-weight: bold;
  text-align: center;
  border-radius: 4px;
  transition: all 0.4s ease;
}
.pos-box:last-child {
  margin-bottom: 0;
}
.box-blue {
  background-color: #0d6efd;
  opacity: 0.8;
}
.box-red {
  background-color: #dc3545;
  /* 重なりがわかるように半透明にしておく */
  opacity: 0.9; 
  /* アニメーション用 */
  z-index: 10; 
}
/* =========================================
  ① static(初期値)
  topなどを指定しても無視され、順番通りに並ぶ
  ========================================= */
#pos-static:checked ~ .pos-container .target-box {
  position: static;
  top: 30px;  /* ← 無効になります */
  left: 30px; /* ← 無効になります */
}
/* =========================================
  ② relative(相対位置)
  「本来いるはずの場所」から右下に30pxズレる。
  ★元のスペースは残ったままなので、「普通の箱2」は上に詰まらない!
  ========================================= */
#pos-relative:checked ~ .pos-container .target-box {
  position: relative;
  top: 30px;
  left: 30px;
}
/* =========================================
  ③ absolute(絶対位置)
  親要素(黒い点線)の右上(top:0, right:0)にワープする!
  ★元のスペースが消滅するため、「普通の箱2」が上にスッと詰まる!
  ========================================= */
#pos-absolute:checked ~ .pos-container .target-box {
  position: absolute;
  top: 0;
  right: 0;
  /* margin-bottomが不要になるので消す */
  margin-bottom: 0; 
  /* 幅が100%になってしまうのを防ぐ */
  width: 150px; 
}

positionで使うtop・bottom・left・right

position: relative;position: absolute;で要素を動かす準備ができたら、要素を「どの方向に、どれくらい動かすか」を指定する必要があります。

そのためのプロパティがtop(上)、bottom(下)、left(左)、right(右)の4つです。

positionでtop・bottom・left・right
  • 上下左右の基準となる端から距離を指定する
  • %(パーセント)を使って画面サイズに合わせる
  • マイナスの値を使って要素を外側に配置する

上下左右の基準となる端から距離を指定する

4つのプロパティの考え方は、「基準となる箱の端っこからどれだけ内側に離れるか」を指定します。

  • top: 20px;= 箱の「上端」から下へ20px離れる
  • bottom: 0;= 箱の「下端」から0px(下端にピッタリくっつく)
  • left: 50px;= 箱の「左端」から右へ50px離れる
  • right: 10px;= 箱の「右端」から左へ10px離れる

これらを組み合わせて、四隅に要素を配置できます。

🎯 ターゲット
HTMLコード表示
<div class="tblr-demo1-wrap">
  <input type="radio" name="tblr-pos" id="pos-tl" class="tblr-radio" checked>
  <input type="radio" name="tblr-pos" id="pos-tr" class="tblr-radio">
  <input type="radio" name="tblr-pos" id="pos-bl" class="tblr-radio">
  <input type="radio" name="tblr-pos" id="pos-br" class="tblr-radio">

  <div class="tblr-controls">
    <label for="pos-tl" class="tblr-btn">左上 (top:0, left:0)</label>
    <label for="pos-tr" class="tblr-btn">右上 (top:0, right:0)</label>
    <label for="pos-bl" class="tblr-btn">左下 (bottom:0, left:0)</label>
    <label for="pos-br" class="tblr-btn">右下 (bottom:0, right:0)</label>
  </div>

  <div class="tblr-container">
    <div class="tblr-target">🎯 ターゲット</div>
  </div>

</div>
CSSコード表示
.tblr-demo1-wrap {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
.tblr-radio {
  display: none;
}
.tblr-controls {
  display: flex;
  justify-content: center;
  font-size: 14px;
  gap: 10px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}
.tblr-btn {
  background-color: #e9ecef;
  padding: 8px 16px;
  border-radius: 4px;
  cursor: pointer;
  font-weight: bold;
  color: #495057;
  transition: 0.2s;
}
#pos-tl:checked ~ .tblr-controls [for="pos-tl"],
#pos-tr:checked ~ .tblr-controls [for="pos-tr"],
#pos-bl:checked ~ .tblr-controls [for="pos-bl"],
#pos-br:checked ~ .tblr-controls [for="pos-br"] {
  background-color: #0d6efd;
  color: white;
}
/* 基準となる親要素 */
.tblr-container {
  background-color: #ffffff;
  border: 2px dashed #333333;
  height: 200px;
  position: relative; /* ★ターゲットの基準位置になる! */
}
/* 動くターゲット要素 */
.tblr-target {
  background-color: #dc3545;
  color: #ffffff;
  padding: 10px 20px;
  font-weight: bold;
  border-radius: 4px;
  position: absolute; /* 親要素を基準に絶対配置! */
  transition: all 0.4s ease; /* アニメーションで滑らかに移動 */
}
/* =========================================
  ラジオボタンで上下左右の位置を切り替える
  ========================================= */
#pos-tl:checked ~ .tblr-container .tblr-target {
  top: 0;
  left: 0;
}
#pos-tr:checked ~ .tblr-container .tblr-target {
  top: 0;
  right: 0;
}
#pos-bl:checked ~ .tblr-container .tblr-target {
  bottom: 0;
  left: 0;
}
#pos-br:checked ~ .tblr-container .tblr-target {
  bottom: 0;
  right: 0;
}

%(パーセント)を使って画面サイズに合わせる

動かす距離の単位には、px(ピクセル)のほかに親要素の幅や高さに対する割合である%(パーセント)も使われます。

例えばleft: 50%;と指定すると、親要素の横幅の半分の位置まで移動します。

スマホやPCなど、画面サイズに合わせて配置を変えたいレスポンシブデザインにおいて重要な指定方法です。

10%
50%
90%
🚗
HTMLコード表示
<div class="tblr-demo2-wrap">
  <input type="radio" name="pct-pos" id="pct-10" class="pct-radio" checked>
  <input type="radio" name="pct-pos" id="pct-50" class="pct-radio">
  <input type="radio" name="pct-pos" id="pct-90" class="pct-radio">

  <div class="pct-controls">
    <label for="pct-10" class="pct-btn">left: 10%</label>
    <label for="pct-50" class="pct-btn">left: 50%</label>
    <label for="pct-90" class="pct-btn">left: 90%</label>
  </div>

  <div class="pct-container">
    <div class="pct-line" style="left: 10%;">10%</div>
    <div class="pct-line" style="left: 50%;">50%</div>
    <div class="pct-line" style="left: 90%;">90%</div>
    
    <div class="pct-target">🚗</div>
  </div>

</div>
CSSコード表示
.tblr-demo2-wrap {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
.pct-radio {
  display: none;
}
.pct-controls {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-bottom: 20px;
}
.pct-btn {
  background-color: #e9ecef;
  padding: 8px 16px;
  border-radius: 4px;
  cursor: pointer;
  font-weight: bold;
  color: #495057;
  transition: 0.2s;
}
#pct-10:checked ~ .pct-controls [for="pct-10"],
#pct-50:checked ~ .pct-controls [for="pct-50"],
#pct-90:checked ~ .pct-controls [for="pct-90"] {
  background-color: #198754;
  color: white;
}
.pct-container {
  background-color: #ffffff;
  border: 2px dashed #adb5bd;
  height: 120px;
  position: relative;
}
/* 目盛り線のスタイル */
.pct-line {
  position: absolute;
  top: 0;
  bottom: 0;
  border-left: 1px dashed #ccc;
  padding-left: 5px;
  font-size: 12px;
  color: #999;
  z-index: 1;
}
.pct-target {
  font-size: 40px;
  position: absolute;
  top: 30px;
  z-index: 2;
  transition: left 0.5s ease;
  /* 車の中心を線に合わせるための微調整 */
  transform: translateX(-50%); 
}
/* =========================================
  パーセントで左からの距離を変える
  ========================================= */
#pct-10:checked ~ .pct-container .pct-target { left: 10%; }
#pct-50:checked ~ .pct-container .pct-target { left: 50%; }
#pct-90:checked ~ .pct-container .pct-target { left: 90%; }

マイナスの値を使って要素を外側に配置する

topleftの値は、10pxなどのプラス値だけでなく、-10pxのようなマイナス(負)の値を指定できます。

マイナス方向に離れると、親要素の箱の「外側」に飛び出す(はみ出す)ことができます。

例えば、商品画像の角に「NEW!」バッジやリボンをはみ出させて配置するなど、Webデザインでよく使われます。

商品画像

大人気のおしゃれなシャツです。

NEW!
HTMLコード表示
<div class="tblr-demo3-wrap">
  <input type="checkbox" id="badge-toggle" class="badge-checkbox">

  <div style="text-align:center; margin-bottom:20px;">
    <label for="badge-toggle" class="badge-toggle-btn">マイナスの値ではみ出させる!</label>
  </div>

  <div class="badge-demo-area">
    <div class="badge-card">
      <div class="badge-image">商品画像</div>
      <p class="badge-text">大人気のおしゃれなシャツです。</p>
      
      <div class="badge-label">NEW!</div>
    </div>
  </div>

</div>
CSSコード表示
.tblr-demo3-wrap {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
.badge-checkbox {
  display: none;
}
.badge-toggle-btn {
  display: inline-block;
  background-color: #fd7e14;
  color: #ffffff;
  padding: 10px 20px;
  border-radius: 4px;
  cursor: pointer;
  font-weight: bold;
  transition: 0.2s;
}
.badge-toggle-btn:hover {
  background-color: #e8590c;
}
.badge-demo-area {
  padding: 30px;
  display: flex;
  justify-content: center;
}
/* 商品カード(親要素) */
.badge-card {
  background-color: #ffffff;
  border: 1px solid #dee2e6;
  border-radius: 8px;
  width: 200px;
  padding: 15px;
  box-shadow: 0 4px 6px rgba(0,0,0,0.1);
  /* ★バッジの基準位置にする */
  position: relative; 
}
.badge-image {
  background-color: #e9ecef;
  height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #adb5bd;
  font-weight: bold;
  margin-bottom: 10px;
}
.badge-text {
  font-size: 14px;
  color: #333;
  margin: 0;
}
/* NEWバッジ(ターゲット) */
.badge-label {
  background-color: #dc3545;
  color: #ffffff;
  font-weight: bold;
  font-size: 12px;
  padding: 5px 15px;
  border-radius: 20px;
  /* 親要素を基準に絶対配置 */
  position: absolute; 
  /* 初期状態は箱の内側にピッタリ配置 */
  top: 0;
  left: 0;
  transition: all 0.4s ease;
  box-shadow: 0 2px 4px rgba(220,53,69,0.4);
}
/* =========================================
  チェックが入ったら、マイナスの値で外側にはみ出させる!
  ========================================= */
#badge-toggle:checked ~ .badge-demo-area .badge-card .badge-label {
  /* 上と左にマイナスを指定して外に飛び出させる! */
  top: -15px;
  left: -15px;
}
#badge-toggle:checked ~ div .badge-toggle-btn {
  background-color: #198754;
}
#badge-toggle:checked ~ div .badge-toggle-btn::after {
  content: "(バッジの装飾になりました!)";
}

position: static;とは

position: static;は、要素を通常の位置(元の流れのまま)に配置するという指定です。

動かすためのプロパティであるpositionの中で、何もしない・普通にするという役割を持ちます。

position: static;とは
  • すべての要素の初期設定(デフォルト)
  • topやleftを指定しても無視される
  • 実務では位置指定をリセットしたい時

すべての要素の初期設定(デフォルト)

HTMLで<div><p>などのタグを書いた時、それらは上から下へ、左から右へと順番に整列して表示されます。

CSSで何も指定していない状態の時、すべての要素には最初からposition: static;が見えない形で設定されています。

普段見ているWebページの標準的なレイアウトは、すべてstaticのおかげで順番通りに成り立ちます。

topやleftを指定しても無視される

要素がposition: static;の状態である時、topbottomleftright、そして重なり順を決めるz-indexを指定しても、すべて無視されます。

top: 50px;って書いたのに全然動かない。」と悩んだ時は、要素にposition: relative;absoluteが指定されておらず、デフォルトのstaticのままになっていることがほとんどです。

実務では位置指定をリセットしたい時

実務においてposition: static;を記述するのは、「PC画面ではabsoluteで自由な位置に飛ばしていた要素を、スマホ画面では順番通りの配置にリセットしたい時」です。

普通の箱 1
【ターゲット】
top: 20px;
right: 20px;
普通の箱 2
普通の箱 3
HTMLコード表示
<div class="static-demo-wrap">
  <input type="radio" name="ps-type" id="ps-absolute" class="ps-radio" checked>
  <input type="radio" name="ps-type" id="ps-static" class="ps-radio">

  <div class="ps-controls">
    <label for="ps-absolute" class="ps-btn">PC画面(absoluteで右上に配置)</label>
    <label for="ps-static" class="ps-btn">スマホ画面(staticでリセットする!)</label>
  </div>

  <div class="ps-container">
    <div class="ps-box box-blue">普通の箱 1</div>
    
    <div class="ps-box target-box">
      【ターゲット】<br>
      top: 20px;<br>
      right: 20px;
    </div>
    
    <div class="ps-box box-blue">普通の箱 2</div>
    <div class="ps-box box-blue">普通の箱 3</div>
  </div>

</div>
CSSコード表示
/* 全体のラッパー */
.static-demo-wrap {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
/* ラジオボタンは非表示 */
.ps-radio {
  display: none;
}
/* ボタンエリアのレイアウト */
.ps-controls {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}
/* ボタンのデザイン */
.ps-btn {
  background-color: #e9ecef;
  padding: 10px 20px;
  border-radius: 4px;
  cursor: pointer;
  font-weight: bold;
  color: #495057;
  border: 2px solid transparent;
  transition: 0.2s;
}
/* 選択されたボタンの色を変える */
#ps-absolute:checked ~ .ps-controls [for="ps-absolute"],
#ps-static:checked ~ .ps-controls [for="ps-static"] {
  background-color: #0d6efd;
  color: #ffffff;
}
/* 基準となる親要素 */
.ps-container {
  background-color: #ffffff;
  padding: 20px;
  border: 2px dashed #333333;
  border-radius: 4px;
  /* absoluteの基準位置にする */
  position: relative; 
  min-height: 250px;
}
/* 箱の共通スタイル */
.ps-box {
  padding: 15px;
  margin-bottom: 10px;
  color: #ffffff;
  font-weight: bold;
  text-align: center;
  border-radius: 4px;
  transition: all 0.5s ease;
}
.ps-box:last-child {
  margin-bottom: 0;
}
.box-blue {
  background-color: #6c757d;
}
/* =========================================
  ターゲットの箱(基本設定)
  ※あらかじめ top と right を設定しておきます。
  ========================================= */
.target-box {
  background-color: #dc3545;
  /* ここで距離を指定しておく */
  top: 20px;
  right: 20px;
  z-index: 10;
}
/* =========================================
  ① absolute が効いている状態(PC画面の想定)
  topとrightの指示通りに右上にワープする!
  ========================================= */
#ps-absolute:checked ~ .ps-container .target-box {
  position: absolute;
  width: 150px;
  margin-bottom: 0;
}
/* =========================================
  ② static でリセットした状態(スマホ画面の想定)
  topとrightの指示が「無視」され、元の列の中にスッと戻る!
  ========================================= */
#ps-static:checked ~ .ps-container .target-box {
  position: static;
  /* 幅などを元の状態に戻す */
  width: auto;
  margin-bottom: 10px;
}

position: relative;とは

position: relative;は、要素を本来表示するはずだった位置から、どれくらいズラすかを指定するプロパティです。

position: relative;とは
  • 自身が元いた配置を基準に動く
  • 動いた後も元のスペースは残る
  • absoluteの基準となる親枠として使う

自身が元いた配置を基準に動く

relativeを指定した要素にtopleftといった距離の指定を追加すると、要素は自身が元いた場所をスタート地点にして移動します。

top: 20px;left: 20px;と指定すると、元いた場所から「下へ20px、右へ20px」だけズレて表示されます。

動いた後も元のスペースは残る

要素がズレて移動しても、要素が占めていたスペースは空洞になって残ります。

そのため、前後の要素は、その要素がまだ元の場所にいるかのように振る舞い、上に詰められたりしません。

absoluteの基準となる親枠として使う

実務においてrelativeを要素をズラすために使うことは多くありません。

多用する場面は、position: absolute;(絶対配置)で子要素を自由な位置に飛ばす「基準となる親枠(親要素)」にする時です。

absoluteは親要素にrelativeが設定されていないと、ブラウザの画面の端まで飛んでいきます。

「箱の中から出さない。」と指定する結界のような役割をrelativeが担います。

普通の箱 1
動く赤い箱 NEW!
普通の箱 2
HTMLコード表示
<div class="rel-demo-wrap">
  <input type="radio" name="rel-pos" id="rel-static" class="rel-radio" checked>
  <input type="radio" name="rel-pos" id="rel-move" class="rel-radio">
  <input type="radio" name="rel-pos" id="rel-parent" class="rel-radio">

  <div class="rel-controls">
    <label for="rel-static" class="rel-btn">① 初期状態 (static)</label>
    <label for="rel-move" class="rel-btn">② relativeで移動</label>
    <label for="rel-parent" class="rel-btn">③ absoluteの親枠になる</label>
  </div>

  <div class="rel-container">
    <div class="rel-box box-gray">普通の箱 1</div>
    
    <div class="rel-box target-box">
      動く赤い箱
      <span class="rel-badge">NEW!</span>
    </div>
    
    <div class="rel-box box-gray">普通の箱 2</div>
  </div>

</div>
CSSコード表示
.rel-demo-wrap {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
.rel-radio {
  display: none;
}
/* ボタンエリアのレイアウト */
.rel-controls {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}
/* ボタンのデザイン */
.rel-btn {
  background-color: #e9ecef;
  padding: 10px 20px;
  border-radius: 4px;
  cursor: pointer;
  font-weight: bold;
  color: #495057;
  border: 2px solid transparent;
  transition: 0.2s;
}
/* 選択されたボタンの色を変える */
#rel-static:checked ~ .rel-controls [for="rel-static"],
#rel-move:checked ~ .rel-controls [for="rel-move"],
#rel-parent:checked ~ .rel-controls [for="rel-parent"] {
  background-color: #0d6efd;
  color: #ffffff;
}
/* 外枠のコンテナ */
.rel-container {
  background-color: #ffffff;
  padding: 20px;
  border: 2px dashed #adb5bd;
  border-radius: 4px;
}
/* 箱の共通スタイル */
.rel-box {
  padding: 15px;
  margin-bottom: 10px;
  color: #ffffff;
  font-weight: bold;
  text-align: center;
  border-radius: 4px;
  transition: all 0.4s ease;
}
.rel-box:last-child {
  margin-bottom: 0;
}
.box-gray {
  background-color: #6c757d;
}
/* =========================================
  ターゲットの箱(初期状態)
  ========================================= */
.target-box {
  background-color: #dc3545;
  /* ここにバッジを入れる準備をしておく */
  display: flex;
  align-items: center;
  justify-content: center;
}
/* 子要素のバッジ(初期状態は見えなくしておく) */
.rel-badge {
  background-color: #ffc107;
  color: #000;
  font-size: 12px;
  padding: 4px 8px;
  border-radius: 12px;
  opacity: 0;
  transition: all 0.4s ease;
}
/* =========================================
  ② relativeで移動する状態
  「普通の箱2」は上に詰まらず、赤い箱だけが右下にズレる!
  ========================================= */
#rel-move:checked ~ .rel-container .target-box {
  position: relative;
  top: 20px;
  left: 20px;
  box-shadow: 0 5px 15px rgba(0,0,0,0.2);
  z-index: 10;
}
/* =========================================
  ③ absoluteの親枠になる状態
  赤い箱は元の位置(top:0, left:0)に留まり、
  中のバッジ(absolute)の「基準位置」として働く!
  ========================================= */
#rel-parent:checked ~ .rel-container .target-box {
  /* ★赤い箱をrelativeにして基準枠にする! */
  position: relative; 
  top: 0;
  left: 0;
}
#rel-parent:checked ~ .rel-container .target-box .rel-badge {
  /* ★中のバッジをabsoluteで自由に配置する! */
  position: absolute;
  top: -10px;  /* 赤い箱の上端から少しはみ出させる */
  right: -10px; /* 赤い箱の右端から少しはみ出させる */
  opacity: 1;  /* バッジを表示する */
}

position: absolute;とは

position: absolute;(絶対的)は、要素を配置から切り離し、指定した基準位置から好きな座標へ設置できるプロパティです。

position: absolute;とは
  • 要素から切り離し元のスペースが消える
  • 親要素といった絶対的な基準が必要
  • 画像の上に文字やアイコンを重ねる

要素から切り離し元のスペースが消える

absoluteを指定した要素は、HTMLの流れから外れ「切り離した状態」になります。

relativeの時は動いても「元の空間」が残ってましたが、absoluteの場合は要素が占めていた空間が消えます。

そのため、要素の下にあった別の文章や画像が空いたスペースを埋めようと詰まってくるという現象が起きます。

親要素といった絶対的な基準が必要

absoluteは「絶対にここを基準にして動く」といった親要素を必要とします。

基準になる親要素が設定されていないと、要素はブラウザの画面の端まで飛んでいきます。

これを防ぐために、「箱の中から出さない。」といった役割として親要素にposition: relative;をセットで指定します。

画像の上に文字やアイコンを重ねる

実務では、商品画像の上に「NEW!」というバッジを重ねたり、メインビジュアルの写真の真ん中にキャッチコピーを配置する時にabsoluteが利用されます。

おしゃれなスニーカーの画像
NEW!
SUMMER SALE
50% OFF
HTMLコード表示
<div class="abs-demo-wrapper">
  <input type="radio" name="abs-pos" id="abs-off" class="abs-radio" checked>
  <input type="radio" name="abs-pos" id="abs-on" class="abs-radio">

  <div class="abs-controls">
    <label for="abs-off" class="abs-btn">① absolute なし(縦に並ぶだけ)</label>
    <label for="abs-on" class="abs-btn">② absolute あり(画像の上に重ねる!)</label>
  </div>

  <div class="abs-demo-area">
    <div class="abs-card">
      
      <div class="abs-image">
        おしゃれなスニーカーの画像
      </div>
      
      <div class="abs-badge">NEW!</div>
      
      <div class="abs-text">
        <span class="abs-text-main">SUMMER SALE</span><br>
        50% OFF
      </div>

    </div>
  </div>

</div>
CSSコード表示
.abs-demo-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
.abs-radio {
  display: none;
}
.abs-controls {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-bottom: 30px;
  flex-wrap: wrap;
}
.abs-btn {
  background-color: #e9ecef;
  padding: 10px 20px;
  border-radius: 4px;
  cursor: pointer;
  font-weight: bold;
  color: #495057;
  border: 2px solid transparent;
  transition: 0.2s;
}
#abs-off:checked ~ .abs-controls [for="abs-off"],
#abs-on:checked ~ .abs-controls [for="abs-on"] {
  background-color: #e91e63; /* 今回はピンク系で目立たせる */
  color: #ffffff;
}
.abs-demo-area {
  display: flex;
  justify-content: center;
}
/* =========================================
  親要素(商品カード)
  ========================================= */
.abs-card {
  width: 300px;
  background-color: #ffffff;
  border: 1px solid #dee2e6;
  border-radius: 8px;
  padding: 15px;
  box-shadow: 0 4px 10px rgba(0,0,0,0.1);
  /* ★親要素に relative を指定 */
  position: relative; 
}
/* ベースとなる画像エリア */
.abs-image {
  background-color: #e3f2fd;
  color: #1565c0;
  height: 200px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  border-radius: 4px;
  margin-bottom: 10px;
}
/* =========================================
  重ねたい要素(初期状態は absolute なし)
  ========================================= */
.abs-badge {
  background-color: #dc3545;
  color: #ffffff;
  font-weight: bold;
  padding: 5px 15px;
  border-radius: 20px;
  display: inline-block;
  margin-bottom: 10px;
  transition: all 0.5s ease;
}
.abs-text {
  background-color: rgba(0, 0, 0, 0.7);
  color: #ffffff;
  padding: 10px;
  text-align: center;
  font-weight: bold;
  border-radius: 4px;
  transition: all 0.5s ease;
}
.abs-text-main {
  color: #ffc107;
  font-size: 18px;
}
/* =========================================
  ② absolute あり(ラジオボタンがチェックされた時)
  ========================================= */
/* NEWバッジを「右上の外側」へ配置 */
#abs-on:checked ~ .abs-demo-area .abs-card .abs-badge {
  position: absolute;
  top: -10px;         /* 上からマイナス10px(はみ出す) */
  right: -10px;       /* 右からマイナス10px(はみ出す) */
  margin-bottom: 0;
  box-shadow: 0 4px 6px rgba(220,53,69,0.4);
}
/* セール情報を「画像の中央下部」へ配置 */
#abs-on:checked ~ .abs-demo-area .abs-card .abs-text {
  position: absolute;
  bottom: 30px;       /* カードの下端から30px上の位置 */
  left: 50%;          /* 左から50%(中央)へ移動 */
  transform: translateX(-50%); /* 自身の幅の半分だけ戻して完全な中央揃えにする */
  width: 80%;         /* 幅を少し広げる */
}

position: fixed;とは

position: fixed;は、要素を「ブラウザの画面上の決まった位置に固定し続ける」ことができるプロパティです。

position: fixedとは
  • 画面を基準にして固定する
  • スクロールしても追従する
  • 実務では「追従ヘッダー」や「トップへ戻るボタン」

画面を基準にして固定する

fixedは、親要素が何であろうと関係ありません。

「ブラウザの画面全体(ウィンドウ)」を基準にし、絶対的な位置へ配置します。

top: 0;left: 0;と指定すれば、親要素がどこにあろうと画面の一番左上に固定されます。

absoluteと同じように、要素が宙に浮くため「元々あったスペース」は消滅し、下の要素が上に詰まります。

スクロールしても追従する

absolutestaticで配置された要素はページを下にスクロールすると、他の文章や画像と一緒に画面の上へと流れて消えていきます。

しかしfixedを指定された要素は、スクロールの影響を一切受けません。

ユーザーがページのどこを見ていても、常に画面の同じ位置に固定され続けます。

実務では「追従ヘッダー」や「トップへ戻るボタン」

実務では以下のようなパーツを作る時にfixedが使われます。

  • 追従ヘッダー
    画面の一番上(top: 0;)に固定され、他のページに移動できるメニューバー。
  • トップへ戻るボタン
    画面の右下(bottom: 20px; right: 20px;)に固定され、長い記事を読んだ後一番上に戻れるボタン。
  • お問い合わせボタン / チャットアイコン
    スマホ画面の下部に表示させておき、ユーザーのアクションを促すボタン。
スクロールしてください ↓
コンテンツ 1
コンテンツ 2
コンテンツ 3
コンテンツ 4
コンテンツ 5
一番下まで来ました!

TOP
HTMLコード表示
<div class="fixed-demo-wrapper">
  <input type="radio" name="fix-pos" id="fix-off" class="fix-radio" checked>
  <input type="radio" name="fix-pos" id="fix-on" class="fix-radio">

  <div class="fix-controls">
    <label for="fix-off" class="fix-btn">① absolute(スクロールで消える)</label>
    <label for="fix-on" class="fix-btn">② fixed(画面にずっと固定される!)</label>
  </div>

  <div class="fix-demo-area">
    
    <div class="fix-scroll-area">
      <div class="fix-scroll-content">
        <div class="fix-box bg-gray">スクロールしてください ↓</div>
        <div class="fix-box bg-blue">コンテンツ 1</div>
        <div class="fix-box bg-blue">コンテンツ 2</div>
        <div class="fix-box bg-blue">コンテンツ 3</div>
        <div class="fix-box bg-blue">コンテンツ 4</div>
        <div class="fix-box bg-blue">コンテンツ 5</div>
        <div class="fix-box bg-gray">一番下まで来ました!</div>
      </div>

      <div class="fix-target-btn">
        ⬆<br>TOP
      </div>
    </div>

  </div>
</div>
CSSコード表示
.fixed-demo-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
.fix-radio {
  display: none;
}
.fix-controls {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}
.fix-btn {
  background-color: #e9ecef;
  padding: 10px 20px;
  border-radius: 4px;
  cursor: pointer;
  font-weight: bold;
  color: #495057;
  border: 2px solid transparent;
  transition: 0.2s;
}
#fix-off:checked ~ .fix-controls [for="fix-off"],
#fix-on:checked ~ .fix-controls [for="fix-on"] {
  background-color: #0d6efd;
  color: #ffffff;
}

.fix-demo-area {
  background-color: #ffffff;
  border: 2px dashed #333333;
  height: 300px;
  transform: scale(1);
  overflow: hidden;
}

.fix-scroll-area {
  height: 100%;
  overflow-y: scroll;
  position: relative;
}

.fix-box {
  padding: 40px 20px;
  margin: 20px;
  color: #ffffff;
  font-weight: bold;
  text-align: center;
  border-radius: 4px;
}
.bg-blue { background-color: #6ea8fe; }
.bg-gray { background-color: #adb5bd; }

.fix-target-btn {
  background-color: #dc3545;
  color: #ffffff;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  text-align: center;
  box-shadow: 0 4px 10px rgba(0,0,0,0.3);
  cursor: pointer;
  transition: all 0.4s ease;
  z-index: 100;
}

/* =========================================
   ① absolute の場合
   内箱(fix-scroll-area)の一番下にくっつくため、
   スクロールしないと見えない。
   ========================================= */
#fix-off:checked ~ .fix-demo-area .fix-scroll-area .fix-target-btn {
  position: absolute;
  bottom: 20px;
  right: 20px;
}

/* =========================================
   ② fixed の場合
   外箱(fix-demo-area)の右下に常に固定される!
   内箱をスクロールしてもずっとついてくる!
   ========================================= */
#fix-on:checked ~ .fix-demo-area .fix-scroll-area .fix-target-btn {
  position: fixed;
  bottom: 20px;
  right: 20px;
  background-color: #198754; 
}

まとめ

Webサイトの要素を順番から切り離して「指定座標(top・bottom・left・right)にワープさせる」のがpositionプロパティです。

用途に合わせて、以下の4つの値を使い分けましょう。

本記事のまとめ
  • static(初期値)
    最初から設定されている初期値。
    topleftを指定しても動かない。
    スマホ画面などで「絶対配置をリセットして元の列に戻したい時」に使う。
  • relative(相対位置)
    「自身が本来いるはずだった場所」を基準にして動く。
    動いた後も「元の空間」は空洞として残る。
    実務では、absoluteの「基準となる親枠」として使う。
  • absolute(絶対位置)
    「親要素」を基準にして配置する。
    宙に浮くため、「元の空間」は消滅し、下の要素が上に詰まる。
    実務では、「画像の上に文字やバッジ(NEW!など)を重ねる時」に利用する。
  • fixed(固定位置)
    親要素に関係なく、「ブラウザの画面全体」を基準にして固定される。
    どれだけ下にスクロールしても、同じ位置で追従する。
    実務では、「追従ヘッダー」や「トップへ戻るボタン」を作る時に利用する。

この記事を書いた人

sugiのアバター sugi Site operator

【経歴】玉川大学工学部卒業→新卒SIer企業入社→2年半後に独立→プログラミングスクール運営/受託案件→フリーランスエンジニア&SEOコンサル→Python特化のコンテンツサイトJob Code&UIコピペサイトCode Stock運営中

目次