4

I'm seeing some interesting z-index behaviour on iOS.

My sample code can be viewed here: https://jsfiddle.net/59mo8s16/4/

I need the #sidebar to be displayed in front of the #slide-in-tip. This is the case when viewed on Chrome (PC and Android) and Firefox (PC). However, on iOS Safari and Chrome, #slide-in-tip appears in front of #sidebar.

I've realised that removing -webkit-overflow-scrolling: touch from the CSS makes it appear as intended across all platforms/browsers. However, I need this in order to provide momentum scrolling for the #container div on iOS. Without it, you get that scrolling that stops as soon as you stop swiping, which provides a terrible user experience.

Any ideas on how to resolve this one? Ideally I'd like a CSS-only solution. Any significant restructure of HTML will cause me some major pain at this point. The sample is a really stripped back version of an already-complete website.

HTML:

html,
body {
  height: 100%;
  margin: 0;
  -webkit-overflow-scrolling: touch;
}

#top-bar {
  top: 0;
  width: 100%;
  z-index: 200;
  background-color: green;
  height: 85px;
  position: absolute;
}

#sidebar {
  float: left;
  padding: 30px;
  background-color: pink;
  position: fixed;
  width: 310px;
  left: 0px;
  z-index: 150;
  top: 85px;
  bottom: 0px;
  padding: 0;
  padding-bottom: 50px;
}

#container2 {
  min-height: 100%;
}

#main {
  padding-right: 20px;
  height: 100%;
  margin: 0;
  margin-left: 10%;
  line-height: 40px;
  text-align: right;
}

#container {
  height: 100%;
  margin: 0;
  position: absolute;
  width: 100%;
  overflow-y: scroll;
}

#container2 {
  padding-top: 75px;
}

#slide-in-tip {
  position: fixed;
  bottom: 0;
  text-align: right;
  width: 100%;
  z-index: 140;
  background-color: blue;
  height: 200px;
}
<div id="top-bar">
  top-bar
</div>
<div id="container">
  <div id="container2">
    <div id="sidebar">
      sidebar
    </div>
    <div id="main">
      long content - see js fiddle for actual long content
    </div>
  </div>
</div>
<div id="slide-in-tip">
  slide-in-tip
</div>

2
  • Try increasing the z-index value, maybe 200 or so. Commented Apr 24, 2017 at 2:15
  • @TricksfortheWeb Nope. Commented Apr 24, 2017 at 3:09

1 Answer 1

2
+50

The documentation offers an explanation for the behaviour you're seeing:

touch
Native-style scrolling. Specifying this style has the effect of creating a stacking context (like opacity, masks, and transforms).

Since you cannot destroy a stacking context after creating one, an element outside of a stacking context cannot interact directly with elements within that stacking context, and you cannot move elements between stacking contexts without moving them physically, you won't be able to work around the stacking issues without restructuring your physical HTML.

Having said that, you shouldn't have to make significant changes to your structure. The best you can do is simply move #slide-in-tip into #container2 as a sibling of #sidebar and #main (where exactly you place it doesn't matter, as long as they are all siblings). For whatever reason, though, this seems to cause severe flickering on scroll in the simulator — I don't have a physical device to test this on, so you'll want to test this thoroughly.

The only CSS-based workaround I can offer is to shorten your #slide-in-tip by giving it a left offset equal to the width of #sidebar. Note that you have conflicting padding declarations in your #sidebar rule such that the width of #sidebar is actually 310px, not 370px. Unfortunately, if portions of #sidebar are transparent and you want #slide-in-tip to be seen through those transparent portions, this will not be an option either.

Sign up to request clarification or add additional context in comments.

2 Comments

thanks for the explanation. it's starting to make sense. the specific sizes of the elements are pretty irrelevant - they have been modified for the purposes of the example. in the actual website, #slide-in-tip slides up from the bottom of screen temporarily based on a timer. #sidebar slides in from the left based on a user clicking/tapping a button. i'm now thinking the easiest option might be for me to just hide #slide-in-tip completely as the #sidebar is triggered. however, i will try your suggestion when i have access to an apple device later today.
Moving #slide-in-tip to inside of #container2 seems to have done the trick. Not seeing any issues with flickering on iphone 6. This was a relatively simple change so I'm happy to go with it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.