vuetifyjs / vuetify

🐉 Vue Component Framework
https://vuetifyjs.com
MIT License
39.67k stars 6.95k forks source link

[Bug Report] IOS: when long dialog scroll, background should not scroll issue #3875

Closed Neo888888 closed 2 years ago

Neo888888 commented 6 years ago

Versions and Environment

Vuetify: 1.0.15 Vue: 2.5.13 Browsers: Safari 11.1 OS: iOS

Steps to reproduce

show a dialog with very long height. (NOT a full screen dialog)

Expected Behavior

the background should not scroll on IOS

Actual Behavior

the background scrolls sometimes

Reproduction Link

https://github.com/

Other comments

To fix this issue:

beforeCreate Dialog
    document.getElementsByTagName("body")[0].className="noscroll";

beforeDestroy Dialog
    document.body.removeAttribute("class","noscroll");

STYLUS: .noscroll position: fixed overflow-x: hidden overflow-y: hidden

johnleider commented 6 years ago

Please follow the guidelines on how to report an issue. In particular, provide an example on www.jsfiddle.net (or a similar service) that reproduces the problem. If necessary, create a repository for us to clone with a minimal reproduction. repositories of actual projects will generally not be accepted .

Thank you.

Neo888888 commented 6 years ago

https://vuetifyjs.com/en/components/dialogs The last example "Overflowed" dialog would reproduce this issue on IOS safari.

chewy94 commented 6 years ago

I have confirmed on iOS 11 that this does happen in safari. It seems to occur when the browser items like the url bar and forward/back buttons appear. Happens on Chrome iOS as well. I think it has something to deal with the dialog reaching the top or bottom of its content and therefore scrolling/focusing the actual page below it to keep scrolling

Neo888888 commented 6 years ago

Here is the way how I "fix" it:

beforeCreate Dialog document.getElementsByTagName("body")[0].className="noscroll";

beforeDestroy Dialog document.body.removeAttribute("class","noscroll"); STYLUS:

.noscroll
  position: fixed
  overflow-x: hidden
  overflow-y: hidden
KaelWD commented 6 years ago

The dialog is supposed to disable overflow when it's opened: https://github.com/vuetifyjs/vuetify/blob/dc9b296533debb5b2e493164149146986eb379f7/src/mixins/overlayable.js#L178-L181

I don't know how we can fix that if safari is somehow ignoring it.

Neo888888 commented 6 years ago

The key point: The class needs to be added to the "body" tag. And maybe we need the "position: fixed" in the style.

Neo888888 commented 6 years ago

stylus: .noscroll position: fixed overflow-x: hidden overflow-y: hidden

code: hideScroll: function hideScroll() { if (this.$vuetify.breakpoint.smAndDown) { document.documentElement.classList.add('noscroll'); document.getElementsByTagName("body")[0].classList.add('noscroll'); } else { window.addEventListener('wheel', this.scrollListener); window.addEventListener('keydown', this.scrollListener); } }, showScroll: function showScroll() { document.documentElement.classList.remove('noscroll'); document.getElementsByTagName("body")[0].classList.remove('noscroll'); window.removeEventListener('wheel', this.scrollListener); window.removeEventListener('keydown', this.scrollListener); }

oscar-gardiazabal commented 5 years ago

It happens to me on iOS when dialog opens over stepper. Maybe 'overflow-y-hidden' could be in all outside dom elements while dialog is open? The attribute 'attach' should block scroll of attached element?

TheRatG commented 5 years ago

It works for me

https://stackoverflow.com/questions/26046373/iframe-scrolling-ios-8

<div style="overflow:auto;-webkit-overflow-scrolling:touch">
    <iframe style="width:100%;height:600px" src="www.iframe.com"></iframe>
</div>
efriedli commented 5 years ago

Can also the issue as diagnosed by @Neo888888 and @chewy94, issue is specific to v-dialog on iOS+Safari and applying the below on v-dialog should fix it:

style="overflow:auto;-webkit-overflow-scrolling:touch"

tsh356 commented 5 years ago

I have confirmed on iOS 11 that this does happen in safari. It seems to occur when the browser items like the url bar and forward/back buttons appear. Happens on Chrome iOS as well. I think it has something to deal with the dialog reaching the top or bottom of its content and therefore scrolling/focusing the actual page below it to keep scrolling

To expand on this, regarding the Dialog Form example, scrolling in the dialog works fine if you touch exactly between two v-text-fields, but when you touch on any v-text-field, the actual page focuses and scrolling occurs there instead of in the dialog.

Is there any way to increase the priority of this bug? This is likely effecting a large percentage of the user base since it occurs across all iOS devices. I haven't been able to get any of the proposed solutions above to work properly.

Pchianes commented 5 years ago

Hello,

Any news about this issue ? I'm having the same problem and the ticket is open since a while now. It could be great if you can give us a dead line for solution

Thank you in advance

KaelWD commented 5 years ago

@Pchianes Buy me an iphone and I'll have a look

iKoru commented 5 years ago

Hello, Any news here?

natxocc commented 5 years ago

I have the same problem with IOS 12 on my Iphone 5 SE.

daviesdoclc commented 5 years ago

They closed my similar issue (https://github.com/vuetifyjs/vuetify/issues/6353), so I thought I'd comment over here. v-toolbar and v-bottom-navbar also cause scrolling of the content area if those components are "fixed" . In that case there is no opportunity to turn off scrolling on the body because they don't become active. They are always active.

I just wonder what the root problem is? What did Apple change that is causing this to happen? I had to resolve this in a similar way in a non-Vue/Vuetify app as well. Seems very janky.

Oh... and maybe I missed it, but the navigation drawer does the same thing too.

In fact, you can go to vuetifyjs.com on your iOS browser and the overlay area is scrollable when the menu drawer is open.

KaelWD commented 5 years ago

Can some more of you iOS guys check if #6280 solves the problem?

@daviesdoclc Scrolling on toolbars and bottom nav is meant to happen, your issue was closed because the navigation drawer uses the same mechanism as dialogs to prevent scroll on the body. As I noted in my previous comment, we do set overflow to hidden on mobile, so I have no idea why this is happening.

daviesdoclc commented 5 years ago

Hmmmm. Having the content area scroll when I drag my finger off a navbar item (because I decided not to select it) does not seem like very good behavior. Native iOS and Android do not behave this way. I decided to move my toolbar and navbar outside the content area instead of being fixed inside of it. This fixes my issue because now the drags in those areas don’t bleed through.

KaelWD commented 5 years ago

2132

daviesdoclc commented 5 years ago

Maybe a video will help describe the issue with the toolbar and navbar. Take a look at this.

As you can see, dragging in the toolbar and navbar both scroll the content. This is not how a native app would behave. This is using v-content and fixed toolbar and navbar.

<template>
    <div>
        <v-toolbar color="white" app>
            <v-btn icon>
                <v-icon>menu</v-icon>
            </v-btn>
            <v-toolbar-title>Title</v-toolbar-title>
        </v-toolbar>
        <v-content>
            <div class="box red"></div>
            <div class="box blue"></div>
            <div class="box red"></div>
            <div class="box blue"></div>
        </v-content>
        <v-bottom-nav value="true" app>
            <v-btn color="#ae2573" flat>
                HOME
                <v-icon>home</v-icon>
            </v-btn>
        </v-bottom-nav>
    </div>
</template>

<style scoped lang="scss">
    .box {
        margin: 20px;
        width: 90%;
        height: 200px;
        display: block;
    }
    .red {
        background-color: red;
    }
    .blue {
        background-color: blue;
    }
</style>

If I don't use v-content and a fixed toolbar or navbar, but instead create a flex container where the content area takes over the remaining space then it works.

<template>
    <div class="app">
        <v-toolbar color="white">
            <v-btn icon>
                <v-icon>menu</v-icon>
            </v-btn>
            <v-toolbar-title>Title</v-toolbar-title>
        </v-toolbar>
        <div class="content">
            <div class="box red"></div>
            <div class="box blue"></div>
            <div class="box red"></div>
            <div class="box blue"></div>
        </div>
        <v-bottom-nav value="true">
            <v-btn color="#ae2573" flat>
                HOME
                <v-icon>home</v-icon>
            </v-btn>
        </v-bottom-nav>
    </div>
</template>

<style scoped lang="scss">
    .app {
        height: 100vh;
        display: flex;
        flex-direction: column;
    }
    .content {
        flex: 1;
        overflow-y: scroll;
    }
    .box {
        margin: 20px;
        width: 90%;
        height: 200px;
        display: block;
    }
    .red {
        background-color: red;
    }
    .blue {
        background-color: blue;
    }
</style>

However, now I feel like I've deviated from the Vuetify preferred way of overlaying the toolbar and navbar (although I'm not sure v-content or v-container are requirements like v-app is).

Hopefully this help. I appreciate the fix for dialogs, drawers, etc. that are overlays. That will be a big help. Ideally it would be good to understand why these events bleed through. BTW... my video was on Chrome on the desktop. So it's not Apple specific nor touch specific.

KaelWD commented 5 years ago

This is not how a native app would behave

It's how a web app does (because the scroll is on the body), #2132 is for that and is an entirely separate issue.

egeersoz commented 5 years ago

This bug is seriously affecting usability for our users, and it's so bad that our PM wants us to ditch Vuetify. I'd rather stay with Vuetify (it's overall very well-designed and engineered) so I figured I'd chime in and see if it can be bumped up in priority.

KaelWD commented 5 years ago

@egeersoz @tsh356 I'll merge #6280 if you can confirm that it works. There's a staging deployment here.

egeersoz commented 5 years ago

Following neo888888's comment above I went to the Dialogs page of the staging site on my iPhone and tested the Overflowed example, but it continues to scroll the background when you scroll up and down inside the dialog.

(Note that it's not just dialogs that are affected. The issue also affects navigation drawers.)

daviesdoclc commented 5 years ago

And bottom sheets. I think anything with an overlay is suppose to be setting the no scroll on the body.

janholas commented 5 years ago

The #6280 fix is not working for me either (iPhone iOS 12.x)

daviesdoclc commented 5 years ago

I have a video of an app I built that demonstrates the issue. This is recorded directly on the iOS device.

https://www.dropbox.com/s/6emopdr6pkpxbv1/ScreenRecording_02-22-2019%2009-27-33.MP4?dl=0

The v-content area is scrollable when dragging in the toolbar, the navbar, the drawer, the bottom sheet, and the overlay. This is using Vuetify 1.5.2.

I'd like to try this with the patch, but for the life of me I can't figure out how to npm install it from the repo. Any help? Once I can build the actual app with it I can do a better test of this.

zachzoup commented 5 years ago

6280 doesn't fix the issue for me.

solojuve1897 commented 5 years ago

Thanks to @daviesdoclc for writing about this issue. I suspected it was something with Vuetify when my fixed v-bottom-nav was behaving strangely on my iOS-device. This issue has never occured on my Android-devices. My problem manifests by the fact that sometimes, quite randomly, the buttons in my v-bottom-nav stops reacting to normal touch. If I am very sensitive and touch the top of the icons it will (sometimes) work when it is in this state. If I then play around with the app it will eventually work again as normal, and then eventually happen again. I haven't been able to pin-point how, why and when the issue exactly occurs. The issue explained by @daviesdoclc is closest to describing my problem. I'm still testing to understand more and will write again if I discover anything interesting.

I have the html build as follows with four main elements:

KaelWD commented 5 years ago

@egeersoz @blackfox00 thanks

@daviesdoclc it's a website, that's normal. The only bit that's a bug is when there's an overlay showing. You probably want #2132 for the toolbar thing.

@solojuve1897 safari blocks the bottom 44px of every page for its own menu bar.

kwindo commented 5 years ago

Hi guys, any update on this? Dialogs on the Components page (https://next.vuetifyjs.com/en/components/dialogs) which have content higher than the window all have scrolling issues on iOS. I tried fixes all afternoon and was unsuccessful. It kind of makes the dialogs unusable for a lot of cases.

BTW: This issue does not only happen on Safari. Chrome on iOS does the same.

egeersoz commented 5 years ago

Agreed, our app is mobile-first and this issue holding up a major release for us.

We, too, have tried all kinds of tricks and haven't been successful.

solojuve1897 commented 5 years ago

Yes. This is very bad. I'm patient though, but when Ionic is completely Vue.js-ready I will sit down and think which framework to switch to for current and future applications. By then Vuetify 2 should be out and Quasar will be another contender. Mobile-first - focus on iOS and Android - will be the top priority. Vuetify today lacks alot on that department.

kwindo commented 5 years ago

I managed to make the body scrolling by adding overflow: hidden and position: fixed to the body css when dialog= true but it still keeps scrolling in the dialog not fluent and makes the body scroll to the top of the page which is not user-friendly.

I tried finding JS fixes outside of vuetify but none of them seem to work. I'm unsure if this is a Vuetify issue. It seems the Bootstrap Modal has the same problem (check "Scrolling long content"): https://getbootstrap.com/docs/4.0/components/modal/

egeersoz commented 5 years ago

It may not be a Vuetify issue, but IMO we should keep this open since it affects lots of people and has a high negative impact on UX. Maybe someone will find a fix or a hack and post it here.

kwindo commented 5 years ago

Could it be the people at Quasar found a solution? https://quasar-framework.org/quasar-play/apple/index.html#/showcase/popups/modal

It seems their modal "With Modal Layout" scrolls fluently. The others ("Basic" and "Basic with Events") seem to not scroll the body but are also not very fluent.

kwindo commented 5 years ago

I talked to some-front end developers at my work and they verified it is a known iOS issue.

One solution could be:

  1. Remember the scroll position
  2. Set the body to overflow:hidden and position:fixed when the dialog is showing (dialog=true)
  3. When dialog=false: remove the overflow and position from the body and scroll to the remembered scroll position

This is rather hacky and will probably not make the scrolling in the dialog nice and fluent.

Another possible solution is to inject the dialog in an already existing wrapper which is already position fixed. This is based on the idea that iOS has a problem handeling programatically changes in position values combined with injected elements which are also position fixed. It's a theory, not even tried.

When I have the time I’d like to investigate how Quasar made their modal work but I only use Vuetify for private projects. It might be that I will not have the time before coming weekend.

KaelWD commented 5 years ago

@kwindo can you try these one at a time for me?

.overflow-y-hidden body {
  overflow-y: hidden
}
.overflow-y-hidden {
  position: fixed
}
namba-hrk commented 5 years ago

@KaelWD In that case the background will be fixed at the top (´・ω・`)

KaelWD commented 5 years ago

Yeah I know, just exploring options. Does the first one do the same thing?

daviesdoclc commented 5 years ago

My experience has been that this has to do with "-webkit-overflow-scrolling: touch". If you set this to "auto" while the dialog is up, then things work as they should.

I have a codepen that demonstrates this: https://codepen.io/funkyvisions/pen/JzNPbJ

Tap on a first BLUE box for a non-scrollable dialog. Tap on the first RED box for a scrollable dialog. Tap on the first GREEN box to see the broken scrolling behavior (it doesn't apply the class).

I have a noscroll class I apply when the dialog is up.

-webkit-overflow-scrolling: touch is a class you apply to get smooth (and bouncy) scrolling on an iOS device. Without it, scrolling is linear and acts like Android.

kwindo commented 5 years ago

Hi @daviesdoclc , I tried your pen and on my iPhone it does not scroll smoothly. The body in your pen does not scroll but when I try to do the same thing in my project the body does scroll in the background. The "noscroll" class with "-webkit-overflow-scrolling: auto !important" has no effect.

kwindo commented 5 years ago

@KaelWD Your suggested CSS behaves as expected. It stops the body from scrolling in the background but fixes it on top. Scrolling in the dialog is not smooth.

kwindo commented 5 years ago

Could you guys take a look at this: https://codepen.io/kimsanka/pen/XGexJy

It's based on @daviesdoclc 's pen on which I basically just commented out some stuff.

I added a toolbar and used a full screen dialog because my application needs one but even then it scroll smooth on my iPhone and keeps the body fixed.

It's a bit hard to believe the solution is this simple so I assume I'm overlooking something.

KaelWD commented 5 years ago

Eyes on https://vuetifyjscom-dnwzaqmfio.now.sh/components/dialogs please

daviesdoclc commented 5 years ago

@KaelWD looks good, except for fullscreen resetting the scroll position to the top.

daviesdoclc commented 5 years ago

After looking at the diffs however... I wonder how this is going to work for those of us not using a scrollable body, but instead a scrollable child div confined to the viewport bounds?

KaelWD commented 5 years ago

that already isn't affected afaik

daviesdoclc commented 5 years ago

Hmmmm... my demo does https://codepen.io/funkyvisions/pen/JzNPbJ. It has a container bound to a height of 100vh and scrollable. It's how my app is laid out currently. Or are you saying that is fixed in a commit I don't have on codepen yet?

egeersoz commented 5 years ago

@KaelWD's link seems to work fine for me on iOS 12.1.