Fixed body background scrolls with the page on iOS7

I'll try and find some reference, but mobile browsers force background: scroll because the repainting is too expensive.


Reference:

CSS - Background images not displaying properly on mobile browsers

@PaulIrish also noted this:

Fixed-backgrounds have huge repaint cost and decimate scrolling performance, which is, I believe, why it was disabled.

There are ways around this, though.. but it's not a quick fix. Have a look at the following question and it's comment.

Android/Mobile Webkit CSS Background-Attachment:Fixed Not Working?


I would recommend looking into scrollr (https://github.com/Prinzhorn/skrollr). It's a parallax library allowing you to achieve the same effect. They have carefully considered issues with mobile devices too:

Some words on why this is an important milestone and why others failed: Mobile browsers try to save battery wherever they can. That's why mobile browsers delay the execution of JavaScript while you are scrolling. iOS in particular does this very aggressively and completely stops JavaScript. In short, that's the reason why many scrolling libraries either don't work on mobile devices or they come with their own scrollbar which is a usability nightmare on desktop. It was an important requirement while I developed skrollr that I don't force you to scroll the way I want it. skrollr on desktop uses a native scrollbar and you can scroll the way you want to (keyboard, mouse, etc.).

You just told me it doesn't work on mobile, but why does it? The answer is simple. When using skrollr on mobile you don't actually scroll. When detecting a mobile browser, skrollr disables native scrolling and instead listens for touch events and moves the content (more specific the #skrollr-body element) using CSS transforms.

Here is an example of the classic parallax background implementation: http://prinzhorn.github.io/skrollr/examples/classic.html

Stated on the example page, another gem worth noting:

Degrades without JavaScript (could be disabled on mobile without breaking everything).


I noticed the background-attachment problem when upgrading to iOS7. I had to fix the issue using Javascript as I couldn't figure out a solution with CSS alone.

if (iosVersion >= 7) {
    $(document).scroll(function() {
        $('#background').css('background-position', '0px ' + $(document).scrollTop() + 'px');
    });
}

I had the same issue you had and struggled with it almost 3 days. But as of June 2020 here is a reliable solution I found for this that works on all devices and has 100% browser compatibility. It allows the desired effect in any place of the page and not just the top or bottom of the page, and you can create as many as you need or want.

The only known issue so far is in safari. The browser repaints the whole image on every scroll movement so it puts a heavy burden on graphics and most of the time makes the image flicker up and down some 10px. There is literally no fix for this, but i think there is also no better response for your inquire.

I hope this works for you. You can check the results live in www.theargw.com, where i have three different fixed background images.

body, .black {
  width: 100%;
  height: 200px;
  background: black;
}

.e-with-fixed-bg {
  width: 100%;
  height: 300px;
  
  /* Important */
  position: relative;
}

.bg-wrap {
  clip: rect(0, auto, auto, 0);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.bg {
  position: fixed;
  display: block;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-size: cover;
  background-position: center center;
  background-image: url(https://images.pexels.com/photos/949587/pexels-photo-949587.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500);
  transform: translateZ(0);
  will-change: transform;
}

.e-container {
  z-index: 1;
  color: white;
  background: transparent;
}
<div class="black"></div>
<div class="e-with-fixed-bg">
  <div class="bg-wrap">
     <div class="bg"></div>
  </div>
  <div class="e-container">
    <h1>This works well enought</h1>
  </div>
</div>
<div class="black"></div>

--------------------- EDIT --------------------- The code posted was missing the background wrapper that allows the background to not change size and maintain the fixed position. Sorry to post the wrong code this morning guys! But here is the change.