🔥
【CSS】iOS Safariでfixed背景がズレる問題を、背景専用レイヤーで解決
background-attachment: fixed を body 直指定で使うと、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の方が安定。
解決方針
-
body背景をやめる:DOMに背景専用のレイヤーを追加して、そこで背景を描画する。 - **PC/Androidは固定(
position: fixed)**を維持。 -
iOSは安全策として
position: absoluteにフォールバック(完全固定ではないが、ズレ・チラつきを防止)。 - 画面の縦横比で
background-positionを微調整。 - セクションの高さは
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