Reputation: 570
I am creating an iPhone Web Application and you are now, since iOS5, able to use position: fixed; for headers etc. etc.
Although it works, if you scroll up at the top of a page, it displays the usual gray area for a while before you can't scroll anymore
Is there a way to stop this scrolling? I've tried things like overflow: hidden; but I can't seem to find anything.
P.S. I only want the one thing to stop scrolling, I have a div named #container which I still want to have the ability to scroll.
Upvotes: 25
Views: 40640
Reputation: 221
A previous solution suggested :
document.ontouchmove = function(event){
event.preventDefault();
}
However, this also stops the scrolling for the element of interest.
In order to overcome this, the following can be done:
preventDefault
technique for the ontouchmove event, but ONLY IF, the user attempts to scroll down further.preventDefault
anymore.Here's the source code for an implementation of the above logic.
The npm package can also be downloaded for convenience (tested with vanilla JS/React on iOS mobile/desktop safari as well as Android/Desktop Chrome).
Checkout https://medium.com/jsdownunder/locking-body-scroll-for-all-devices-22def9615177 for more of an explanation of the different approaches.
Upvotes: 0
Reputation: 11
Like others suggested I wrote a quick function that bumps my scrolling div one pixel whenever it is scrolled to the top or bottom to prevent the entire page from dragging. That's fine for my scrolling div but the fixed divs on my page were still susceptible to page drag. I accidentally noticed that when I layered a fixed div on top of my scrolling div (which no longer dragged the page because of my bump function) the touch drag events were passed through the fixed div to the scrolling div underneath and that fixed div was no longer a potential page dragger. Based on that I figured it might be possible to use a full screen scrolling div in the background as the foundation for the entire page so that all dragging would be pass through and my actual elements on top will be safe. The foundation div needs to actually scroll so I placed a filler div inside of it and made it slightly larger to guarantee it scrolls. And it worked! Below is an example using this idea to prevent page dragging. Sorry if this is obvious or already posted but I didn't see this anywhere else and it really improved my web app. Please try it out and let me know if it helps.
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<style>
.myDiv {
position:absolute;
left:0;
width:100%;
color:white;
}
.myDiv.hidden {
top:0;
height:100%;
-webkit-overflow-scrolling:touch;
overflow-y:scroll;
}
.myDiv.title {
top:0;
height:30%;
background-color:#6297BC;
}
.myDiv.scroll {
bottom:0;
height:70%;
-webkit-overflow-scrolling:touch;
overflow-y:scroll;
background-color:#ADADAD;
}
</style>
<script>
function setup() {
hiddenScrollingDiv.addEventListener("scroll", preventWindowScroll);
visibleScrollingDiv.addEventListener("scroll", preventWindowScroll);
hiddenScrollingDiv.style.height=window.innerHeight;
visibleScrollingDiv.style.height=parseInt(window.innerHeight*.7)+1;
fillerDiv.style.height=window.innerHeight+2;
hiddenScrollingDiv.scrollTop=1;
visibleScrollingDiv.scrollTop=1;
}
function preventWindowScroll(evt) {
if (evt.target.scrollTop==0) evt.target.scrollTop=1;
else if (evt.target.scrollTop==(evt.target.scrollHeight-parseInt(evt.target.style.height))) evt.target.scrollTop=evt.target.scrollHeight-parseInt(evt.target.style.height)-1;
}
</script>
</head>
<body onload="setup()">
<div id="hiddenScrollingDiv" class="myDiv hidden"><div id="fillerDiv"></div></div>
<div id="visibleTitleDiv" class="myDiv title"><br><center>Non-scrolling Div</center></div>
<div id="visibleScrollingDiv" class="myDiv scroll">
<ul>
<li style="height:50%">Scrolling Div</li>
<li style="height:50%">Scrolling Div</li>
<li style="height:50%">Scrolling Div</li>
</ul>
</div>
</body>
</html>
Upvotes: 1
Reputation: 526
After reviewing several solutions, I began to create a custom solution:
http://jaridmargolin.github.io/bouncefix.js/
bouncefix.add(el)
Apply fix so that the given element no longer causes a full body elastic bounce when scrolling at its extremes.
bouncefix.remove(el)
Remove all listeners/observers responsible for fixing the full body elastic bounce.
Scrollfix was a good start, however I noticed several problems:
It uses a similar approach to that of scrollfix. The problem occurs when you are at one of the scrolling extremes. On touchstart, we look to see if we are at the top extreme or bottom extreme, adding 1px if we are at the top, and removing 1px if we are at the bottom.
Unfortunately, this trick only works if we are able to set the scrollTop value. If the content is not yet scrollable, for example, you only have 1 list item, the whole body will again scroll. Bouncefix.js will take care of all of this behind the scenes by using event delegation and checking the scrollHeight against the offsetHeight anytime touchstart is triggered. In the case that there is no scrollable content, all scrolling on the container is blocked with e.preventDefault();
Upvotes: 16
Reputation: 76968
what worked for me:
html, body, .scrollable {
overflow: auto;
-webkit-overflow-scrolling: touch;
}
plus (using jQuery...)
$(function() {
$(document).on("touchmove", function(evt) { evt.preventDefault() });
$(document).on("touchmove", ".scrollable", function(evt) { evt.stopPropagation() });
});
it's important that the evt.stopPropagation()
call is using a delegate since it's also caught on the document but cancelled at the last second.
In effect this catches all touchmove
events on the document but if the original event was bubbled up from a .scrollable
we simply stopPropagation
instead of cancelling the event.
Upvotes: 11
Reputation: 4575
Update:
This issue has been a pain for lots of people, but here is a solid solution created by bjrn:
Demo: http://rixman.net/demo/scroll/
And there's a discussion about it here: https://github.com/joelambert/ScrollFix/issues/2
This was originally posted by ryan in answer to a question of mine: Prevent touchmove default on parent but not child.
I hope that helps some people.
Original answer:
I'm actually looking into the exact same issue and I've come across this:
https://github.com/joelambert/ScrollFix
I've tried it out and it works nearly perfectly. If you copy all the code into a demo and give it a go on iOS you'll not see the grey background unless you grab the black bar and try to scroll that. However, it should be pretty easy to use the code that Ben supplied to prevent that happening ( preventDefault() ).
Hope that helps (It's definitely helped me!) will :)
Upvotes: 5
Reputation: 82257
Try putting this at the top of your JS file..
document.ontouchmove = function(event){
event.preventDefault();
}
This'll stop you being able to scroll your page at all, so you won't be able to see the 'grey area' at the top.
Source: Stop UIWebView from "bouncing" vertically?
Upvotes: 10