How to avoid scroll leakage when scrolling a fixed menu on touch devices

When I was working as a frontend developer for a retailer, developing a web shop, I stumbled upon a tricky problem.
My customer was pretty picky, and didn’t want any edge case flaws.

We had a fixed (or sticky of you supported that) navigation that was always attached from top to bottom.
The nav did only cover about 2/3 of the screen’s width though, so when the user reached the end of the content,
you could see how the background started scrolling instead. The scrolling was leaking upwards to the body.

Note: This has been fixed in iOS 8 but is still a valid defect in iOS 7 and below, as well as Android.

To fix this you need to listen to the touchstart and touchmove events and check where you are in the content and which direction you are scrolling.
When you have reached the bottom of the container and the direction you are scrolling is downwards we simple use preventDefault() to stop the scroll event,
to avoid it leaking to the body content.

The wrapper covers the whole screen so when user scrolls outside of the menu, it will still scroll the menu.
It’s using a semi-transparent color to appear modular.

The content covers the width of the menu.

I also need to mention that this solution is not perfect on Android devices.
If you scroll almost all the way to the bottom, and then scrolling past the bottom without lifting you finger, the scroll will leak with the following error message in the console:

Ignored attempt to cancel a touchmove event with cancelable=false, for example because scrolling is in progress and cannot be interrupted.

A way around this, is to implement a custom scroll like iScroll, this is what we ended up doing, although not optimal, of course.

Here’s the JavaScript fixing the problem, I have explained the code with comments inside the script itself.

Try it out on your device:
https://jonwallsten.com/codepen-examples/example1/

See the Pen RNMrmP by Jon WAllsten (@JonWallsten) on CodePen.