1. ホーム
  2. CSS

【CSS】position の使い方|static・relative・absolute・fixed・sticky で要素を自由に配置する

Share

要素を好きな場所に動かしたい、見出しの右上にバッジを重ねたい、スクロールしてもヘッダーを画面の上に貼り付けておきたい——こうした「配置」を担当するのが CSS の position プロパティです。この記事では position がとる5つの値(staticrelativeabsolutefixedsticky)の違いと、位置を決める toprightbottomleft の使い方、重なり順を決める z-index との関係、そして「absolute が思った場所に行かない」原因までを、初心者の方にも分かるように順番に解説します。

position は「要素の配置方法」を切り替えるプロパティ

通常、HTML の要素はソースに書いた順番どおりに、上から下へ(インライン要素は左から右へ)自動的に並びます。この自然な流れを「通常フロー」と呼びます。position は、要素をこの通常フローに従わせるのか、それとも流れから切り離して座標で配置するのかを切り替えるプロパティです。

positionstatic 以外の値を指定すると、その要素は toprightbottomleft という4つのプロパティで位置をずらせるようになります。どこを基準にずれるかは値によって変わるので、まずは各値の意味を一つずつ見ていきましょう。

配置の基準通常フローでの扱い
static通常フローのまま(初期値)。top 等は効かない場所を占める
relative本来あった位置を基準にずれる元の場所を占めたまま
absolute位置指定された一番近い祖先を基準に配置流れから外れる(場所を空ける)
fixedビューポート(画面)を基準に固定流れから外れる
stickyスクロールに応じて relative と fixed が切り替わる場所を占めたまま

static は何も指定しないときの状態

staticposition の初期値で、要素を通常フローのまま配置します。この状態では topleft を書いても一切効きません。「position を指定していない要素はすべて static である」と覚えておけば十分です。何かを動かしたいときは、まずこの static から別の値に変えることがスタートになります。

relative は元の位置からの相対移動

relative は、要素が本来あった位置を基準にtopleft などで指定した分だけずらします。重要なのは、ずらしても元の場所はそのまま空けて確保されることです。つまり周りの要素は動かず、見た目だけが移動します。

style.css
.box {
  position: relative; /* 本来の位置を基準にする */
  top: 20px;          /* 上から 20px 下へ移動 */
  left: 30px;         /* 左から 30px 右へ移動 */
}

/* 元の場所はそのまま空き、周りの要素は動かない */

top: 20px は「上端から下方向へ 20px」、left: 30px は「左端から右方向へ 30px」ずらすという意味です。relative 単体で使うことは実はそれほど多くなく、次に説明する absolute の基準を作るために添えるのが、現場ではもっとも多い使い方です。

absolute は「位置指定された祖先」を基準に配置する

absolute を指定した要素は通常フローから完全に切り離され、座標を使って自由に配置できます。このとき位置の基準になるのは、positionstatic 以外に指定された一番近い祖先要素です。該当する祖先が一つもない場合は、ページ全体(正確には初期包含ブロック)が基準になります。

そこで定番となるのが、基準にしたい親に position: relative を付けておき、その中の子に position: absolute を指定するパターンです。次のデモは、親要素の右上にバッジを重ねる例です。CSS タブで .parentposition: relativestatic に変えると、バッジが画面基準に飛んでいくのが確認できます。

<div class="parent">
  <span class="parent__label">position: relative の親要素</span>
  <div class="badge">absolute で右上に配置</div>
</div>
.parent {
  position: relative; /* 子要素の absolute の基準になる */
  height: 160px;
  padding: 12px;
  border: 2px solid #007bff;
  background: #f0f8ff;
}

.badge {
  position: absolute; /* 親(.parent)を基準に配置される */
  top: 12px;
  right: 12px;
  padding: 6px 12px;
  border-radius: 4px;
  background: #007bff;
  color: #fff;
  font-size: 14px;
}
Preview

topright を組み合わせれば右上、bottomleft なら左下、というように四隅へ自在に配置できます。商品画像の「SALE」ラベルや、アイコンの右上に付く通知バッジなどは、ほぼこの仕組みで作られています。

fixed は画面に貼り付けて固定する

fixedabsolute と似ていますが、基準が常にビューポート(ブラウザの表示領域)になる点が違います。ページをスクロールしても要素はその場に留まり続けるため、画面の隅に置く「トップへ戻る」ボタンや、追従するナビゲーションバー、常時表示したいバナーなどに使われます。

style.css
.back-to-top {
  position: fixed; /* 画面を基準に固定 */
  right: 24px;     /* 画面の右端から 24px */
  bottom: 24px;    /* 画面の下端から 24px */
  z-index: 100;    /* 他の要素より前面に */
}

このように書くと、スクロール量に関係なく常に画面右下に固定されたボタンになります。なお、祖先要素に transformfilter が指定されていると、fixed の基準が画面ではなくその祖先に変わってしまうことがあります。固定したいのに動いてしまうときは、この点を疑ってみてください。

sticky はスクロールに追従して貼り付く

sticky は、普段は relative のように通常フロー内に置かれ、スクロールして指定した位置(しきい値)に達すると、そこから先は fixed のように貼り付く、という2つの性質を切り替える値です。表の見出し行を上部に貼り付けたり、セクションごとの見出しを画面の上に残したりする用途でよく使われます。

style.css
.heading {
  position: sticky; /* 通常は流れの中、スクロールで貼り付く */
  top: 0;           /* 画面上端まで来たら、そこで固定される */
  background: #fff;
}

sticky では top などのしきい値の指定が必須です。これを書き忘れると、貼り付くタイミングが決まらず通常の relative と同じ見た目になってしまいます。

z-index で要素の重なり順を決める

position で要素を重ねると、どちらが前面に来るかが問題になります。これを制御するのが z-index で、値が大きいほど前面(手前)に表示されます。ポイントは、z-indexpositionstatic 以外の要素にしか効かないことです。重ねたはずの要素が前面に出ないときは、その要素に position が指定されているかをまず確認してください。

style.css
.modal {
  position: fixed;
  z-index: 1000; /* 値が大きいほど前面に表示される */
}

.overlay {
  position: fixed;
  z-index: 999;  /* modal より後ろ(背面)になる */
}

absolute が思った場所に配置されない原因

absolute を使ったときに「画面の左上や予想外の場所に飛んでしまう」というつまずきは非常によくあります。原因はほぼ決まっているので、順番に確認していきましょう。

基準にしたい親に position を指定し忘れている

もっとも多い原因がこれです。absolute は「position が指定された一番近い祖先」を基準にしますが、その祖先が一つもないと、基準はページ全体になります。その結果、親の右上に置いたつもりの要素がページの右上まで飛んでいきます。基準にしたい親に position: relative を付けるだけで解決します。

top や left を一つも指定していない

position: absolute だけを指定して topleft を書かないと、要素はおおよそ「本来表示されるはずだった位置」に留まります。動いていないように見えて実は通常フローからは外れているため、後続の要素がその下に詰めて表示され、レイアウトが崩れたように見えます。配置したい位置を topleft 等で明示しましょう。

親要素の高さがなくなって崩れる

absolute の要素は通常フローから外れるため、面積を持ちません。子要素がすべて absolute になると、親要素の高さが 0 になってつぶれてしまうことがあります。親に明示的な height を与えるか、フロー内に残す要素を1つ用意するなどで対処します。

まとめ

position は要素の配置方法を切り替える、レイアウトの土台となるプロパティです。要点を振り返ります。

  • static は初期値で通常フローのまま。top 等は効かない
  • relative は本来の位置を基準にずれ、元の場所は確保したまま
  • absolute は位置指定された一番近い祖先を基準に配置され、フローから外れる
  • fixed は画面(ビューポート)を基準に固定し、スクロールしても動かない
  • sticky はスクロールに応じて relativefixed が切り替わる。しきい値の指定が必須
  • 重なり順は z-index で制御し、position 指定済みの要素にのみ効く
  • absolute が飛ぶときは、基準にしたい親の position: relative を疑う

「親に relative、子に absolute」という組み合わせは、バッジ・ラベル・吹き出しなど数えきれないほどの場面で登場します。まずはこのパターンを手に馴染ませると、配置の応用が一気に広がります。

参考ページ