-webkit-overflow-scrolling: touch does not "obey" z-index #14

Open
bridgestew opened this Issue Mar 27, 2012 · 32 comments

Comments

Projects
None yet
@bridgestew

Summary:

-webkit-overflow-scrolling: touch does not "obey" z-index.

Platforms:

iOS5, not sure about other platforms

How to reproduce:

  1. Build a content area and a modal overlay above it using HTML/CSS
  2. View on iPad for the example below. When you attempt to scroll the page, the content behind the modal scrolls. I wouldn't expect this, since attempting to click a link behind a z-index div doesn't work...

Reduced Example:

(Hastily thrown together example. No Media queries applied, so ignore the ugly -- just check out the bug.)
http://jsfiddle.net/cPHMN/48/embedded/result/

Bug Tracker ticket(s):

Workarounds:

@scottjehl

This comment has been minimized.

Show comment
Hide comment
@scottjehl

scottjehl Mar 29, 2012

Owner

Interesting. This sounds and looks similar to how touch devices vary in their bubbling of scroll events on elements in the page.

Is your scroll region short enough to trigger a scroll? I wonder how it'll behave if it is...

On Mar 27, 2012, at 9:19 PM, bridgestew wrote:

Summary:

-webkit-overflow-scrolling: touch does not "obey" z-index.

Platforms:

iOS5, not sure about other platforms

How to reproduce:

  1. Build a content area and a modal overlay above it using HTML/CSS
  2. View on iPad for the example below. When you attempt to scroll the page, the content behind the modal scrolls. I wouldn't expect this, since attempting to click a link behind a z-index div doesn't work...

Reduced Example:

(Hastily thrown together example. No Media queries applied, so ignore the ugly -- just check out the bug.)
http://jsfiddle.net/cPHMN/48/embedded/result/

Bug Tracker ticket(s):

Workarounds:


Reply to this email directly or view it on GitHub:
#14

Owner

scottjehl commented Mar 29, 2012

Interesting. This sounds and looks similar to how touch devices vary in their bubbling of scroll events on elements in the page.

Is your scroll region short enough to trigger a scroll? I wonder how it'll behave if it is...

On Mar 27, 2012, at 9:19 PM, bridgestew wrote:

Summary:

-webkit-overflow-scrolling: touch does not "obey" z-index.

Platforms:

iOS5, not sure about other platforms

How to reproduce:

  1. Build a content area and a modal overlay above it using HTML/CSS
  2. View on iPad for the example below. When you attempt to scroll the page, the content behind the modal scrolls. I wouldn't expect this, since attempting to click a link behind a z-index div doesn't work...

Reduced Example:

(Hastily thrown together example. No Media queries applied, so ignore the ugly -- just check out the bug.)
http://jsfiddle.net/cPHMN/48/embedded/result/

Bug Tracker ticket(s):

Workarounds:


Reply to this email directly or view it on GitHub:
#14

@bridgestew

This comment has been minimized.

Show comment
Hide comment
@bridgestew

bridgestew Apr 24, 2012

I don't understand your question about the scroll region being short enough. :)

I don't understand your question about the scroll region being short enough. :)

@moll

This comment has been minimized.

Show comment
Hide comment
@moll

moll May 6, 2012

One workaround is to apply the same overflow: scroll and -webkit-overflow-scrolling: touch on the layer above it to stop the lower one from getting the events.

moll commented May 6, 2012

One workaround is to apply the same overflow: scroll and -webkit-overflow-scrolling: touch on the layer above it to stop the lower one from getting the events.

@kpuputti

This comment has been minimized.

Show comment
Hide comment
@kpuputti

kpuputti May 28, 2012

I think I ran into the same issue with my custom map component.

I have a large pannable image (with -webkit-overflow-scrolling: touch) and absolutely positioned marker images on top. Sometimes I get one marker to show up, but usually they are hidden no matter what the z-index is.

Any solutions yet for this?

I think I ran into the same issue with my custom map component.

I have a large pannable image (with -webkit-overflow-scrolling: touch) and absolutely positioned marker images on top. Sometimes I get one marker to show up, but usually they are hidden no matter what the z-index is.

Any solutions yet for this?

@moll

This comment has been minimized.

Show comment
Hide comment
@moll

moll May 28, 2012

@kpuputti This bug's problem with z-index is only functional — visually the items are correct. You sure the map you've got has a lower z-index than all the markers?

moll commented May 28, 2012

@kpuputti This bug's problem with z-index is only functional — visually the items are correct. You sure the map you've got has a lower z-index than all the markers?

@kpuputti

This comment has been minimized.

Show comment
Hide comment
@kpuputti

kpuputti May 28, 2012

@moll Yes, the z-index on the map is lower than on the markers.

I'm using Overthrow ( http://filamentgroup.github.com/Overthrow/ ) and the map works fine on Android 2.3 & 4.0, WP7, iOS 4.2. Of these platforms, at least Android 4.0 supports the native touch scrolling.

This comment is the only info I've found:
http://mobile.tutsplus.com/tutorials/mobile-web-apps/ios-5-fixed-positioning-and-content-scrolling/comment-page-1/#comment-17477

@moll Yes, the z-index on the map is lower than on the markers.

I'm using Overthrow ( http://filamentgroup.github.com/Overthrow/ ) and the map works fine on Android 2.3 & 4.0, WP7, iOS 4.2. Of these platforms, at least Android 4.0 supports the native touch scrolling.

This comment is the only info I've found:
http://mobile.tutsplus.com/tutorials/mobile-web-apps/ios-5-fixed-positioning-and-content-scrolling/comment-page-1/#comment-17477

@kpuputti

This comment has been minimized.

Show comment
Hide comment
@kpuputti

kpuputti May 28, 2012

Oh, I found the solution. My problem seemed to be the same as in this issue:

#8

and the proposed workaround fixed the problem.

Oh, I found the solution. My problem seemed to be the same as in this issue:

#8

and the proposed workaround fixed the problem.

@hober

This comment has been minimized.

Show comment
Hide comment
@hober

hober Aug 28, 2012

This is not a bug; -webkit-overflow-scrolling: touch induces a stacking context. Just like if you put opacity: 0.9 or a 3d transform on the element.

hober commented Aug 28, 2012

This is not a bug; -webkit-overflow-scrolling: touch induces a stacking context. Just like if you put opacity: 0.9 or a 3d transform on the element.

@toddparker

This comment has been minimized.

Show comment
Hide comment
@toddparker

toddparker Aug 28, 2012

Collaborator

Thanks for chiming in with this info @hober.

Collaborator

toddparker commented Aug 28, 2012

Thanks for chiming in with this info @hober.

@cstewartgannett

This comment has been minimized.

Show comment
Hide comment
@cstewartgannett

cstewartgannett Feb 20, 2013

@hober How is this not a bug? I have my context layered properly and -webkit-overflow-scrolling: touch on the top most layer. Functionally everything works properly, except that the background scrolls instead of my modal, unless I use the scrollbar to scroll the div (which contains an unavoidable iFrame). Has anyone else found a workaround for this?

@hober How is this not a bug? I have my context layered properly and -webkit-overflow-scrolling: touch on the top most layer. Functionally everything works properly, except that the background scrolls instead of my modal, unless I use the scrollbar to scroll the div (which contains an unavoidable iFrame). Has anyone else found a workaround for this?

@noordawod

This comment has been minimized.

Show comment
Hide comment
@noordawod

noordawod May 12, 2013

Hello all,

I am in the same boat here, unfortunately. But I did find a solution to this. Actually only one, for now.

The solution that I've found is to turn off overflow for the DIV underneath (having lesser z-index) using "overflow:hidden". This seems to trick iOS into capturing the touch events on the top-most DIV (having a higher z-index).

The only downside to this trick, however, is once the DIV having the higher z-index is dismissed (using animation or not), and "overflow:auto" or "overflow:scroll" is reapplied to the DIV underneath, a short "flick" is noticed as if the iOS is redrawing that DIV.

If any of you guys or gals found a better solution, it'd be nice to share.

/Noor

Hello all,

I am in the same boat here, unfortunately. But I did find a solution to this. Actually only one, for now.

The solution that I've found is to turn off overflow for the DIV underneath (having lesser z-index) using "overflow:hidden". This seems to trick iOS into capturing the touch events on the top-most DIV (having a higher z-index).

The only downside to this trick, however, is once the DIV having the higher z-index is dismissed (using animation or not), and "overflow:auto" or "overflow:scroll" is reapplied to the DIV underneath, a short "flick" is noticed as if the iOS is redrawing that DIV.

If any of you guys or gals found a better solution, it'd be nice to share.

/Noor

@moll

This comment has been minimized.

Show comment
Hide comment
@moll

moll May 12, 2013

@noordawod:

If any of you guys or gals found a better solution, it'd be nice to share.

Well, I consider the workaround I posted a year ago to be a better solution as it doesn't require JavaScript nor changes other elements' styles.

moll commented May 12, 2013

@noordawod:

If any of you guys or gals found a better solution, it'd be nice to share.

Well, I consider the workaround I posted a year ago to be a better solution as it doesn't require JavaScript nor changes other elements' styles.

@noordawod

This comment has been minimized.

Show comment
Hide comment
@noordawod

noordawod May 12, 2013

@moll

I've seen and checked your proposed solution before. Surely, I had these CSS rules in place since I wanted the top DIV to have a scrollbar, even before I saw your post (it only made sense to me.)

Now, the interesting thing is that although this works when the DIV is displayed without any animation, the solution doesn't work when animating the DIV (for example, making it appear by sliding it from the bottom of the screen to the top, like Safari's Bookmarks panel on the iPhone.)

This must be a bug in iOS's transformations, I am guessing. Not opacity, as @hober suggested, since when I show the DIV instantly without an animation, and set its opacity to 0.9, scrolling still works.

So we're back to the first post by @bridgestew since it doesn't work when the DIV is animated, sadly.

/Noor

@moll

I've seen and checked your proposed solution before. Surely, I had these CSS rules in place since I wanted the top DIV to have a scrollbar, even before I saw your post (it only made sense to me.)

Now, the interesting thing is that although this works when the DIV is displayed without any animation, the solution doesn't work when animating the DIV (for example, making it appear by sliding it from the bottom of the screen to the top, like Safari's Bookmarks panel on the iPhone.)

This must be a bug in iOS's transformations, I am guessing. Not opacity, as @hober suggested, since when I show the DIV instantly without an animation, and set its opacity to 0.9, scrolling still works.

So we're back to the first post by @bridgestew since it doesn't work when the DIV is animated, sadly.

/Noor

@noordawod

This comment has been minimized.

Show comment
Hide comment
@noordawod

noordawod May 12, 2013

And like I mentioned before, only setting overflow to hidden on the lower DIV makes the top DIV respond to touch scrolling (when the top DIV has been animated to its position.)

And like I mentioned before, only setting overflow to hidden on the lower DIV makes the top DIV respond to touch scrolling (when the top DIV has been animated to its position.)

@noordawod

This comment has been minimized.

Show comment
Hide comment
@noordawod

noordawod May 12, 2013

Here's more information about a stacking context, introduced by @hober :
http://daneden.me/2012/04/css-transforms-and-z-index/

Here's more information about a stacking context, introduced by @hober :
http://daneden.me/2012/04/css-transforms-and-z-index/

@thztti

This comment has been minimized.

Show comment
Hide comment
@thztti

thztti Sep 2, 2013

@moll your trick works. Thanks!

thztti commented Sep 2, 2013

@moll your trick works. Thanks!

@tymcdowell

This comment has been minimized.

Show comment
Hide comment
@tymcdowell

tymcdowell Oct 2, 2013

I stumbled onto this conversation because I have a similar issue that I have now fixed. I have a menu panel that is absolutely positioned above the main page. I hide/show this panel using an opacity transition. Both this panel and the main page use -webkit-overflow-scrolling:touch. My problem was that when showing the menu the scrolling would not work and instead the main page behind it would scroll. To fix this, I simply removed the -webkit-overflow-scrolling:touch from the menu when hidden and add it back when shown. It seems that the order in which this value is added is very important here. I was surprised to see that there is no flicker when you do this.

Cheers

I stumbled onto this conversation because I have a similar issue that I have now fixed. I have a menu panel that is absolutely positioned above the main page. I hide/show this panel using an opacity transition. Both this panel and the main page use -webkit-overflow-scrolling:touch. My problem was that when showing the menu the scrolling would not work and instead the main page behind it would scroll. To fix this, I simply removed the -webkit-overflow-scrolling:touch from the menu when hidden and add it back when shown. It seems that the order in which this value is added is very important here. I was surprised to see that there is no flicker when you do this.

Cheers

@sofish

This comment has been minimized.

Show comment
Hide comment
@sofish

sofish May 24, 2014

@moll seems not working on ios7

sofish commented May 24, 2014

@moll seems not working on ios7

@joeybaker

This comment has been minimized.

Show comment
Hide comment
@joeybaker

joeybaker Aug 27, 2014

This bug appears to be gone in iOS8.

This bug appears to be gone in iOS8.

@iclanzan

This comment has been minimized.

Show comment
Hide comment
@iclanzan

iclanzan Dec 30, 2014

Still present on iOS 8.1.

Still present on iOS 8.1.

@janson

This comment has been minimized.

Show comment
Hide comment
@janson

janson Jan 19, 2015

Like @iclanzan, I can confirm it is still present in iOS 8.1 Here's what I think is the relevant bug report on Webkit Bugzilla

Edit: nope.

My workaround:

.modal {
    overflow-y: scroll;
    -webkit-overflow-scrolling: touch;
}
.content-behind-modal {
    overflow: hidden;
    -webkit-overflow-scrolling: auto;
}

janson commented Jan 19, 2015

Like @iclanzan, I can confirm it is still present in iOS 8.1 Here's what I think is the relevant bug report on Webkit Bugzilla

Edit: nope.

My workaround:

.modal {
    overflow-y: scroll;
    -webkit-overflow-scrolling: touch;
}
.content-behind-modal {
    overflow: hidden;
    -webkit-overflow-scrolling: auto;
}

@Master-Oliveira Master-Oliveira referenced this issue in FrDH/jQuery.mmenu Apr 15, 2015

Closed

Scroll bug on iPhone 6 / iOS 8 #332

@shi-sergiom

This comment has been minimized.

Show comment
Hide comment
@shi-sergiom

shi-sergiom May 1, 2015

@moll your trick did indeed work like a charm, until iOS8 was released.
i could change the -webkit-overflow-scroll: auto; (as mentioned by @jason) but that adds a flicker that I'm not willing to live with.

@moll your trick did indeed work like a charm, until iOS8 was released.
i could change the -webkit-overflow-scroll: auto; (as mentioned by @jason) but that adds a flicker that I'm not willing to live with.

@davidvanleeuwen davidvanleeuwen referenced this issue in awkward/backbone.modal May 7, 2015

Closed

Modal scrolling issue #77

@studioscholz

This comment has been minimized.

Show comment
Hide comment
@studioscholz

studioscholz Aug 25, 2015

@noordawod
calling the css as part of the animation queue solved the problem for me.
("div").css("webkit-overflow-scrolling" , "touch");

@noordawod
calling the css as part of the animation queue solved the problem for me.
("div").css("webkit-overflow-scrolling" , "touch");

@a5hik a5hik referenced this issue in a5hik/ng-sortable Sep 4, 2015

Closed

Issues on iOS while sorting #215

@manoj30dec

This comment has been minimized.

Show comment
Hide comment
@manoj30dec

manoj30dec Oct 8, 2015

Just target IOS device with media query and put overflow:touch; instead of -webkit-overflow-scrolling: touch; that works for me :-)

Just target IOS device with media query and put overflow:touch; instead of -webkit-overflow-scrolling: touch; that works for me :-)

@Aides359

This comment has been minimized.

Show comment
Hide comment
@Aides359

Aides359 Jun 6, 2016

Is there any working workaround for this issue? (The workaround from @moll does not work in my case, the one from @noordawod does, however while the short flicker is still acceptable, the repaint causes heavy performance problems which are far from acceptable)

Two things I've noticed (testing with iPhone 5+6 on iOS 9.1 and 9.3.2):
• it only occurs when launching the page/app from the homescreen (pinned app)
• changing the device orientation (portrait -> landscape) after page load fixes the problem and everything works as expected

PS: why are the default bullet points bold and enormously large?

Edit: I was able to reduce my project source to a rather comprehensible MCVE (check out this pen). To see the described behaviour you have to load the full-screen version (full) on a iOS device, save it to your home screen and call it from there. Then touch the yellow bar and try to scroll the list below.

Aides359 commented Jun 6, 2016

Is there any working workaround for this issue? (The workaround from @moll does not work in my case, the one from @noordawod does, however while the short flicker is still acceptable, the repaint causes heavy performance problems which are far from acceptable)

Two things I've noticed (testing with iPhone 5+6 on iOS 9.1 and 9.3.2):
• it only occurs when launching the page/app from the homescreen (pinned app)
• changing the device orientation (portrait -> landscape) after page load fixes the problem and everything works as expected

PS: why are the default bullet points bold and enormously large?

Edit: I was able to reduce my project source to a rather comprehensible MCVE (check out this pen). To see the described behaviour you have to load the full-screen version (full) on a iOS device, save it to your home screen and call it from there. Then touch the yellow bar and try to scroll the list below.

@Aides359

This comment has been minimized.

Show comment
Hide comment
@Aides359

Aides359 Jun 8, 2016

It seems that this issue (at least in some cases) does not occur when removing

html, body
{
    width: 100%;
    height: 100%;
}

from the CSS.

This is not a suitable solution however, since those declarations are essential for percentage scale values to work.

Aides359 commented Jun 8, 2016

It seems that this issue (at least in some cases) does not occur when removing

html, body
{
    width: 100%;
    height: 100%;
}

from the CSS.

This is not a suitable solution however, since those declarations are essential for percentage scale values to work.

@gauravksoni

This comment has been minimized.

Show comment
Hide comment
@gauravksoni

gauravksoni Apr 3, 2017

-webkit-overflow-scrolling: touch; overcomes z-index . and if we remove it then the scroll flickers. Is there any good solution of it?

-webkit-overflow-scrolling: touch; overcomes z-index . and if we remove it then the scroll flickers. Is there any good solution of it?

@noordawod

This comment has been minimized.

Show comment
Hide comment
@noordawod

noordawod Apr 7, 2017

Yeah, do like I did years ago: ditch hybrid and go native.

Yeah, do like I did years ago: ditch hybrid and go native.

@CommanderXL

This comment has been minimized.

Show comment
Hide comment
@CommanderXL

CommanderXL Sep 13, 2017

@gauravksoni Well. I choose to change some html structure to meet the demand.Becase of the mechanism of z-index.

@gauravksoni Well. I choose to change some html structure to meet the demand.Becase of the mechanism of z-index.

@Ralpharoo Ralpharoo referenced this issue in OnsenUI/OnsenUI Oct 15, 2017

Closed

iOS scrolling under modal views / masks #2220

@Ralpharoo Ralpharoo referenced this issue in OnsenUI/OnsenUI Nov 18, 2017

Closed

iOS Page Flickering #2255

@kaankucukx

This comment has been minimized.

Show comment
Hide comment
@kaankucukx

kaankucukx Jan 29, 2018

Wow, 5 years topic.

I haven't been to this since yesterday, surprisingly its weird not to face with it.

3 hours of research i come up with, overflow:hidden to outer most div-element. (i can say body) this works with the position:fixed inner element situations.

You should care all your segmented elements stack context transform - z-index properties.

Wow, 5 years topic.

I haven't been to this since yesterday, surprisingly its weird not to face with it.

3 hours of research i come up with, overflow:hidden to outer most div-element. (i can say body) this works with the position:fixed inner element situations.

You should care all your segmented elements stack context transform - z-index properties.

@studentIvan

This comment has been minimized.

Show comment
Hide comment
@studentIvan

studentIvan Feb 16, 2018

workaround by me:

  1. remove position fixed from container and it's parents
  2. block useless touchmove (unimportant)
window.addEventListener('touchmove', (touchEvent) => {
        /** touch scroll block */
        const sBlock = '.rs-infinity-scroll-block';
        const { target } = touchEvent;
        if (target && target.closest && !(target.closest(sBlock))) {
          touchEvent.preventDefault();
        }
      }, false);

studentIvan commented Feb 16, 2018

workaround by me:

  1. remove position fixed from container and it's parents
  2. block useless touchmove (unimportant)
window.addEventListener('touchmove', (touchEvent) => {
        /** touch scroll block */
        const sBlock = '.rs-infinity-scroll-block';
        const { target } = touchEvent;
        if (target && target.closest && !(target.closest(sBlock))) {
          touchEvent.preventDefault();
        }
      }, false);
@nickjohnson

This comment has been minimized.

Show comment
Hide comment
@nickjohnson

nickjohnson May 23, 2018

As many of you, I was led to this thread because of a common issue. In some cases our modal would seem locked in iOS Safari, and the body would retain the scroll touch events. From the developer console we could toggle the body's position:fixed style off and on, then the scroll would come back to our modal. This only seems to happen on some sites where our modal is triggered. We assume it must be some js or css library grabbing precedence. So we tried simulating the console method with this hack, using jQuery:

$('body').css('position','').css('position','fixed');

That didn't work, so I set a timeout on the position reset.

$('body').css('position','');
setTimeout(function(){$('body').css('position','fixed');},100);

And that did it for us. Hacky? Yes! But it works well for us. I hope this may help someone else out there. We spent way too much time on this one :(

As many of you, I was led to this thread because of a common issue. In some cases our modal would seem locked in iOS Safari, and the body would retain the scroll touch events. From the developer console we could toggle the body's position:fixed style off and on, then the scroll would come back to our modal. This only seems to happen on some sites where our modal is triggered. We assume it must be some js or css library grabbing precedence. So we tried simulating the console method with this hack, using jQuery:

$('body').css('position','').css('position','fixed');

That didn't work, so I set a timeout on the position reset.

$('body').css('position','');
setTimeout(function(){$('body').css('position','fixed');},100);

And that did it for us. Hacky? Yes! But it works well for us. I hope this may help someone else out there. We spent way too much time on this one :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment