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.
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
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);
});
html {
overflow: scroll;
-webkit-overflow-scrolling: touch;
}
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.