我希望 iOS 13 Safari 上的 body 元素不滚动。这意味着没有滚动,也没有弹性反弹(溢出滚动)效果。
我设置了两个相邻的元素
overflow: scroll;
,它们应该滚动,只是它们周围的主体不应该滚动。
我尝试过的所有解决方案都不适用于渐进式网络应用程序,这些应用程序的头中有以下标签并保存到主屏幕。
<meta name="apple-mobile-web-app-capable" content="yes">
我尝试过的解决方案:
设置隐藏在正文和/或 HTML 上的溢出。不适用于 iOS 13 safari:https://stackoverflow.com/a/18037511
html {
position: relative;
overflow: hidden;
height: 100%;
}
body {
position: relative;
overflow: hidden;
height: 100%;
}
在 iOS 13 Safari 中不执行任何操作,但可以在 macOS Safari 和 Firefox 中使用。
设置位置固定在机身上。对我不起作用,因为当用户滚动时,主体不会滚动,但滚动仍然会阻止我的两个内部元素在溢出反弹动画时滚动:https://stackoverflow.com/a/47874599
body {
position: fixed;
}
仅将正文置于页面滚动之上。滚动(溢出滚动)通过固定主体发生。
防止默认触摸移动。不起作用(是一个较旧的解决方案......):https://stackoverflow.com/a/49853392
document.addEventListener("touchmove", function (e) {
e.preventDefault();
}, { passive: false });
据我所知,什么也没做。 Safari 和 Firefox 中均不支持。
防止窗口默认滚动并将滚动位置设置回 0。由于动画有问题,不可行。
window.addEventListener("scroll", (e) => {
e.preventDefault();
window.scrollTo(0, 0);
});
将滚动位置设置回 0,但溢出滚动仍然适用,最终导致错误行为。
演示它的片段:
要自行测试,请将下面的代码片段另存为 HTML 文件,并将其保存到 iPad(或 iPad 模拟器)的主屏幕上。保存到主屏幕后,正文突然变得可滚动。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<meta name="apple-mobile-web-app-capable" content="yes">
</head>
<body>
<style>
body, html {
position: relative;
overflow: hidden;
height: 100%;
width: 100%;
}
body {
margin: 0;
display: flex;
flex-direction: column;
}
nav, footer {
width: 100%;
height: 5rem;
background: blue;
flex-shrink: 0;
}
main {
display: flex;
height: 0;
flex-grow: 1;
padding: 2rem;
}
section {
width: 50%;
overflow: scroll;
display: flex;
flex-direction: column;
align-items: center;
}
div {
flex-shrink: 0;
width: 25%;
height: 18rem;
margin: 1rem;
background: red;
}
</style>
<nav></nav>
<main>
<section>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</section>
<section>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</section>
</main>
<footer></footer>
</body>
</html>
他们都没有以我可以接受的方式工作。我该如何执行此操作才能在 iOS 13 Mobile Safari 中正常工作(当保存为 PWA 到主屏幕时)?
我结合了问题中的尝试2和尝试4。固定主体不显示溢出滚动,滚动重置可防止后台溢出滚动的长动画。虽然很丑,但是还蛮管用的。
body {
position: fixed;
}
window.addEventListener("scroll", (e) => {
e.preventDefault();
window.scrollTo(0, 0);
});
只需在 CSS 的 body 中添加一个 touch-action:none 即可:
body{
touch-action:none;
}
function unlockScroll () {
const scrollY = this.body.style.top;
document.body.style.position = '';
document.body.style.top = '';
document.body.style.left = '';
document.body.style.right = '';
window.scrollTo(0, parseInt(scrollY || '0') * -1);
};
function lockScroll () {
document.body.style.position = 'fixed';
document.body.style.top = `-${window.scrollY}px`;
document.body.style.left = '0';
document.body.style.right = '0';
};
在我的例子中(应用程序需要拖动来排列元素)将 touch-action 设置为
none
可以防止拖动某些元素时滚动。
例如
draggableElement.css('touch-action', 'none') // disable actions
draggableElement.css('touch-action', 'auto') // restore actions
我之前也遇到过类似的问题,到目前为止,使用以下方法效果最好:
首先,通过应用
-webkit-overflow-scrolling: touch
其次,应用以下规则:
/* this part makes sure there is nowhere left to scroll */
html {
position: static;
overflow-y: hidden;
height: 100%;
max-height: 100%;
}
/* all properties don't necessarily need to be applied on both elements,
this is only used to override any existing code */
body {
overflow: hidden;
height: 100%;
max-height: 100%;
}
window.addEventListener('touchend', _ => {
window.scrollTo(0,0)
});
在用户放开身体后,这会将身体弹回 0,0,允许用户立即向下滚动,除了立即弹回之外,不会出现任何奇怪的动画。我尝试使用平滑的滚动动画,但它的动画速度并不总是足够快。这将防止 iPhone 上的身体从弹跳弹性滚动条滚动时发生屏幕锁定,并且仅在用户松开拉力时才会触发。
对我来说有效:
import { useEffect } from "react";
export const useOverscrollHandler = () => {
useEffect(() => {
const onScroll = (e: any) => {
e.preventDefault();
window.scrollTo(0, 0);
};
window.addEventListener("scroll", onScroll);
return () => window.removeEventListener("scroll", onScroll);
}, []);
};
https://github.com/willmcpo/body-scroll-lock
我目前无法测试,但这似乎值得一试。
这对我有用https://stackoverflow.com/a/41601290/10763156
请将
添加到-webkit-overflow-scrolling: touch;
元素。#overlay
请在 body 标签末尾添加此 javascript 代码:
(function () {
var _overlay = document.getElementById('overlay');
var _clientY = null; // remember Y position on touch start
_overlay.addEventListener('touchstart', function (event) {
if (event.targetTouches.length === 1) {
// detect single touch
_clientY = event.targetTouches[0].clientY;
}
}, false);
_overlay.addEventListener('touchmove', function (event) {
if (event.targetTouches.length === 1) {
// detect single touch
disableRubberBand(event);
}
}, false);
function disableRubberBand(event) {
var clientY = event.targetTouches[0].clientY - _clientY;
if (_overlay.scrollTop === 0 && clientY > 0) {
// element is at the top of its scroll
event.preventDefault();
}
if (isOverlayTotallyScrolled() && clientY < 0) {
//element is at the top of its scroll
event.preventDefault();
}
}
function isOverlayTotallyScrolled() {
// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Problems_and_solutions
return _overlay.scrollHeight - _overlay.scrollTop <= _overlay.clientHeight;
}
}())