防止在移动浏览器上滚动,而不会阻止输入聚焦

我在文档的touchstart上使用preventDefault()以防止在页面上滚动。 不幸的是,这防止了太多。 用户无法再将焦点放在输入上(并打开软键盘)。 使用jQuery focus(),我可以将焦点放在touchstart上的输入上。 这会在iOS上打开软键盘(大部分时间),但从不在Android上打开。

背景

我有一个网页,我想尽可能多的移动应用程序。 我只关心Android和iOS,但任何forms因素。 我首先使页面中的内容与屏幕大小完全相同。 这很好,直到用户将手指放在页面上。 我需要阻止用户滚动。 以下代码完成了此操作,但在两个操作系统上的方式略有不同。

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

在iOS上,这可以防止弹性滚动:用户可以通过尝试滚动页面来显示网页后面的纹理。 这个function很适合常规网页,但在我的情况下,它会降低用户体验。

在Android上,防止我用来隐藏地址栏的方便黑客的启示。 Android浏览器以可见的地址栏开头,但当用户向下滚动页面时,它会消失。 要以编程方式强制浏览器隐藏地址栏,只需将此行代码添加到您在load时调用的函数中。

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

这是告诉Android浏览器我们已经滚动的hacky(但也是唯一的)方式,并且不再需要地址栏。

如果没有文件上的preventDefault,Android浏览器将允许滚动并显示地址栏。

因此,两个操作系统都有充分的理由在文档的每个touchstart上调用preventDefault(),但它可以防止太多。 点击输入字段不起作用。 使用jQuery focus()调用可以提供帮助,但只能打开iOS上的软键盘,而不是Android。

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

如何阻止页面滚动,但使用浏览器本机function将焦点放在输入字段上?

注意:此代码

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

因为用户仍然可以滚动页面是有缺陷的,只要初始触摸源自输入字段内。

我实际上在另一个项目中解决了这个问题,忘记了它,并且通过输入它来记住它的大部分内容。

他们的关键是在touchmove上做它。

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

但是,touchstart上的preventDefault会执行各种不错的操作,例如在启用手势的幻灯片中阻止图像保存菜单。 我的项目也包括这个。

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

如果有人对其他内容有一些建议或如何重新格式化,以便它可以达到更好的观众。 我从来没有在一个地方看到过这里的内容,所以我觉得它需要在SO上。

结合两个!

 // 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(); } }); 

这可能也不完美,我特别担心第一个函数会阻止以下链接,但我会留给其他人做广泛的测试。

你的问题的简单答案是不要使用“preventDefault”而是使用pointer-events css属性来禁用滚动元素的滚动。

您输入的CSS:

 input { pointer-events: auto !important; } 

touchstart事件监听器:

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

模糊输入时,您需要重置指针事件。

 document.body.pointerEvents = 'auto'; 

+1好问题