iOS/WebKit: touchmove/touchstart not working on input & textarea

10,919

Solution 1

I think I've found a great workaround for this issue using the "pointer-events" CSS property:

function setTextareaPointerEvents(value) {
    var nodes = document.getElementsByTagName('textarea');
    for(var i = 0; i < nodes.length; i++) {
        nodes[i].style.pointerEvents = value;
    }
}

document.addEventListener('DOMContentLoaded', function() {
    setTextareaPointerEvents('none');
});

document.addEventListener('touchstart', function() {
    setTextareaPointerEvents('auto');
});

document.addEventListener('touchmove', function(e) {
    e.preventDefault();
    setTextareaPointerEvents('none');
});

document.addEventListener('touchend', function() {
    setTimeout(function() {
        setTextareaPointerEvents('none');
    }, 0);
});

This will make Mobile Safari on iOS (others not tested so far) ignore the textareas for scrolling but allows to set focus etc. as usual.

Solution 2

the Thomas Bachem answer is the one!

I rewrote it in jQuery. Just add a class scrollFix to your desired inputs and you are ready to go. Or attach the event handlers to all inputs and textareas using $('input, textarea').

Now when you touch and scroll on an input on iOS 8+, the input get all its pointer-events disabled (including the problematic behavior). Those pointer-events are enabled when we detect a simple touch.

$('.scrollFix').css("pointer-events","none");

$('body').on('touchstart', function(e) {
    $('.scrollFix').css("pointer-events","auto");
});
$('body').on('touchmove', function(e) {
    $('.scrollFix').css("pointer-events","none");
});
$('body').on('touchend', function(e) {
    setTimeout(function() {
        $('.scrollFix').css("pointer-events", "none");
    },0);
});
Share:
10,919
Louis B.
Author by

Louis B.

freelance web developer working out of zurich, switzerland mobweb.ch mobweb.ch/cv/en [email protected]

Updated on July 24, 2022

Comments

  • Louis B.
    Louis B. over 1 year

    I have an IOS Web App that can't be scrolled. For that reason I want to deactivate scrolling. To do this, I use an element's ontouchmove attribute and have it call a function that uses element.preventDefault. However, I am unable to detect any touching event when it starts on a textarea or input element, even when the element is disabled! I have also tried binding the touchmove or touchstart event to these elements via JavaScript's addEventlistener, without success!

    And here's my JavaScript:

    function onBodyLoad() {
    
     document.addEventListener( "touchstart", doNotScroll, true );
     document.addEventListener( "touchmove", doNotScroll, true );
    
    }
    
    function doNotScroll( event ) {
    
     event.preventDefault();
     event.stopPropagation();
    
    }
    

    Thanks for any help!

  • nothingisnecessary
    nothingisnecessary about 8 years
    My hero! Works on Safari and Chrome for iPad.
  • Bobe
    Bobe almost 7 years
    Is this still a valid solution? I used Dotgreg's jQuery implementation and while it allows you to scroll, you cannot focus the inputs. Bear in mind the form in question is in a Fancybox v2 lightbox, just to add to the misery. Tested this on a 6 Plus running iOS 10 and on BrowserStack on a 7 with iOS10.
  • Daniel Bonnell
    Daniel Bonnell almost 6 years
    This solution works only in the sense that it allows you to tap an input and scroll, however it makes it impossible to focus the input, which sort of defeats the purpose. The correct solution to preserve expected behavior (i.e. ability to start a scroll even on an input element and still focus the input element) is to add -webkit-overflow-scrolling: touch; to your html or body tag. See here for more