最終更新日:

background-attachment: fixedを使わずに、背景固定をiOSで実装する方法

背景固定をiOSで実装する方法

こんにちは。五平餅くんです。

「背景を固定でお願いします」

みたいなことはよくデザイナーさんからご指示を受けます。

そんな時、cssには便利なbackground-attachment: fixedというプロパティがあり、背景画像を簡単に固定してくれます。

背景固定例:https://test01.goheymochikun.com/ の「五平餅組、高みを目指す」のところ

ただ、実務でbackground-attachment: fixedはほとんど使えません。

なぜbackground-attachment: fixedは使えないのか

background-attachment: fixedを実務で使えない理由、それは、

iOSで動かないのです!!

iOSとは・・・iPhoneやiPadなど。

レスポンシブが当たり前の時代において、iPhoneで表示が変わるのは致命的です。

そこで今回は、iOSに対応した背景固定の実装方法をご紹介します。

ちなみに、、、、

background-attachment: fixedがiOSで動かないのは、厳密にはbackground-size: coverが一緒に指定されている場合です。background-sizeが違う値なら動くかもしれません。

ただ、background-sizeプロパティでcover以外の値を使うことはほとんどないかと思いますので、ほぼbackground-attachment: fixedは使えない状況です。

iOSに対応した背景固定の実装方法

さて、本題に参ります。

iOSに対応した背景固定の実装方法ですが、background-attachment: fixedは使いません

一旦background-attachment: fixedは忘れましょう。

今回はposition: fixedを使って同じように表現します。

<section class="section-p bg-white">
  <div class="inner">
    <h1>セクション1</h1>
    <p class="mt30">テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
    <p>テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
    <p>テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
    <p>テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
    <p>テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
    <p>テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
    <p>テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
    <p>テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
  </div>
</section>

<section class="section-p bg-gray">
  <div class="inner">
    <h1>セクション2</h1>
    <p class="mt30">テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
    <p>テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
    <p>テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
    <p>テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
    <p>テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
    <p>テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
    <p>テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
    <p>テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
  </div>
</section>

<!-- ここから重要! -->
<section class="section-p" id="bg-fix-section">
  <div class="inner">
    <div class="bg-fix js-bg-fix">
      <div class="bg-fix__txt">
        <h1>セクション3</h1>
        <p class="mt30">テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
        <p>テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
        <p>テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
      </div>
    </div>
  </div>
</section>

/* リセット */
* {
  margin: 0;
  padding: 0;
}

li {
  list-style: none;
}

a {
  text-decoration: none;
  color: inherit;
}

/* ベース設定 */
.inner {
  max-width: 800px;
  width: 97%;
  margin: 0 auto;
}

.section-p {
  padding: 100px 0;
}

.bg-white {
  background: #fff;
}

.bg-gray {
  background: #f5f5f5;
}

.mt30 {
  margin-top: 30px;
}

/* ここから重要! */
#bg-fix-section {
  border-top: 100px solid #fff;/* 100pxは.section-pと同じ値 ! */
  border-bottom: 100px solid #fff;/* 100pxは.section-pと同じ値 ! */
}

.bg-fix {
  height: 300px;
}

.bg-fix::before {
  content: '';
  display: none;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%);
  z-index: -1;
  width: 800px;/* .innerのmax-widthと同じ設定 */
  height: 100vh;
  min-height: 500px;
  background-image: url();
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
}

.bg-fix.active::before {
  display: block;
  background-image: url(../img/kouji-fixed-bg.jpg);
}

.bg-fix__txt {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  text-align: center;
  height: 300px;
}
$(function() {
  $(window).scroll(function () {
    var scrollTop = $(this).scrollTop();
    var showPoint = $('#bg-fix-section').prev().offset().top - 300;
    if(scrollTop > showPoint) {
      $(".js-bg-fix").addClass('active');
    } else if(scrollTop < showPoint) {
      $(".js-bg-fix").removeClass('active');
    }
  });
});

解説

bg-fixの擬似要素にposition: fixedを指定してあります。

position: fixedは画面固定してくれるプロパティです。

テキストが上に来るようにするため、z-index: -1も忘れずにお願いします!

ひとまずこれで画面固定は完了です(あっさり!)。

しかしこれだけでは不十分なので、ここからはポイントをいくつかご紹介します。

他のセクションに背景色をつけておく

背景固定をするセクションは背景色が透明です。

背景色が透明なので、画面固定されている背景画像が見える感じになります。

ということは、他のセクションは白やグレーなど背景色をつけないと、他のセクションでも背景画像がすけて見えてしまいます。

<section class="section-p bg-white">
・・・
</section>

<section class="section-p bg-gray">
・・・
</section>
.bg-white {
  background: #fff;
}

.bg-gray {
  background: #f5f5f5;
}

背景固定をするセクションの余白は、borderで実装

背景固定をするセクションの余白は、白のborderで実装をお願いいたします。

(borderの色は、サイトに合わせて変更してOKです。)

これをpaddingでやっても、背景色が透明なので余白ができません。

ここは他のセクションの余白と同じ値の上下borderで余白を作ってください。

#bg-fix-section {
  border-top: 100px solid #fff;/* 100pxは.section-pと同じ値 ! */
  border-bottom: 100px solid #fff;/* 100pxは.section-pと同じ値 ! */
}

背景固定をするセクションの前のセクションまでスクロールしたら背景画像を表示

今回、固定する背景画像を最初は何も指定しません。

background-image: url()で空にしておきます。

これを、背景固定をするセクションの前のセクションまでスクロールしたら初めて背景画像を表示するようにします。

なぜ、こんなことをするかというと、一番上までスクロールした時に、ちらっと固定する背景画像が見えてしまうからです。

※一部ブラウザのみ。動画はfirefoxです。

背景固定をするセクションの前のセクションまでスクロールしたら初めて背景画像を表示するようにするために、まずあらかじめこのcssを記述しておきます。

.bg-fix::before {
  /* 一部省力 */
  display: none;
  background-image: url();
}
/* active後 */
.bg-fix.active::before {
  display: block;
  background-image: url(../img/kouji-fixed-bg.jpg);
}

そして、JavaScript(jQuery)で、「背景固定をするセクションの前のセクションまでスクロールしたら、activeというclassを付与する」という処理を追加します。

$(function() {
  $(window).scroll(function () {
    var scrollTop = $(this).scrollTop();
    var showPoint = $('#bg-fix-section').prev().offset().top - 300;
    if(scrollTop > showPoint) {
      $(".js-bg-fix").addClass('active');
    } else if(scrollTop < showPoint) {
      $(".js-bg-fix").removeClass('active');
    }
  });
});

var scrollTop = $(this).scrollTop(); という部分が「スクロールの量」、
var showPoint = $(‘#bg-fix-section’).prev().offset().top – 300; という部分が「背景固定をするセクションの前のセクションの、一番上からの距離」になります。スクロールの少し前に対応するため、300px引いています。

条件分岐で、スクロール量が「背景固定をするセクションの前のセクションの、一番上からの距離」よりも大きい時【if(scrollTop > showPoint))】、.js-bg-fixにactiveクラスを付与します。

小さい時【else if(scrollTop < showPoint)】は.js-bg-fixからactiveクラスを取り除きます。

.js-bg-fixは、背景固定をしている部分(.bg-fix)と同じ要素についているclassですので、.bg-fixにactiveというclassを付けたり取ったりしていることと同じ意味になります。.js-bg-fixは、JavaScript用のclassです。

これで「背景固定をするセクションの前のセクションまでスクロールしたら背景画像を表示」する実装は完成です!

ただ、実はこの「一部のブラウザで一番上までスクロールした時に、ちらっと固定する背景画像が見えてしまう問題」は、一番下でも起こります。

今度、一番下までスクロールした場合のJavaScriptをご紹介しますので、その後に追記させていただきます。


ということで今回は以上です!

最後まで読んでいただきありがとうございました!

関連記事

人気記事