42

I am having some issues with a scrollable div on iOS. When trying to scroll by touching outside an input, it scrolls ok without any problem but when I try to scroll and I touch an input to start scrolling (there are a lot of chances that it happens because it is a div with a lot of inputs) it scrolls the whole window instead scrolling the div. I don't have that problem either in desktop or Android. I found a similar question (iOS HTML Input Tag Stops Scrolling in Scrollable Element) but it doesn't have any answer either. While I don't find any good solution, I decided to prevent the event touchmove when the user touches an input, but it is not exactly what I want.

Maybe someone already faced this problem and can help. I would really appreciate it, thanks in advance.

Community
  • 1
  • 1
Mindastic
  • 4,023
  • 3
  • 19
  • 20
  • I am facing the same issue. See here http://stackoverflow.com/questions/26784118/scrolling-on-ios-device-finger-input-tag/28862015#28862015 . I have provided details there or what was causing my issue. Can you see if it is the same for you? – corbin Mar 04 '15 at 19:23
  • Please acept answer if it's correct for you – mjimcua Nov 19 '19 at 09:44

3 Answers3

43

To get native momentum scrolling on iOS 5+, you'll need:

div {
  overflow: scroll;
  -webkit-overflow-scrolling: touch;
}

Source: Overflow

Maybe you also need:

div > * {
    -webkit-transform: translateZ(0px);
}

Source: Similar question in Stack Overflow

Source 2: Another similar question

Community
  • 1
  • 1
mjimcua
  • 2,781
  • 3
  • 27
  • 47
  • 6
    This has nothing to do with what OP was asking. Problem is that if you initiate drag-scroll from an input such as a textbox (which triggers touchmove event), the entire document scrolls instead of the inner scrollable area. – nothingisnecessary Mar 29 '16 at 18:05
  • 9
    this works but instead of putting it in div. Put it in the html or body. `html { overflow: scroll; -webkit-overflow-scrolling: touch;}` – Mark Anthony Uy Aug 24 '16 at 10:21
  • 2
    god damn IOS - should have found this earlier! – Stender Nov 23 '17 at 11:29
  • 1
    This should be the accepted answer as this is the correct way to "fix" this problem without adversely impacting the usability of a page. – Daniel Bonnell Jun 15 '18 at 19:51
7

This stuff made me crazy too, after testing everything, I found the following answer from Thomas Bachem here working and made it simpler in jquery.

Just add a class scrollFix to the inputs and you are ready to go. (or directly apply that js to any inputs/textarea 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);
});
Community
  • 1
  • 1
Dotgreg
  • 333
  • 3
  • 9
  • Been hunting for hours for a fix for the Iphone IOS9 and this worked perfectly. Cheers. – JDavies Oct 27 '16 at 11:10
  • Tried using this with Ionic (hybrid web wrapper). It's a bit wonky when it comes to ionic. if I tap into an input, It scrolls the page to the right spot and opens the keyboard, but it doesn't actually focus on the input. Good start here for me at least. – ntgCleaner Feb 10 '17 at 14:41
  • 1
    this works for scrolling, but makes the form fields not selectable/ so you cant fill out the form. – md123 Sep 18 '18 at 12:33
0

Hacky workaround, but by doing this I was able to make scrolling work even on form inputs. The JS forces a reflow in the rendering engine, which is where the bug in iOS8 Safari lies. Changing the height to auto also improved scrolling when focused on a form element, since scrolling is forcibly handled by the browser when focused.

Markup:

<div class="modal-backdrop-container">
  <div class="modal-backdrop">
    <div class="modal> <!-- Content --> </div>
  </div>
</div>

CSS:

.modal-backdrop-container {
    z-index: 10;
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    height: 100%;
}
.modal-backdrop {
    z-index: 10;
    height: 100%;
    background-color: rgba(255,255,255,0.5);
    overflow: auto;
    overflow-x: hidden;
    overflow-y: scroll;
    -webkit-overflow-scrolling: touch;
}
.modal {
    position: relative;
    width: 400px;
    max-width: 100%;
    margin: auto;
    background-color: white;
}

JS:

// reflow when changing input focus
        $modalInputs = $('.modal').find(':input');
        modalInputs.on('focus', function() {
            var offsetHeight = modal.$backdrop[0].offsetHeight;
            modal.$backdropContainer.css({
                'height': 'auto'
            });
        });
        modalInputs.on('blur', function() {
            var offsetHeight = modal.$backdrop[0].offsetHeight;
            modal.$backdropContainer.css({
                'height': ''
            });
        });

Not sure of the var offsetHeight = modal.$backdrop[0].offsetHeight; line is needed, since both this and changing the height value should force a reflow.

Alex K
  • 14,893
  • 4
  • 31
  • 32