1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Position:fixed :stickyの使い分け

Last updated at Posted at 2025-06-29

初めに

先日、モーダルを実装していてバツボタンを上部に固定化する改修を行いました。
固定化するなら安易にpostion:fixed使えばいけるかなーと思っていたのですが、fixedの動きをちゃんと理解しておらずハマったので今後のためにメモ

やりたかったこと

  • モーダルのバツボタンをスクロールしても常に同じ位置に表示したい
  • レスポンシブ対応できるようにリサイズしても位置が変わらないようにしたい

最初にやったこと

実装は以下のイメージでした。

<div className="modal-header">
  <p className="modal-title">{dispName}</p>
  <button className="close-btn" onClick={closeModal}>
    ×
  </button>
</div>;

.modal-header {
  width: 100%;
}

.close-btn {
  position: fixed;
  top: 28%;
  right: 27%;
}

バツボタンをpositionをfixedにして、パーセントで位置調整して固定化する方針で実装してみました。
レスポンシブ対応するために%指定すれば画面サイズ変わってもイイ感じに変わるだろうと思ってました。

レイアウト的にはこんな感じ
image.png

上手くいってるのでは?と思って画面をリサイズすると・・・
image.png

バツボタンがとんでもない方向に。。。

なぜダメだったのか?

公式に書いてありました。

fixed
要素は文書の通常のフローから除外され、ページレイアウト内に要素のための空間が作成されません。要素は最初の包含ブロック(視覚メディア要素の場合はビューポート)から相対的に配置されます。最終的な位置は top、right、bottom、left の値によって決まります。

つまり
position:fixedは、ビューポート(画面全体)を基準に位置が決まるので、
画面の幅が小さくなると、それに伴って位置を指定するtopやrightの値もズレてしまうのが原因でした。

解決策

postion:stickyを使って固定化しました。

sticky
要素は文書の通常のフローに従って配置され、直近のスクロールする祖先および包含ブロック(直近のブロックレベル祖先、表関連要素を含む)に対して top, right, bottom, left の値に基づいて相対配置されます。このオフセットは他の要素の配置には影響を与えません。

つまり
position:stickyは親要素を、基準にして固定化する

.modal-header {
  width: 100%;
}

.close-btn {
  position: sticky;
}

上記にしたらリサイズしてもバツボタンの位置を固定化できました。
image.png

まとめ

要素を固定化するためにfixedをよく使っていたのですが、どこを基準に固定化するかを意識していなかったと感じました。感覚で使わずプロパティを設定したときの動きを明確に説明できるようにしていきたいです。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?