紡Book の勉強ノートに戻る
技術ブログ2026.07.16

ページの途中で背景の色が切り替わる「帯」が出る — background-attachment: fixed の仕様

CSSbackground紡Book

作品テンプレート29種を、ページの上端から下端まで1枚に繋げて撮った全景スクリーンショットで眺めていたら見つかった表示バグの記録です。修正済み。スクショの撮り方は「テンプレート29種の全景スクショを自動で撮る — ウィザード自動操縦と、途中で死んだ別ポート作戦」に書いています。

何が起きていたか

作品テンプレート(写真と言葉の見せ方の型)のページを上から下まで撮った全景スクショで、ページの中腹〜下部に背景色が水平に切り替わる帯が写っていた。上半分は生成りのグラデーション、ある高さから急に白っぽい色に変わる。デザインとしてそんな区切りは入れていない。

同じ症状が3つのテンプレート(一枚一文・柱のきず・交換日記)で出ていた。3箇所で同時に出ているなら、それぞれ別の原因ということはまずありません。同じものが3つに入っている、と当たりを付けて調べ始めた。

原因は1行だった

実装は AI と進めているので、調査もそのまま投げた。返ってきたのは、グラデーションの中身は3つとも違うのに、その下にこの1行だけが揃って入っている、という結果だった。宣言そのものは読めば分かるが、なぜこれで帯が出るのかは分からなかったので、そこは後から自分で追った。

css
/* .page = 作品ページ全体を包む箱に付けた名札 */
.page {
    /* グラデーション自体は3つとも別物(linear だったり radial だったり) */
    background: linear-gradient(180deg, #ffffff 0%, var(--paper) 40%, var(--paper-deep) 100%);
    /* ↓ 共通していたのはこの1行だけ。背景の貼り付け先を「箱」から「画面」に切り替える */
    background-attachment: fixed;
}

fixed にすると、背景のサイズ計算の基準が「要素の箱」ではなく「画面1枚分」になります。

宣言は各テンプレ CSS の .page。描画はブラウザのメモリ。保存しない。scroll(既定)fixed.page約3,000〜4,600px画面約900px画面約900px帯背景は箱に1枚継ぎ目は出ない絵は画面高さで終わる同じ絵を縦に3〜5枚継ぐ

作品ページは写真が並ぶので縦に長いです。全景スクショの実寸から逆算すると、この3テンプレでおよそ3,000〜4,600pxあった。

そして今回のグラデーションは、終わりが一番濃い生成りで、始まりがほぼ白。絵の内側では40%地点、100%地点と滑らかに移り変わっていた色が、絵と絵の境目だけ濃い生成りから白へ一気に飛ぶ。だから「じわっと変わる」ではなく、定規で引いたような水平線に見える。これが帯の正体だった。

つまりバグではなく、仕様どおりの動きだった。長いページと fixed の組み合わせが悪かっただけ。

なぜこの1行が書かれていたのか

仕様どおりなら、そもそも誰がなぜこれを書いたのか。git を遡ると、この行が最初に生まれたのは6月頭に作った誌面風のテンプレートで、そこにはこう添えられていた。

css
/* ごく薄い紙の地合い(繊維のざらつき) */
background-attachment: fixed;

背景を紙に見立てたかった、という意図だ。書いた時点では理由のある1行だった。

問題はその後で、この行が他のテンプレートにコピーされたとき、コメントは付いてこなかった。コピー先のどれにも、宣言だけが単独で座っている。理由を説明する言葉が剥がれた1行は、後から読む側には「何のためにあるのか分からないが、消していいのかも分からない」ものとして残ります。疑う手がかりが無いから、そのまま生き延びます。

直し方

background-attachment: fixed; の行を消しただけ。既定の scroll に戻れば、背景は .page の箱の高さを基準に1回だけ描かれるので、継ぎ目は原理的に出なくなります。3ファイルで同じ1行を消して終わり——と、そのときは思っていた。

後からリポジトリ全体を検索したら、同じ1行は5ファイルにあった。継ぎ目に気づいたのは29枚を撮ったあと推しを8枚に絞って見比べていた回で、残る2つ(手紙・editorial)はその8枚に入っていない=そもそも見ていなかった。しかも editorial はこの1行の発生源そのものだ。この2つは翌日のテンプレート選別でフォルダごと切られて、直らないまま消えた。直したのではなく、たまたま消えた。

描画はブラウザのメモリ。保存しない。スクショは撮った画像。実ブラウザ全景スクショ画面の外見える範囲帯1枚目だけが視界に入るページ全体を像にする

学んだこと

  • 装飾系のCSSはコピペで増殖します。しかも今回は、目視で見つけた3つを直して満足していて、実際には5つあった。目で見つけた数と、grep で出る数は違います。直す前に宣言そのものをプロジェクトのコード全体(リポジトリ)で検索していれば、5つとも出ていた
  • 意図を書いたコメントは旅をせず、宣言だけが旅をします。コピー先に残るのは「理由の分からない1行」で、そうなると誰も疑えないし、消せません
  • 「バグ」に見えても仕様どおりのことがあります。fixed を「背景が動かなくなる指定」としか認識していなくて、サイズ計算の基準まで一緒に変わるとは知らなかった。値を変えたとき何が基準になるかまで見ていないと、この手の組み合わせは踏みます
  • 全景スクショは表示バグの検出器として優秀だった。1画面ずつ見ていたら、画面の外に敷かれていたこの帯には気づけなかったと思う

この記事は2026年7月時点の自分の理解で書いています。仕様や認識が変わってる可能性があります。