Svelte: Non-scrollable element with `bind:clientHeight` and `z-index` (iOS 14)

Created on 23 Sep 2020  路  6Comments  路  Source: sveltejs/svelte

Describe the bug
Using bind:clientHeight on an element with z-index prevents that element's contents from being scrolled on iOS 14. On previous versions of iOS and on other OS's, this bug does not appear.

The iframe added by add_resize_listener specifies a z-index that is 1 less than the element's z-index, as well as pointer-events: none. Perhaps this is connected...

Logs
N/A

To Reproduce
I've made a small REPL with a simplified version of the environment this occurred in for us at Playpilot (in our top navigation): https://svelte.dev/repl/695f80e7948e4575b6e1f0fd536716fb?version=3.26.0

Expected behavior
The z-index should not make a difference to whether you can scroll or not (as on other platforms/OS versions).

Information about your Svelte project:

  • Your browser and the version: Safari, Chrome, Firefox (tested various browsers)
  • Your operating system: iOS 14 (it works fine for previous versions of iOS, as well as other OS's)

  • Svelte version: 3.26.0

  • Bundler: Rollup

Severity
Just a bit annoying. It was quite a mystery in the beginning, but once we found the issue, solving it was relatively simple: we just wrapped the content of the element in a div with position: relative; plus the same z-index as the element itself and it works fine. Of course we would like to remove this once the bug is fixed, but for now this is not pressing.

pending clarification

All 6 comments

Just ran into this same exact issue as well...

For some reason, in my specific case, this is also blocking scroll in Safari 14 on macOS Catalina.

The workaround I'm considering is to use an empty div inside the resized element to measure width.

Simple enough to work around I suppose, but pretty unexpected behavior...

(Also, this looks like a duplicate of #5241...)

I'm confused because the other issue says that it affects iOS12 and below, and this issue says iOS 14, and works fine below that. Not sure how this would be the same issue?

@antony Yeah, my apologies, I'm a bit confused as well...

Both issues appear to be caused by to the iframe's z-index layering above sibling elements, and both issues involve Safari.

In my specific case, I'm observing the behavior on macOS Catalina in Safari 14 as well as the iPhone simulator in Xcode 12.2.

I've confirmed that setting the z-index of the iframe to -1 (as suggested in #5241) does fix this problem.

I'm having trouble replicating the behavior in the REPL however... Hope to have more information soon.

FWIW, It does appear that the iframe z-index indeed used to be set to -1 before this diff...

Not sure why it changed there, do you have context around that @mrkishi / @Conduitry?

Okay, after much frustration, I've figured out how to repro this.

Steps I took to verify:

  • Download @jhwheeler's original REPL example posted above and run it locally.
  • Load the app in Safari and make the browser viewport skinnier than the nav list. (Dock the web inspector to do this.)
  • Using the trackpad only, try to scroll the list horizontally - it won't let you and appear to be "stuck".
  • In the web inspector, change the z-index of the <iframe> from 4 to -1.
  • Try to scroll the list horizontally again using the trackpad only - now it works!

ezgif-6-aa0599bcf9bc

Again, I'm observing this behavior in Safari 14.0.1 on macOS Catalina 10.15.7. What's even stranger is that, if you have "Show scroll bars: Always" in System Preferences, you can actually still use the scrollbar to scroll, but not the trackpad.

I believe this issue at its core is the same issue that @crotru identified in #5241. As he put it:

This seems weird to have a correlation between parent and children z-indexes.
In the end we have something like this :

holder : z-index: 3
|- element : z-index: auto
|- element : z-index: auto
|- iframe : z-index: 2

No matter what z-index is on the holder, a positive z-index on the iframe will always be above auto ones

So the original z-index: -1 solution prevented the invisible iframe from overlaying everything inside the holder element.

Same issue indeed that #5241 indeed.

To put it in another words :


iframe can't take pointer-events: none statement in safari (I guess for security reason)
So when the iframe is on top of any content, iframe receives the scroll event, content does not. (scrollbar you see with "Show scroll bars: always" are the ones of the content, so they indeed work).


Z-index are scoped to their dom-level.
ie. if a parent has its z-index (and its position) set, there is absolutely no correlation between parents and child z-indexes :

so in this case

  • parent1 : auto
  • |- children : z-index: 100
  • parent2 : z-index: 2

children will be over parent2

but in this case :

  • parent1 : z-index: 1
  • |- children : z-index: 100
  • parent2 : z-index: 2

parent2 will be above children

So having the Iframe (which is a children) to have a z-index value of [parent z-index minus 1] doesn't do anything good 馃檪


z-index: -1 on the other hand forces the children to display below the first child.
So that's why it worked fine before the diff
(also if it gets set back as this, pointer-events statement can be removed)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

AntoninBeaufort picture AntoninBeaufort  路  3Comments

Rich-Harris picture Rich-Harris  路  3Comments

robnagler picture robnagler  路  3Comments

1u0n picture 1u0n  路  3Comments

sskyy picture sskyy  路  3Comments