CSS position(ポジション)種類.static、relative、absolute、fixed、sticky使い方

Webサイトを作っていると「要素を特定の位置に固定したい」「他の要素と重ねて表示したい」「スクロールしても常に画面上部に表示させたい」といった対応が必要になる場面があります。
このとき、HTMLの構造を変えずにCSSだけで要素の配置を細かくコントロールできるのが、position(ポジション)プロパティです。

ここでは、CSSのpositionプロパティの種類(static、relative、absolute、fixed、sticky)と基本的な使い方、実務でよく使うユースケースについて解説します。

position(ポジション)プロパティとは

position(ポジション)プロパティは、HTML要素をどのように配置するかを指定するプロパティです。Webサイト制作における次のような場面で特に活躍します。

場面具体例
要素を重ねて表示したい商品画像に「NEW」「SALE」バッジを重ねる、テキストを画像の上に重ねる
スクロールしても常に表示したい画面上部に固定するナビゲーションバー、右下に固定するページトップボタン
特定の要素を基準に配置したいモーダルウィンドウを画面中央に表示する、ドロップダウンメニューを親要素の直下に表示する
スクロール途中で要素を固定したい長い表のヘッダー行をスクロールしても常に表示する

positionプロパティを使用するときは、positionで要素の配置方法を指定し、top・bottom・left・rightの4つのプロパティで具体的な表示位置を指定します。

要素 {
 position: 値; /* 配置方法を指定(static / relative / absolute / fixed / sticky)*/
 top: px(または%);
 bottom: px(または%);
 left: px(または%);
 right: px(または%);
}

top・bottom・left・rightは「基準となる要素から、上下左右どのくらい移動した場所に要素を配置するか」を指定することができます。例えば「top: 50px; left: 80px」とした場合、基準となる要素の上から50px、左から80px移動した位置に要素が配置されます。


top・bottom・left・rightは同時にすべて指定する必要はなく、topとleft、bottomのみなど、必要なものだけ指定します。
positionプロパティに指定できる主な値は次の5種類です。

種類説明特徴
staticデフォルト値。HTMLに書かれた順番どおりに自動的に配置されます。位置の指定(top・bottom・left・right)は効きません。positionを指定しない場合もこの状態です。
relative通常の位置を基準に、相対的にずらして配置します。移動しても元いた場所のスペースはそのまま残ります。また、relative内に配置したabsoluteの基準位置になります。
absolute直近の「position: static以外」の要素を基準に位置を指定します。他の要素には「そこに存在しない」ものとして扱われます。要素が重なって表示されることがあります。
fixedブラウザに表示されている画面の範囲を基準に配置します。ページをどれだけスクロールしても、画面上の同じ場所に表示され続けます。
sticky最初はrelativeと同じように配置され、スクロールして指定した位置に達すると固定されます。relativeとfixedの中間のような動作をします。

(1) static

staticはpositionのデフォルト値です。HTMLの記述順どおりに上から下へ要素が並ぶ通常の配置になります。top・bottom・left・rightプロパティは効果がありません。
CSSでpositionの指定がない場合、すべての要素はstaticとして扱われます。明示的に記述することはほとんどありませんが、他のCSSで上書きされたpositionをリセットしたいときに使います。

例)style.css

.box {
 position: static; /* デフォルト値のため省略可 */
 width: 100px;
 height: 100px;
 background-color: lightblue;
 margin-bottom: 10px;
}

例)index.html

<html>
<head>
  <title>ページのタイトル</title>
  <style>
   @import url(style.css)
  </style>
</head>
<body>
  <div class=”box”>ボックス1</div>
  <div class=”box”>ボックス2</div>
  <div class=”box”>ボックス3</div>
</body>
</html>

ブラウザでの表示結果

(2) relative

relativeは、要素が本来配置されるべき位置(staticのときの位置)を基準に、top・bottom・left・rightで指定した量だけずらして表示します。

例)style.css

.box {
 width: 100px;
 height: 100px;
 background-color: lightblue;
}

.box-relative {
 position: relative;
 top: 30px; /* 元の位置より30px下にずらす */
 left: 50px; /* 元の位置より50px右にずらす */
 width: 100px;
 height: 100px;
 background-color: salmon;
}

例)index.html

<html>
<head>
  <title>ページのタイトル</title>
  <style>
   @import url(style.css)
  </style>
</head>
<body>
  <div class=”box”>通常の要素</div>
  <div class=”box-relative”>relativeで移動した要素</div>
  <div class=”box”>通常の要素</div>
</body>
</html>

ブラウザでの表示結果

今回の例の場合、通常は2つ目のdiv要素は点線の位置に表示されますが、position: relativeを指定したことで、もとの表示位置から下に30px、右に50pxずれた位置に表示されています。

position: relativeで要素をずらしても、元の位置のスペースはそのまま残るため、3つ目のdiv要素はrelativeの要素が移動する前の位置を基準に並びます。

(3) absolute

absolute を指定した要素は、直近の「position: static以外」の要素(=親要素やその外側にある要素)を基準に位置を指定します。親要素やその外側の要素のどれにもposition(static以外)が指定されていない場合は、ページ全体(body要素)が基準になります。

例)style.css

.parent {
 position: relative; /* 基準となる要素 */
 width: 300px;
 height: 200px;
 background-color: lightgray;
}

.child {
 position: absolute;
 top: 80px; /* 親要素の上端から80px */
 right: 50px; /* 親要素の右端から50px */
 width: 80px;
 height: 80px;
 background-color: steelblue;
}

例)index.html

<html>
<head>
  <title>ページのタイトル</title>
  <style>
   @import url(style.css)
  </style>
</head>
<body>
  <div class=”parent”>
  親要素(position: relative)
    <div class=”child”>子要素(absolute)</div>
  </div>
</body>
</html>

ブラウザでの表示結果

今回の例の場合、position: relativeが指定されている親要素の位置を基準として、下に80px、右から50px内側にずれた位置に表示されています。

absoluteはrelativeとセットで使うのが基本パターンです。基準にしたい要素にrelativeを指定し、その中の要素にabsoluteを指定して位置を決めます。

また、absoluteを指定した要素は他の要素から「そこに存在しない」ものとして扱われるため、他の要素はabsoluteの要素を無視して並びます。例えば、以下のように3つの要素を並べた場合の動きを見てみます。

例)style.css

.item {
 width: 200px;
 height: 60px;
 background-color: lightblue;
 margin-bottom: 5px;
}

.item-absolute {
 position: absolute;
 top: 100px;
 left: 200px;
 width: 200px;
 height: 60px;
 background-color: salmon;
}

例)index.html

<html>
<head>
  <title>ページのタイトル</title>
  <style>
   @import url(style.css)
  </style>
</head>
<body>
  <div class=”item”>要素A</div>
  <div class=”item-absolute”>要素B(absolute)</div>
  <div class=”item”>要素C</div>
</body>
</html>

ブラウザでの表示結果

通常であれば「要素A → 要素B → 要素C」の順に縦に並びますが、要素Bにabsoluteを指定したことで、要素Cは要素Bが存在しないかのように、要素Aのすぐ下に詰めて表示されます。要素Bは指定した位置(上から100px、左から200px)に、他の要素とは独立して表示されます。

(4) fixed

fixedは、ブラウザのビューポート(画面に表示されている領域)を基準に配置します。ページをスクロールしても常に同じ位置に表示され続けます。ページ上部に固定するナビゲーションバーや、右下に固定するページトップボタンなどによく使われます。
ナビゲーションバーの例は以下のとおりです。ページトップボタンは「CSS positionバッジ(ラベル)、モーダルウィンドウ、ページトップボタン、追随ボタンの作り方 画面右下にページトップボタンを固定する」で紹介します。

例)style.css

.fixed-header {
 position: fixed;
 top: 0;    /* 画面の上端に固定 */
 left: 0;
 width: 100%;
 height: 50px;
 background-color: steelblue;
 color: white;
 line-height: 50px;
 padding-left: 20px;
}

例)index.html

<html>
<head>
  <title>ページのタイトル</title>
  <style>
   @import url(style.css)
  </style>
</head>
<body>
  <div class=”fixed-header”>固定ヘッダー</div>
  <div style=”margin-top: 80px;”>
   <p>段落① スクロールしてもヘッダーは画面上部に固定されます。</p>
  </div>
  <div style=”margin-top: 80px;”>
   <p>段落② スクロールしてもヘッダーは画面上部に固定されます。</p>
  </div>
  <div style=”margin-top: 80px;”>
   <p>段落③ スクロールしてもヘッダーは画面上部に固定されます。</p>
  </div>
  <div style=”margin-top: 80px;”>
   <p>段落④ スクロールしてもヘッダーは画面上部に固定されます。</p>
  </div>
  <div style=”margin-top: 80px;”>
   <p>段落⑤ スクロールしてもヘッダーは画面上部に固定されます。</p>
  </div>
</body>
</html>

ブラウザでの表示結果

ブラウザを下にスクロールしても、ヘッダーは上部に固定されたままです。

fixedを指定した要素は、他の要素から「そこに存在しない」ものとして扱われます。そのため、fixedで固定したヘッダーなどの下にコンテンツが隠れてしまうことがあります。コンテンツを隠したくない場合、fixed要素の高さに合わせて、コンテンツ側にmargin-topやpadding-topを設定して対処してください。
例えば、上記の例では各段落に margin-top: 80px を指定することで、固定ヘッダー(高さ50px)に隠れないようにしています。

  <div style=”margin-top: 80px;”>
   <p>段落① スクロールしてもヘッダーは画面上部に固定されます。</p>
  </div>

または、body全体に余白を設定する方法もあります。

body {
 margin-top: 50px; /* 固定ヘッダーの高さ分の余白を確保 */
}

(5) sticky

stickyは、最初はrelativeと同じように通常の位置に表示されますが、ページをスクロールして要素が指定した位置(例:top: 0 なら画面の上端)に達すると、そこで止まって固定されます。長い表の見出し行をスクロール中も常に表示したいときなどに便利です。

例)style.css

.sticky-header {
 position: sticky;
 top: 0;
 background-color: cornsilk;
 border-bottom: 2px solid gray;
 padding: 8px;
}

例)index.html

<html>
<head>
  <title>ページのタイトル</title>
  <style>
   @import url(style.css)
  </style>
</head>
<body>
  <p>コンテンツ1</p>
  <p>コンテンツ2</p>
  <p>コンテンツ3</p>
  <div class=”sticky-header”>この見出しはスクロールで固定されます</div>
  <p>コンテンツ4</p>
  <p>コンテンツ5</p>
  <p>コンテンツ6</p>
  <p>コンテンツ7</p>
  <p>コンテンツ8</p>
  <p>コンテンツ9</p>
  <p>コンテンツ10</p>
  <p>コンテンツ11</p>
  <p>コンテンツ12</p>
  <p>コンテンツ13</p>
  <p>コンテンツ14</p>
  <p>コンテンツ15</p>
  <p>コンテンツ16</p>
  <p>コンテンツ17</p>
  <p>コンテンツ18</p>
  <p>コンテンツ19</p>
  <p>コンテンツ20</p>
  <p>コンテンツ21</p>
  <p>コンテンツ22</p>
  <p>コンテンツ23</p>
  <p>コンテンツ24</p>
  <p>コンテンツ25</p>
  <p>コンテンツ26</p>
  <p>コンテンツ27</p>
  <p>コンテンツ14</p>
  <p>コンテンツ15</p>
  <p>コンテンツ16</p>
  <p>コンテンツ17</p>
  <p>コンテンツ18</p>
  <p>コンテンツ19</p>
  <p>コンテンツ20</p>
  <p>コンテンツ21</p>
  <p>コンテンツ22</p>
  <p>コンテンツ23</p>
  <p>コンテンツ24</p>
  <p>コンテンツ25</p>
  <p>コンテンツ26</p>
  <p>コンテンツ27</p>
  <p>コンテンツ28</p>
  <p>コンテンツ29</p>
  <p>コンテンツ30</p>
  <p>コンテンツ31</p>
  <p>コンテンツ32</p>
  <p>コンテンツ33</p>
  <p>コンテンツ34</p>
  <p>コンテンツ35</p>
  <p>コンテンツ36</p>
  <p>コンテンツ37</p>
</body>
</html>

ブラウザでの表示結果

下にスクロールしていき、見出しがposition: stickyで指定した位置(画面の上端)に達すると、そこで位置が固定されます。さらにスクロールしても見出しは表示されたままの状態です。

※画面の下端までスクロールした状態

position(ポジション)プロパティがうまく動かないときの原因と対処法

positionを指定しても意図通りに動かない場合、次のような原因が考えられます。

(1) absoluteが意図した位置に表示されない
absoluteは直近の「position: static以外」の要素(=親要素やその外側にある要素)を基準にします。基準にしたい親要素にposition: relativeを指定し忘れると、さらに外側の要素やページ全体が基準になってしまい、意図しない位置に表示されてしまいます。

(2) stickyが効かない
topなどの位置プロパティが指定されていないとstickyとして動作しないため、必ずtop・bottom・left・rightのいずれかを指定してください。

>>CSS positionバッジ(ラベル)、モーダルウィンドウ、ページトップボタン、追随ボタンの作り方