iPad off screen elements, z-index ignored with webkit overflow set to touch

I have a div the has overflow: hidden and -webkit-overflow-scrolling: touch. The problem is that z-index is being ignored on elements some elements. This seemed to start with iOS6 on the iPad 2. I don’t remember this being a problem with iOS 5. Here’s a jsfiddle link: (You will need to scroll horizontally to see the whole page).

http://jsfiddle.net/vkt9U/

The full code is also below the text:

Now to see the problem, swipe horizontally across the black squares. You should see the off screen content come into view, BUT the yellow boxes that were off screen are no longer below the black box - until they scrolling has come to a complete stop. Then the yellow boxes obey the z-index that is set for them.

This is a pared down code from a site in development. I tried to get just the parts that are relevant to the problem. Any idea on this would be greatly appreciated. I’ve struggled with this for a while now and can’t seem to figure it out.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">

  <title>CSS3 Touch Scroll Test</title>
  <meta name="viewport" content="width=768, minimum-scale=1.0, maximum-scale=1.0">
  <style type="text/css" title="text/css">
/* <![CDATA[ */
  .projects {
       margin: 4px auto 0;
       padding: 0 20px;
       overflow: hidden;
       width: 918px;
  }

  #row_outer {
       overflow: hidden;
       position: relative;
       height: 246px;
       width: 856px;
       margin-top: 6px;
  }

  #row_inner {
       position: absolute;
       left: 0;
       top: 0;
  }

  .transition {
       -webkit-transition: all 1100ms cubic-bezier(0.190, 1.000, 0.220, 1.000);
       -moz-transition: all 1100ms cubic-bezier(0.190, 1.000, 0.220, 1.000);
        -ms-transition: all 1100ms cubic-bezier(0.190, 1.000, 0.220, 1.000);
         -o-transition: all 1100ms cubic-bezier(0.190, 1.000, 0.220, 1.000);
            transition: all 1100ms cubic-bezier(0.190, 1.000, 0.220, 1.000); /* easeOutExpo */
  }

  .transition_nav_tabs {
       -webkit-transition: all 500ms cubic-bezier(0.250, 0.460, 0.450, 0.940);
          -moz-transition: all 500ms cubic-bezier(0.250, 0.460, 0.450, 0.940);
               -ms-transition: all 500ms cubic-bezier(0.250, 0.460, 0.450, 0.940);
                -o-transition: all 500ms cubic-bezier(0.250, 0.460, 0.450, 0.940);
                       transition: all 500ms cubic-bezier(0.250, 0.460, 0.450, 0.940); /* easeOutQuad */
  }

  .transition_scroll {
       -webkit-transition: all 750ms cubic-bezier(0.230, 1.000, 0.320, 1.000);
          -moz-transition: all 750ms cubic-bezier(0.230, 1.000, 0.320, 1.000);
               -ms-transition: all 750ms cubic-bezier(0.230, 1.000, 0.320, 1.000);
                -o-transition: all 750ms cubic-bezier(0.230, 1.000, 0.320, 1.000);
                       transition: all 750ms cubic-bezier(0.230, 1.000, 0.320, 1.000); /* easeOutQuint */
  }

  .transition_popup_buy_album {
       /* The next two lines may help FF... it may not */
       -moz-backface-visibility: hidden;
       -moz-perspective: 1000;

       -webkit-transition: all 350ms cubic-bezier(0.250, 0.460, 0.450, 0.940);
          -moz-transition: all 350ms cubic-bezier(0.250, 0.460, 0.450, 0.940);
               -ms-transition: all 350ms cubic-bezier(0.250, 0.460, 0.450, 0.940);
                -o-transition: all 350ms cubic-bezier(0.250, 0.460, 0.450, 0.940);
                       transition: all 350ms cubic-bezier(0.250, 0.460, 0.450, 0.940); /* easeOutQuad */
  }

  .box {
       position: absolute;
       left: 0;
       top: 0;
       width: 210px;
       height: 246px;
       text-align: center;
       line-height: 1.25em;
  }

  .box_img {
       width: 210px;
       height: 210px;
       position: absolute;
       left: 0;
       top: 0;
       z-index: 2;
  }

  .bg_on,
  .bg_off {
       position: absolute;
       left: 0;
       top: 0;
  }

  .bg_on {
       opacity: 0;
       filter: alpha(opacity=0);
  }

  .bg_on {
       width: 180px;
       height: 180px;
       margin: 7px 15px 23px;
       background-color: #000;
       -webkit-box-shadow: 0px 8px 16px 0px rgba(123, 81, 45, .8);
       -moz-box-shadow: 0px 8px 16px 0px rgba(123, 81, 45, .8);
       box-shadow: 0px 8px 16px 0px rgba(123, 81, 45, .8);
  }

  :root .bg_on {
       box-shadow:  0px 8px 32px 0px rgba(123, 81, 45, .8)\\9;
  }

  .bg_off {
       width: 180px;
       height: 180px;
       margin: 7px 15px 23px;
       background-color: #000;
       -webkit-box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, .8);
       -moz-box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, .8);
       box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, .8);
  }

  :root .bg_off {
       box-shadow:  0px 8px 32px 0px rgba(00, 00, 00, .8)\\9;
  }

  .box_img a.img_link,
  .box_img span {
       display: block;
       width: 180px;
       height: 180px;
       position: absolute;
       left: 15px;
       top: 7px;
  }

  .box_img .inv_nav {
       position: absolute;
       left: 33px;
       top: 187px;
       width: 142px;
       height: 30px;
  }

  .inv_ba,
  .inv_pt {
       height: 19px;
       position: absolute;
       top: 6px;
       cursor: pointer;
  }

  .inv_ba {
       width: 45px;
       left: 7px;
  }

  .inv_pt {
       width: 72px;
       right: 7px;
  }

  .box_nav {
       background: yellow;
       width: 152px;
       height: 42px;
       position: absolute;
       left: 28px;
       top: 185px;
       z-index: 1;
  }

  /* ===== Mobile Layout Changes ===== */

  @media only screen and (min-device-width: 481px) and (max-device-width: 1024px) {
       /* For landscape AND portrait */
       #row_outer {
               height: 286px;
               margin-left: 20px;
               overflow-x: scroll;
               -webkit-overflow-scrolling: touch;
       }

       .box {
               width: 250px;
               height: 271px;
               margin: 0 7px;
       }

       .box_img {
               width: 250px;
               height: 250px;
       }

       .bg_on {
               width: 220px;
               height: 220px;
       }

       .bg_off {
               width: 220px;
               height: 220px;
       }

       .bg_on_inner,
       .bg_off_inner {
               width: 250px;
               height: 250px;
       }

       .box_img a.img_link,
       .box_img span {
               width: 220px;
               height: 220px;
       }

       .box_img .inv_nav {
               left: 53px;
               top: 227px;
       }

       .box_nav {
               left: 48px;
               top: 225px;
       }
  }

  @media only screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:landscape) {
  /* For landscape layouts only */
       #wrap_inner {
               width: 1024px;
       }

       .projects {
               width: 938px;
       }

       #row_outer {
               width: 890px;
       }
  }

  @media only screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:portrait) {
  /* For portrait layouts only */
       #wrap_inner {
               width: 768px;
       }

       .projects {
               width: 682px;
       }

       #row_outer {
               width: 634px;
       }
  }
  /* ]]> */
  </style>
  <script src="js/jquery-1.8.2.min.js" type="text/javascript" language="javascript">
</script>
  <script type="text/javascript" language="javascript">
// <![CDATA[
  $(document).ready(function() {
       var leftStart = 914;

       var boxWidth = $('.box:first').outerWidth(true); // true: include the margin in the width calculations
       var boxCountZero = $('.box').length - 1;
       var cssTransform = bpfx + 'transform';
       var boxWidthExtra = boxWidth + 650;
       var boxWidthTranslate = 650 - 4;
       var boxWidthFinal = boxWidth + 4;

       // Set project containing box width, move to starting position, then animate
       cssObj = {};
       cssObj[cssTransform] = 'translate3d('+leftStart+'px,0,0)';
       cssObj['width'] = (boxWidth*(boxCountZero+1)) + (boxCountZero * 10);

       $('#row_inner').css(cssObj);

       // Wait for css to "take"
       setTimeout(function() {
               css3SetCheckCount++;
       },1);

       // Move each project box
       $('.box').each(function(index) {
               var cssObj = {};
               cssObj[cssTransform] = 'translate3d('+(index*boxWidthTranslate)+'px,0,0)';
               cssObj['left'] = index * boxWidthFinal;

               $(this).css(cssObj);

               if (index == boxCountZero) {
                       // Wait for css to "take"
                       setTimeout(function() {
                               css3SetCheckCount++;
                       }, 1);
               }
       });

       $('.box_nav').css('top','152px');
  });

  $(window).load(function() {
       var moreDvdsBoxWidth = $('.box:first').outerWidth(true); // Get the full width of one box - includes padding - and margin (true)
       var numberOfBoxesInAllRows = $('#row_inner').children('.box').size();

       $('#row_inner').css({'width': (moreDvdsBoxWidth * numberOfBoxesInAllRows) + 'px'});

       var marginRight = '7px';

       // Wait for all css3 elements to be set then move them
       var css3SetCheck = setInterval(function() {
               if (css3SetCheckCount == 2) {
                       clearInterval(css3SetCheck);

                       // Reset row_outer opacity:1 (visibile) in case this is an iPad
                       $('#row_outer').css({
                               'opacity':'1',
                               'left':'2px'
                       });

                       var transitionCount = 0;
                       // The math for transitionTotal = (number of boxes - 1 + the containing div - 1), i.e. (6 - 1 + 1 - 1)
                       // Number of boxes - 1 , because the first box is not being transitioned, because it's already at zero before the transitions start
                       // The -1 at the end of the equation is because we are starting the counter at 0, and not 1
                       // But because we are starting the counter at zero, we can use the exact number of boxes as the reference
                       var transitionTotal = numberOfBoxesInAllRows - 1;

                       document.getElementById('row_inner').addEventListener(transEnd, function(e) {
                               if (transitionCount == transitionTotal) {
                                       $('#row_inner').removeClass('transition').css(bpfx + 'transform', '');

                                       // Drop down nav tabs
                                       moreDvdsBoxWidth = $('.box:first').outerWidth(true); // Get the full width of one box - includes padding - and margin (true)
                                       $('#row_inner').css({'width': (moreDvdsBoxWidth * numberOfBoxesInAllRows) + 'px'});

                                       var boxNavCount = 0;

                                       $('.box_nav').each(function() {
                                               var t = $(this);
                                               setTimeout(function() {
                                                       var topCSS = '73px';
                                                       t.addClass('transition_nav_tabs').css(bpfx + 'transform', 'translate3d(0,'+topCSS+',0)');
                                               }, boxNavCount);
                                               boxNavCount = boxNavCount + 200;
                                       });
                               }

                               transitionCount++;
                       }, false);

                       $('#row_inner, .box').addClass('transition').css(bpfx + 'transform', 'translate3d(0,0,0)');
               }
       }, 100);

  });

  var css3SetCheckCount = 0;

  var supports = (function() {
       var div = document.createElement('div'),
               vendors = 'Ms,O,Moz,Webkit'.split(','),
               transEnd = 'transitionend,oTransitionEnd,transitionend,webkitTransitionEnd'.split(','),
               len = vendors.length,
               pfx = '';

       return function(prop) {
               if ( prop in div.style ) {
                       //return [true,pfx,getTransEnd()];
                       return [true,pfx,'transitionend'];
               }

               prop = prop.replace(/^[a-z]/, function(val) {
                       return val.toUpperCase();
               });

               while(len--) {
                       if ( vendors[len] + prop in div.style ) {
                               pfx = '-' + vendors[len].toLowerCase() + '-';
                               return [true,pfx,transEnd[len]];
                       }
               }

               return false;
       };

       function getTransEnd() {
       while(len--) {
               if ( vendors[len] + prop in div.style ) {
                       return transEnd[len];
               }
       }
       }
  })();

  var css3support = supports('transform');
  var bpfx = css3support[1];
  var transEnd = css3support[2];
  // ]]>
  </script>
</head>

<body>
  <div class="projects">
    <div id="row_outer">
      <div id="row_inner">
        <div class="box">
          <div class="box_nav"></div>

          <div class="box_img">
            <div class="bg_on"></div>

            <div class="bg_off"></div>
          </div>
        </div>

        <div class="box">
          <div class="box_nav"></div>

          <div class="box_img">
            <div class="bg_on"></div>

            <div class="bg_off"></div>
          </div>
        </div>

        <div class="box">
          <div class="box_nav"></div>

          <div class="box_img">
            <div class="bg_on"></div>

            <div class="bg_off"></div>
          </div>
        </div>

        <div class="box">
          <div class="box_nav"></div>

          <div class="box_img">
            <div class="bg_on"></div>

            <div class="bg_off"></div>
          </div>
        </div>

        <div class="box">
          <div class="box_nav"></div>

          <div class="box_img">
            <div class="bg_on"></div>

            <div class="bg_off"></div>
          </div>
        </div>

        <div class="box">
          <div class="box_nav"></div>

          <div class="box_img">
            <div class="bg_on"></div>

            <div class="bg_off"></div>
          </div>
        </div>
      </div>
    </div>
  </div><!-- END PROJECTS -->
</body>

Hi,

Looks like the z-index is being reset to auto so try a negative z-index on box_nav:


.box_nav {
	background: yellow;
	width: 152px;
	height: 42px;
	position: absolute;
	left: 28px;
	top: 185px;
	[B]z-index: -1;[/B]
}


Seems to work in that test case but of course may have consequences in the real layout.

Yep - that was it. Not sure why it was being set to auto, but changing the z-index to -1 did the trick. Good catch.