Prevent scrolling in a mobile browser without preventing focus entry

I use preventDefault () on the touch object in the document to prevent the page from scrolling. Unfortunately, this interferes too much. The user can no longer concentrate on typing (and open a soft keyboard). Using jQuery focus (), I can focus on typing on the touch screen. This opens a soft keyboard on iOS (most of the time), but never on Android.

Background

I have a webpage that I want to make as mobile as possible. I am only very concerned about Android and iOS, but in any form factor. I start by saying that the content on the page is the same size as the screen size. This is nice until the user places his finger on the page. I need to prevent user scrolling. The following code does this, but in slightly different ways on two operating systems.

$(document).on('touchstart', function(e) { e.preventDefault(); }); 

On iOS, this prevents scrolling by elasticity: where the user can detect the texture behind the webpage while trying to scroll the page. This feature is good for a regular web page, but in my case it distracts from UX.

On Android, it is forbidden to detect a convenient hack, which I use to hide the address bar. Android browsers start with a visible address bar, but as the user scrolls down the page, it disappears. To programmatically force the browser to hide the address bar, simply add this line of code to your function called at boot time.

 $('html, body').scrollTop(1); 

This is a hacker (but also the only) way to tell the Android browser that we have scrolled, and the address bar is no longer needed.

Without warning in the document, the Android browser will allow scrolling, and the address bar can be detected.

Thus, both operating systems have a good reason for this preventDefault () function to call every barcode in the document, but this prevents too much. Clicking on an input field does nothing. Using the jQuery focus () function call may help, but it only opens the soft keyboard on iOS, not Android.

 $('input').on('touchstart', function() { $(this).focus(); }); 

How to prevent page scrolling, but use the built-in browser function to indicate the focus on entering fields?

Note: This code

 $(document).on('touchstart', function(e) { if (e.target.nodeName !== 'INPUT') { e.preventDefault(); } }); 

is erroneous because the user can still scroll through the page while the initial touch arises from the input field.

+6
source share
3 answers

I really solved this problem in another project, forgot about it and remembered it most of the way by typing it.

The keys are just to do it on touchmove.

 $(document).on('touchmove', function(e) { e.preventDefault(); }); 

However, preventDefault on touchstart does all sorts of nice things, such as preventing the slideshow associated with saving the image. My designs also include this.

 $(document).on('touchstart', function(e) { if (e.target.nodeName !== 'INPUT') { e.preventDefault(); } }); 

If someone has suggestions for additional content or how to reformat it so that it can reach a larger audience, that would be great. I have never seen the content that I have here in one place, so I felt that it should be on SO.

+8
source

Combine the two!

 // prevent scrolling from outside of input field $(document).on('touchstart', function(e) { if (e.target.nodeName !== 'INPUT') { e.preventDefault(); } }); // prevent scrolling from within input field $(document).on('touchmove', function(e) { if (e.target.nodeName == 'INPUT') { e.preventDefault(); } }); 

This is probably not ideal either, and I am particularly concerned that the first function will prevent subsequent links, but I will leave it to others to conduct extensive tests.

0
source

A simple answer to your question: instead of using the preventDefault function, use the css-event-pointer property to disable the scroll of the element that is scrolling.

CSS for your inputs:

 input { pointer-events: auto !important; } 

touchstart event listener:

 document.body.addEventListener('touchstart', function(e) { if (e.target.nodeName === 'INPUT') { this.style.pointerEvents = 'none'; } }); 

You will need to reset the event pointer when you blur the input.

 document.body.pointerEvents = 'auto'; 

+1 Good question

0
source

Source: https://habr.com/ru/post/925723/


All Articles