当网页内容大于视口时,我正在尝试实施一种解决方案,以防止iOS for Safari中的iOS反弹效果。
我正在处理的页面在结构上非常具体,与此页面非常相似http://new.salt.ch/
我遇到的问题与页面http://new.salt.ch/上的问题相同,因为当您向上滚动时,屏幕底部会出现一个反弹效果,并显示背景和叠加效果。
我尝试了各种解决方案,包括iNoBounce.js,Nonbounce.js以及我在SO上找到的其他一些建议。
我总是遇到同样的问题...当我尝试禁用反弹时,所有滚动都会被禁用。我猜这是因为内容(除了页脚)总是足够大,不需要滚动,因此滚动被禁用,滚动时不再可以访问页脚。
答案 0 :(得分:16)
如果我正确地解释您的问题,我们多年来一直在开发跨平台移动网络应用程序时遇到同样的问题,试图让所有不同的专有滚动功能在每台设备上正常运行:Apple iOS,Google Android,Windows Phone,笔记本电脑Chrome,笔记本电脑Safari,IE和笔记本电脑Edge。
jQuery Mobile继续尝试在他们的框架范围内修复这个问题,但是由于每个设备制造商/操作系统制造商的不断更新,这个问题太多了。
是的,我们为每个移动设备提供了解决方案。我们已经测试过,但没有认真考虑为每个设备开发设备选择性分页框架,要求我们检测每个设备并为每个设备提供略微不同的框架。基本上维护至少3个以及最多十几个不同版本的代码,这是一个非常糟糕的主意。
解决方案:只需将持久性页眉和页脚放在页面框架之上,我们就能获得最大的收益。以下是使用内联样式的简单通用解决方案:
<html>
<head>
<title>Fixed Header and Footer on All Mobile Web Apps</title>
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0" />
<style>
html, body { height:100%; width:100%; }
</style>
</head>
<body>
<div style="position: fixed; height:100%; width:100%; top:0; left:0;">
<div style="height:calc(100% - 1px); width:100%; margin-top: 60px; z-index: 1; overflow-y: scroll; -webkit-overflow-scrolling: touch;">
[Body Content That Can Scroll if it extends beyond screen...]
</div>
<div style="position: absolute; top:0; left:0; width:100%; height: 60px; background:#dddddd; z-index:10;">
[Header Content...]
</div>
<div style="position: absolute; bottom:0; left:0; width:100%; height: 40px; background:#cccccc; z-index:11;">
[Footer Content...]
</div>
</div>
</body>
</html>
因此,Body可以是任何jQuery Mobile页面集。事实上,从理论上讲,Body几乎可以是任何框架中的任何内容。
特别说明,高度线:calc(100% - 1px);对魔术至关重要。
这个问题看似无限的组合或排列几乎已成为我们多年来的一次讨伐,试图找到最纯粹,最简单,最普遍兼容的解决方案。因此,在为这个主题投入了令人尴尬的工时后,这不仅是我们最好的解决方案,它也是我们发现的唯一普遍兼容的方法,也允许您坚持只有一个单一的代码库。它已经在最新版本的iOS,Windows Phone,Android,笔记本电脑Chrome,笔记本电脑Safari,PhoneGap,笔记本电脑Firefox,IE 9-11和Windows Edge上成功测试过。
标签:移动应用,网络应用,固定标题,固定页脚,持久标题,持久页脚,滚动问题,iOS滚动弹跳,Chrome滚动弹跳,Android滚动弹跳,webkit滚动问题,webkit触摸滚动,iOS触摸滚动问题答案 1 :(得分:15)
此代码应停止反弹,因为它是反弹的HTML标记
html {
height : 100%;
overflow: hidden;
}
body {
height : 100%;
overflow: auto;
}
答案 2 :(得分:13)
我在SO上经历了几个答案,事情看起来很惨淡,直到找到了这段代码。
html {
position: fixed;
height: 100%;
overflow: hidden;
}
body {
width: 100vw;
height: 100vh;
overflow-y: scroll;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
}
body
的样式声明可以放在您想要滚动的任何元素上。您还可以根据需要更改overflow-x
和overflow-y
。我个人需要它不要滚动到两侧,所以我宣布它是这样。
2017年9月15日更新:我必须将此修复程序用于另一个项目,并且我能够在position: fixed
选择器上没有这些声明height: 100%;
和html
。 YMMV
2018年4月12日更新(在评论中提到):如果您在页面上使用固定元素,那么这些元素在滚动时可能会出现视觉上的“晃动”。
答案 3 :(得分:4)
我使用了iNoBounce https://github.com/lazd/iNoBounce,效果很好!
如果您还需要允许水平滚动,那么santi6291 https://github.com/lazd/iNoBounce/pull/36处的拉取请求会修复
答案 4 :(得分:1)
这些答案都无法在2019年用于iOS 13移动Safari。
答案 5 :(得分:0)
我设法在移动版Safari上解决了支持overflow: auto
和overflow: scroll
的大多数问题:
window.addEventListener('DOMContentLoaded', function () {
var atTop = true;
var atBottom = false;
var body = document.getElementById('fixedBody');
body.addEventListener('touchmove', function(event){
event.preventDefault();
});
body.addEventListener('touchstart', function(event){
event.preventDefault();
});
body.addEventListener('touchend', function(event){
event.preventDefault();
});
var scrollingDiv = document.getElementById('scrollDiv');
if (scrollingDiv.scrollHeight <= scrollingDiv.clientHeight) {
atBottom = true;
}
scrollingDiv.addEventListener('scroll', function(event){
if (event.target.scrollTop === 0) {
atTop = true;
} else {
atTop = false;
}
if (event.target.scrollHeight - event.target.scrollTop === event.target.clientHeight) {
atBottom = true;
} else {
atBottom = false;
}
});
var lastY = 0;
var topLock = false;
var bottomLock = false;
scrollingDiv.addEventListener('touchmove', function(event){
event.stopPropagation();
var currentY = event.touches[0].clientY;
if (currentY > lastY) {
// moved down
if (atTop) {
event.preventDefault();
topLock = true;
}
if (bottomLock) {
bottomLock = false;
// TODO: Emulate finger remove and touch again here
}
} else if(currentY < lastY){
// moved top
if (atBottom) {
event.preventDefault();
bottomLock = true;
}
if (topLock) {
topLock = false;
// TODO: Emulate finger remove and touch again here
}
}
lastY = currentY;
});
scrollingDiv.addEventListener('touchstart', function(event){
lastY = event.touches[0].clientY;
event.stopPropagation();
});
scrollingDiv.addEventListener('touchend', function(event){
event.stopPropagation();
});
});
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
</head>
<body id="fixedBody" style="overflow: hidden;">
<div style="position: fixed; height: 64px; width:100%; top:0; left:0; background-color: green; z-index: 1;">
Header
</div>
<div id="scrollDiv" style="position: absolute; width: 100%; top: 64px; bottom: 0px; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; background-color: white;">
<div style="height: 150px; background-color: blue;">
First
</div>
<div style="height: 150px; background-color: red;">
Second
</div>
<div style="height: 150px; background-color: green;">
Third
</div>
<div style="height: 150px; background-color: black;">
Another
</div>
</div>
</body>
</html>
我唯一需要注意的是,当用户触摸并开始向下然后向上移动时,没有任何反应(预期:列表应向下滚动)。但至少该方法可以防止“伪滚动”而不会混淆用户。
要克服最后一个问题,有必要模拟触摸结束,然后在方向改变时触摸开始事件(我已经发出“TODO”评论)。
更新:可以避免在{1}}和DisallowOverscroll = true
的iOS Cordova上使用JavaScript代码修复。
答案 6 :(得分:0)
对于iOS 13上的2019 Safari,我可以使用此修复程序:
html {
overflow: hidden;
height: 100%;
position: fixed;
}
body {
overflow: auto;
height: 100%;
position: relative;
}
至少对我来说,它涵盖了大多数情况。
答案 7 :(得分:0)
答案 8 :(得分:0)
我尝试了所有CSS解决方案,但无济于事。当到达顶部/底部时,iOS仍会反弹某些div,或者在使用固定位置进行操作时,滚动本身确实变得不可靠且容易出错。因此,我想出了一个JavaScript解决方案,它实际上非常简单,似乎已经为我解决了这个问题:
function onTouchStart(e) {
// Save position of touch
console.log("touchstart");
const touch = e.touches[0] || e.changedTouches[0];
window.lastY = touch.pageY;
}
function onTouchMove(e) {
console.log("touchmove");
// Check user isn't scrolling past content. If so, cancel move to prevent ios bouncing
const touch = e.touches[0] || e.changedTouches[0];
y = touch.pageY;
if (y < window.lastY && e.srcElement.scrollTop == (e.srcElement.scrollHeight - e.srcElement.clientHeight)) {
console.log("user is trying to scroll down without anywhere to scroll to. Canceling propagation.");
e.preventDefault();
} else if (y > window.lastY && e.srcElement.scrollTop == 0) {
console.log("user is trying to scroll up without anywhere to scroll to. Canceling propagation.");
e.preventDefault();
}
};
document.addEventListener("touchstart", onTouchStart, { passive: false });
document.addEventListener("touchmove", onTouchMove, { passive: false });
答案 9 :(得分:0)
对于离子用户 -
对我来说一个简单的解决方案是在 ion-content 的子 div 上使用 slot="fixed"
。
<ion-content>
<div slot="fixed" />
</ion-content>
答案 10 :(得分:0)
就我而言,我希望地址栏在滚动时消失,并且在用户滚动时获得弹跳效果,但这为我解决了
html {
position: relative;
overflow-y: scroll;
}
body {
overflow-y: scroll;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
}