J'essaie d'implémenter une solution pour empêcher l'effet de rebond iOS dans Safari pour iOS lorsqu'un contenu de page Web est plus volumineux que la fenêtre d'affichage.
La page sur laquelle je travaille est assez spécifique dans sa structure et ressemble beaucoup à cette page http://new.salt.ch/
Le problème que je rencontre est identique à celui de la page http://new.salt.ch/ . En effet, lorsque vous faites défiler l'écran vers le haut, vous obtenez un effet de rebond en bas de l'écran qui révèle les fond et superposition.
J'ai essayé diverses solutions, notamment iNoBounce.js, Nonbounce.js et quelques autres suggestions que j'ai trouvées sur SO.
J'ai toujours le même problème ... lorsque j'essaie de désactiver le rebond, tout le défilement est désactivé. J'imagine que c'est parce que le contenu (autre que le pied de page) est toujours suffisamment volumineux pour que le défilement ne soit pas nécessaire. Le défilement est donc désactivé et le pied de page n'est plus accessible sur le défilement.
Ce code devrait arrêter le rebond car c'est la balise HTML qui rebondit
html {
height : 100%;
overflow: hidden;
}
body {
height : 100%;
overflow: auto;
}
Si j'interprète correctement votre question, nous avons le même problème depuis des années en développant des applications Web mobiles multiplates-formes, en essayant de faire en sorte que toutes les fonctionnalités de défilement propriétaires fonctionnent correctement sur chaque appareil: Apple iOS, Google Android, Windows. Téléphone, ordinateur portable Chrome, ordinateur portable Safari, IE et ordinateur portable Edge.
jQuery Mobile continue d'essayer de résoudre ce problème dans les limites de son cadre, mais c'est trop compliqué, avec les mises à jour constantes de chaque fabricant de périphérique/fabricant de système d'exploitation.
Oui, nous avons des solutions pour chaque appareil mobile individuel. Et nous avons testé, mais n'avons pas sérieusement envisagé de développer des structures de pagination sélectives pour chaque périphérique, nous obligeant à détecter chaque périphérique et à présenter une structure légèrement différente pour chacun. Insanement mauvaise idée de maintenir au moins 3 et même jusqu'à une douzaine de versions différentes de votre code.
SOLUTION: Nous avons eu le plus de chance en mettant simplement votre en-tête et votre pied de page persistants au-dessus de la structure de votre page. Voici la solution générale utilisant des styles en ligne pour plus de simplicité:
<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>
Ainsi, Body pourrait être n’importe quel ensemble de pages de jQuery Mobile. En fait, théoriquement, le corps pourrait être n'importe quel contenu de n'importe quel cadre.
Note spéciale, la ligne avec la hauteur: calc (100% - 1px); est essentiel à la magie.
Les combinaisons ou les permutations apparemment infinies de cette question sont presque devenues une croisade pour nous au fil des ans, en essayant de trouver la solution la plus pure, la plus simple et la plus universellement compatible. Donc, après avoir consacré un nombre embarrassant d'heures-personnes à ce sujet, il ne s'agit pas seulement de notre meilleure solution, mais également de la SEULE approche universellement compatible que nous avons trouvée, qui vous permet également de vous en tenir à une base de code unique. Il a été testé avec succès sur les dernières versions d'iOS, Windows Phone, Android, Chrome, Safari, PhoneGap, Firefox, IE 9-11 et Windows Edge.
TAGS: application mobile, application Web, en-tête fixe, pied de page fixe, en-tête persistant, pied de page persistant, problème de défilement, rebond de défilement iOS, rebond de défilement Chrome, rebond de défilement Android, problème de défilement Webkit, défilement Webkit Touch
J'ai parcouru quelques réponses sur SO et la situation semblait sombre jusqu'à ce que le code soit tombé par hasard.
html {
position: fixed;
height: 100%;
overflow: hidden;
}
body {
width: 100vw;
height: 100vh;
overflow-y: scroll;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
}
Les déclarations de style pour body
peuvent être placées sur tout élément que vous souhaitez pouvoir faire défiler. Vous pouvez également modifier overflow-x
et overflow-y
si nécessaire. Personnellement, j’en avais besoin pour ne PAS faire défiler les côtés, je l’ai donc déclaré.
mise à jour du 15 sept. 2017: je devais utiliser ce correctif pour un autre projet et je pouvais me passer de ces déclarations position: fixed
et height: 100%;
sur le sélecteur html
. YMMV
Mise à jour du 12 avril 2018 (mentionné dans les commentaires): Si vous utilisez des éléments fixes sur la page, ceux-ci peuvent présenter un "tremblement" visuel lors du défilement.
J'ai utilisé iNoBounce https://github.com/lazd/iNoBounce et cela fonctionne parfaitement!
Si vous devez également autoriser le défilement horizontal, il existe une demande d'extraction de santi6291 at https://github.com/lazd/iNoBounce/pull/36 qui corrige ce problème.
J'ai réussi à résoudre la plupart des problèmes liés à overflow: auto
et overflow: scroll
sur Safari mobile:
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>
La seule mise en garde que j'ai est que lorsque l'utilisateur touche et commence à descendre, puis à monter, rien ne se passe (attendu: la liste doit défiler vers le bas). Mais au moins, la méthode empêche le "pseudo-défilement" et ne confond pas l’utilisateur.
Pour surmonter ce dernier problème, il est nécessaire d'émuler une fin tactile, puis de toucher l'événement de début lorsque la direction change (j'ai mis des commentaires "TODO").
Mise à jour: il est possible d'éviter d'utiliser un correctif de code JavaScript sur iOS Cordova avec DisallowOverscroll = true
et WKWebView
.