🔥

【CSS】iOS Safariでfixed背景がズレる問題を、背景専用レイヤーで解決

に公開

background-attachment: fixedbody 直指定で使うと、iOS Safari でスクロール時に背景がずれたり表示されないことがあります。
背景専用の固定レイヤー(<div>)を用意し、PC/Android では position: fixed、iOS では absolute にフォールバックする実装で安定表示できました。


背景

ホームページの背景に好きなイメージを敷き、スクロールしても背景だけ固定(いわゆる“固定背景”)にしたい。

既存の設定(問題が出たCSS)

body {
  /* 省略 */
  background: url('/images/bg3.jpg') no-repeat center center fixed;
  background-size: cover;
}

症状(iOSでの不具合)

  • iOS Safari(および iOS版 Chrome/Firefox)で、背景がずれる

よくある症状

  • iOS Safari は、background-attachment: fixed不安定することが多い。
  • body に直接背景を当てると、スクロールやアドレスバーの高さ変動で描画が乱れやすい。
  • 祖先要素に transform / filter / will-change / overflow などが付いていると、スタッキング/コンテキストの影響でさらに不具合が出やすい。
  • 100vh は iOS のアドレスバーに影響されるため、100svh の方が安定。

解決方針

  1. body 背景をやめる:DOMに背景専用のレイヤーを追加して、そこで背景を描画する。
  2. **PC/Androidは固定(position: fixed)**を維持。
  3. iOSは安全策として position: absolute にフォールバック(完全固定ではないが、ズレ・チラつきを防止)。
  4. 画面の縦横比で background-position を微調整。
  5. セクションの高さは 100svh を使い、アドレスバー変動に強くする。

実装

① ページ直下に固定レイヤーを置く

<>
  {/* 背景専用の固定レイヤー */}
  <div className={styles.bgFixedLayer} aria-hidden="true" />

  {/* 省略 */}
  
</>

② CSS(背景レイヤー & 微調整)

.page { position: relative; }  

/* 背景固定レイヤー(PC/Android) */
.bgFixedLayer {
  position: fixed;     /* ← viewport基準で固定(PC/Android) */
  inset: 0;
  z-index: -1;         /* すべてのコンテンツの背面 */
  pointer-events: none;

  background-image: url('/images/bg3.jpg');
  background-repeat: no-repeat;
  background-size: cover;

  /* 例:被写体がやや下にある場合のフォーカス */
  background-position: 50% 72%;

  will-change: transform;  /* Safariの描画を安定させるヒント */
}

/* 画面が縦長(スマホ寄り)ほど、少し下をフォーカス */
@media (max-aspect-ratio: 9/16) { .bgFixedLayer { background-position: 50% 76%; } }
@media (max-aspect-ratio: 2/3)  { .bgFixedLayer { background-position: 50% 80%; } }

/* iOS向けフォールバック:absoluteで安全に */
@supports (-webkit-touch-callout: none) {
  .bgFixedLayer { position: absolute; }
}

/* 各セクションの高さ(iOSのアドレスバー対策にsvh) */
.section {
  min-height: 100svh;
}

なぜこれで安定するのか

  • background-attachment: fixed を避け、自前の固定レイヤーで同等の表現に置き換えたため。
  • iOS では position: fixed 自体が不安定な場面もあるので、機能より安定性を優先して absolute にフォールバック。
  • svh(Small Viewport Height)を使い、アドレスバー表示/非表示によるvhの揺れを回避。

Discussion