Ionic version:
[x] 4.x
[x] 5.x
Current behavior:
ion-content is still scrollable while ion-menu is opening. This is happens only with cordova and capacitor, not in the browser.
Expected behavior:
ion-content should not be scrollable.
Steps to reproduce:
While opening a ion-menu, swipe finger up and down.
Other information:
Here you can see it: https://www.youtube.com/watch?v=K-ImPdKFoiA
Confirmed here as well, on all platforms/modes (iOS/Android/Web/etc). This happens easily and consistently and results in a VERY slow/jittery interaction for the user.
Are there any updates?
Still an issue. Seems to have gotten worse specifically in the latest chrome releases. Almost impossible to swipe open any menu without extreme lag / jank. It's almost to the point where I'd consider disabling swipe-to-open because it's just a really bad impression.
Users have been complaining our apps are slow when in reality it's just the menu opening :/
Not sure how to proceed with this as I believe it's a result of the event being captured by multiple elements.
I stumbled on this, haven't had a chance to dig in too deep yet, but could be useful for finding a solution/workaround?
Possibly related: https://github.com/w3c/pointerevents/issues/303
Eventually it is possible to disable the scroll feature of IonContent as soon as the menu gets opened.
I will create create a demo of my solution ASAP.
Awesome, thank you! I actually think I just came up with a solution as well. Does yours look something like this?
@liamdebeasi This seems to cancel the touchmove event on IonContent scrollable element.
// mainElmt is the <main> element from IonContent: <main class="inner-scroll scroll-x scroll-y" part="scroll"><slot></slot></main>
constructor(
private _rnd: Renderer2,
private _dom: DomController)
{ ... }
// Called from menu (ionWillOpen) --->
lockContent() {
this._dom.write(() => {
this._rnd.setStyle(this.mainElmt, 'pointer-events', 'none');
Timeout.fn(() => {
this._dom.write(() => {
this._rnd.removeStyle(this.mainElmt, 'pointer-events');
});
}, 0);
});
}
@lincolnthree That looks very good, I've just started to create something. Are you able to create a PR?
@BerkeAras I probably can tomorrow. Right now I've done this in a directive that attaches to every [ion-content] element automatically.
What was your solution?
I dont have a solution. I just created a new project, but I dont have something yet.
Ah :) Here's something that might help:
@Directive({
selector: 'ion-content'
})
export class IonContentDirective implements OnInit, OnDestroy {
pricate static readonly locks: IonContentStyleDirective[] = [];
private mainElmt: HTMLElement;
private styled = false;
constructor(
private _el: ElementRef,
private _rnd: Renderer2,
private _dom: DomController
) {
// Very hacky singleton. Don't look at me like that.
IonContentStyleDirective.locks.push(this);
}
static cancelContentScrollEvents() {
for (const c of IonContentStyleDirective.locks) {
c.cancelPointerEvents();
}
}
static activateContentScrollEvents() {
for (const c of IonContentStyleDirective.locks) {
c.activatePointerEvents();
}
}
cancelPointerEvents() {
console.log('cancel pointer events', this._el.nativeElement)
this._dom.write(() => {
this._rnd.setStyle(this.mainElmt, 'pointer-events', 'none');
});
}
activatePointerEvents() {
console.log('activate pointer events', this._el.nativeElement)
this._dom.write(() => {
this._rnd.removeStyle(this.mainElmt, 'pointer-events');
});
}
ngOnInit() {
}
ngOnDestroy() {
IonContentStyleDirective.locks.splice(IonContentStyleDirective.locks.indexOf(this), 1);
}
}
There may be a simpler way, but that's what I did in ~10 minutes.
I also noticed it helps to do this when the menu is being closed, as well.
I've just created a very basic version of @lincolnthree's version. This is useful for especially No-Framework Users.
@liamdebeasi Not sure my tag came through since I edited it in. Just making sure you saw it, since I believe we have a viable workaround/fix for this if you want to incorporate it.
FYI. This seems to work best when it is ALSO called on menu ionWillOpen and ionWillClose, as menus may also have content inside them that can scroll when closing.
So something like this:
_menuWillClose(side: string) {
IonContentStyleDirective.cancelContentScrollEvents();
}
_menuDidClose(side: string) {
IonContentStyleDirective.activateContentScrollEvents();
}
_menuWillOpen(side: string) {
IonContentStyleDirective.cancelContentScrollEvents();
}
_menuDidOpen(side: string) {
IonContentStyleDirective.activateContentScrollEvents();
}
As an additional aside. It seems to improve/reduce menu jitter if the ion-content::part(scroll) has touch-action: pan-y set in CSS. I believe this prevents the browser from attempting to attach horizontal (x-axis) touch events to this element in the first place.
@liamdebeasi Facepalm... 馃う I think the simplest fix is actually just to apply touch-action: pan-y to the main/scroll element in ion-content. I haven't tested in "all browsers" yet, but just this CSS change seems to resolve all the background-scrolling and jitter issues on chrome/android/and ios safari.
That said, I'm going to get back to my "day job" and let the dust settle on this one for a bit.
Most helpful comment
Confirmed here as well, on all platforms/modes (iOS/Android/Web/etc). This happens easily and consistently and results in a VERY slow/jittery interaction for the user.