Skip to content

Instantly share code, notes, and snippets.

@mattsahr
Created November 17, 2011 02:47
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save mattsahr/1372229 to your computer and use it in GitHub Desktop.
Save mattsahr/1372229 to your computer and use it in GitHub Desktop.
IOS Webkit - native internal scroll - a fix for the document page-top-bounce
<!DOCTYPE html>
<html>
<!-- NOTES
Demo - uses IOS native scroll available in IOS5, but sidestep the document-bounce behavior. Tested on iPad 1, using IOS 5.1.
This approach uses a set of 3 nested divs.
OuterDiv -- fixed height, width, overflow-scrolling: touch;
MiddleDiv -- fixed height width, overflow-scrolling: touch; fits inside OuterDiv
InnerDiv -- fixed height width, bigger than MiddleDiv, so it kicks in the overflow behavior
This particular example does the triple-nested trick twice.
The inner 3-wrapper-set uses no javascript
(height and width are explicit CSS declarations).
The outside 3-wrapper-set uses javascript to fetch
the document height, so that it can be full-window-size.
This approach allows native internal scrolls AND reaps
the benefits of killing page-bounce for the overall document.
-->
<head>
<meta charset="utf-8" />
<title>ios webkit native scroll test</title>
<style>
body,ul,li { padding:0; margin:0; border:0; }
body { font-family: Verdana, Helvetica, Arial, sans-serif; }
#divHead { top:0; }
#divFoot { bottom:0; }
#divHead, #divFoot {
position:fixed;
width:100%;
z-index:2;
left:0;
background-color:#c27b00;
font-size:20px;
text-align:center;
color:#f3f3f3;
font-weight:bold;
line-height:45px;
height:48px;
padding:0;
}
#pageOuter, #pageMiddle {
position:absolute;
width:100%;
top:0px;
left:0px;
padding:0px;
-webkit-overflow-scrolling: touch;
overflow:auto;
}
#pageInner {
position:absolute;
width:100%;
top:0px;
left:0px;
padding:0px;
}
#divOuter {
padding:10px;
border: 2px solid #0055bb;
position:absolute;
top:60px;
left:30px;
height:500px;
width: 400px;
-webkit-overflow-scrolling: touch;
overflow:auto;
background:#ffffff;
}
#divMiddle {
z-index:1;
width:100%;
border: solid 2px #aa8800;
position:absolute;
height:500px;
width: 400px;
background:#ffffff;
-webkit-overflow-scrolling: touch;
overflow:auto;
}
#divInner {
position:absolute;
z-index:1;
top:0;
padding:0;
width: 900px;
}
ul {
list-style:none;
padding:0;
margin:0;
width:100%;
text-align:left;
}
ul li {
padding:0 10px 0px 40px;
height:120px;
line-height:120px;
border-bottom:1px solid #ccc;
border-top:1px solid #fff;
background-color:#fafafa;
font-size:26px;
}
</style>
</head>
<body>
<div id="divHead">
Web App Template
</div>
<div id="pageOuter">
<div id="pageMiddle">
<div id="pageInner">
<div id="divOuter">
<div id="divMiddle">
<div id="divInner">
<ul>
<li> v9 ... somewhat random filler random somewhat filler </li>
<li>More Stuff somewhat random filler som random filler </li>
<li>Big Stuff somewhat random filler somewhat, random </li>
<li>Small Stuff somewhat random random random</li>
<li>Geek Stuff somewhat random filler somewhat</li>
<li>Nerd Stuff somewhat filler somewhat, somwhat random</li>
<li>Fast Stuff somewhat random filler somewhat, somwhat random</li>
<li>Slow Stuff somewhat random filler somwhat random</li>
<li>Good Stuff somewhat random filler somewhat, somwhat random</li>
<li>Bad Stuff somewhat random filler somewhat, somwhat random</li>
<li>Your Stuff somewhat random filler somewhat, random</li>
<li>My Stuff random filler somewhat, somwhat random</li>
</ul>
</div> <!-- END // div id="divInner" -->
</div> <!-- END // div id="divMiddle" -->
</div> <!-- END // div id="divOuter" -->
</div> <!-- END // div id="pageInner" -->
</div> <!-- END // div id="pageMiddle" -->
</div> <!-- END // div id="pageOuter" -->
<div id="divFoot">
Some Footer Content
</div>
<script type="text/javascript" charset="utf-8">
var body = document.body, html = document.documentElement;
var height = Math.max( body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight );
document.getElementById('pageOuter').style.height = height+'px';
document.getElementById('pageMiddle').style.height = height+'px';
height=height+1;
document.getElementById('pageInner').style.height = height+'px';
</script>
</body>
</html>
Copy link

ghost commented Sep 24, 2013

I cannot say what a lifesaver this code has been for me. I believe it is the only code in cyberspace of its kind! Brilliant. It worked like a charm UNTIL Apple released the new iPad/iPhone iOS 7. There is now a 1 pixel black border around the content. I have spent hours trying to get rid of this border without success. HELP. The border only shows on Apple devices (iPad/iPhone). Not in any other browsers or devices that I can tell.

@mattsahr
Copy link
Author

Here is a partial solution --

It seems like those border lines are created by stacked layers with "background" attributes. In the example here, I can get the black lines to disappear if I change #divMiddle and #divOuter to "background: none;"

Copy link

ghost commented Sep 24, 2013

Ahhhhhhhhhhhhhhhhhhhhh! You FIXED it!

Thank you so much! How kind of you to respond so quickly. I really do appreciate your creativity on this solution. Have a wonderful day!

@pward123
Copy link

Thanks! This helped me out quite a bit. FYI, you still end up with the bounce if pageInner ends up smaller than pageMiddle.

The following fixes the problem above for me. However, in my case, the width of pageOuter, pageMiddle and pageInner are all forced to be the same. If you need to scroll right/left, you'll have to take that into account when discarding the touchMove event.

    $('.pageOuter').on('touchmove', function( e ){
        var middleHeight = $('.pageMiddle').height(),
            innertHeight = $('.pageInner').height();

        if (middleHeight >= innerHeight) {
            e.preventDefault();             
        }
    });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment