While scrolling on an iOS device, the z-index of elements isn't working
Asked Answered
N

2

29

My layout is fairly simple, a repeating background element, a couple of vertical spaces (roads) and some horizontal bridges and a little car which should drive underneath them when you scroll.

Everything works just fine on my Mac but on iOS devices —my testing devices are: iPhone 4 on iOS 6.1, iPad 2 on iOS 6.1.3— the z-index isn't being honoured when the scroll event is active.

This means that as you scroll, the car, which is position: fixed to the window, is moving over the bridge (which has a higher z-index than the "car") rather than the z-index making the bridge higher as it should be and is on non-iOS browsers which makes the car drive under the bridge.

It seems like a simple layering issue, but even with a very simplified test case the bug is still apparent.

Test case: http://plnkr.co/EAE5AdJqJiuXgSsrfTWH (view in full screen on iPad to avoid a iframe scrolling issue which isn't related to the demo content)

Does anyone know what's wrong with the code which would cause the z-index not working while the scroll is active?

Note: This happens on both, Chrome for iOS and the native Mobile Safari.


Here are the code bits running on the reduced test case I linked to above in case someone can point out a fix without opening the demo.


HTML:

<!DOCTYPE html>
<html>

  <head>
    <link rel="stylesheet" href="style.css">
  </head>

  <body>
    <div class="car"></div>

    <div class="street"></div>
    <div class="bridge"></div>
    <div class="street"></div>
    <div class="bridge"></div>
    <div class="street"></div>
    <div class="bridge"></div>
    <div class="street"></div>
    <div class="bridge"></div>
    <div class="street"></div>
    <div class="bridge"></div>
    <div class="street"></div>
    <div class="bridge"></div>
    <div class="street"></div>
  </body>

</html>

CSS:

body {
  /* Adds the 'road' as a background image. */
  background: #8BA341 url("http://f.cl.ly/items/1r2g152h2J2g3m1e1V08/road.png") repeat-y top center;
  margin:     0;
  padding:    0;
} 

.car {
  /* The car's position is fixed so that it scrolls along with you. */
  position:   fixed;
  top:        5%;
  left:       52%;
  width:      220px;
  height:     330px;
  background: #BD6C31;
  z-index:    1;
}
.street {
  /* Empty in the example, just used to space things out a bit. */
  position:   relative;
  height:     500px;
}
.bridge {
  /* A bridge crossing the main road. The car should drive under it. */
  position:   relative;
  height:     353px;
  /* Image of repeating road. */
  background: url("http://f.cl.ly/items/0u0p2k3z45242n1w3A0A/bridge-road.png") repeat-x center left;
  /* Higher z-index than car. */
  z-index:    2;
}
Niven answered 16/4, 2013 at 9:30 Comment(3)
Just in case anyone else stumbles upon this question… while the original question hasn't been answered entirely (I still don't know why the normal z-index stacking order isn't being used properly) the solution to get things to work is using a negative z-index for background elements and the car itself. So car is negative, overpass/bridge is on a positive z-index and then iOS renders it correctly.Niven
I'm having the same issue and your negative z-index solution does indeed the trick but it unfortunately raises another problem: negative z-indices on <a> tags breaks the links. Thanks for sharing anyways, I'll do my part if I find something but I'm quit stuck right now.Rockery
I keep looking for a workaround, but meanwhile here are the results of some investigations: plnkr.co/aeubN4 If I'm correct, I'm not sure if there's anything we can do about it?Rockery
D
59

I believe I've solved this after much trial and error. What I did was add a webkit transform to the bridges. This allows for positive z-index numbers (car at 10, pothole at 1, bridge at 20):

new CSS:

.bridge {
  -webkit-transform: translate3d(0,0,0);
}

Adding the translate to the different bridges seem to not only fix the flicker from before, but also lets you scroll immediately without any delay.

Check it out in full screen or the full Plunker. Tested on iPad iOS 6.0.1.

Dollarbird answered 14/8, 2013 at 18:58 Comment(7)
I started to give up after days of struggling but your solution is working great in my case me as well, thanks!Rockery
Bizzare bug, your solution fixed it for us too!Abessive
Awesome. Works greats!Montgolfier
OMG! I spent a week trying to get jplayer to work with reveal.js The play button link would not fire when touched on the iphone (links worked on the ipad, firefox, chrome, everything else, but ios). Your CSS trick solved my problem. Thank you!!!!!!Knut
My entire organization says thank you. Come grab a beer if you'll ever travel Israel.Fungoid
Bless you strangerNeighborly
This is stopped working on ios 12.2 any suggestion here ?Blindfish
G
0

What solved the issue for me was making sure that the items in the DOM were in descending order based on the z-index value. So the items I needed on top was z-3 and was listed first, then the z-2 item, then z-1. Hope this helps someone else!

Groscr answered 8/12, 2022 at 15:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.