这最终比代码更多的研究。发生的事情是 - 我有根据内容调整 IFrame 大小的代码。
在所有其他浏览器中,这可以正常工作并消除滚动条。原来 Safari automatically sizes the Iframe 留下了它自己的卷轴。在我的应用程序中,静态页面为零。这给我留下了无法使用链接中描述的scrolling=no 修复的问题。
在确切发现发生了什么之后,我采取了不同的方法来修复elm.scrollIntoView()。除了重要的部分之外,代码更多的是 cmets;
- 检测何时使用
RequiresIframeScrollFix 应用 Iframe 修复
- 使用
elm.getBoundingClientRect().top 从 Iframe 中获取我们的滚动位置。
- 与父级通信以滚动
window.parent.postMessage
- 用
window.addEventListener('message',...)在父级中接收消息
这就是它的样子。
Iframe 网站
我们的 Iframe 网站目前将其元素滚动到这样的视图中 elm.scrollIntoView(); 我们已将其更改为以下内容。
if (RequiresIframeScrollFix())
window.parent.postMessage(elm.getBoundingClientRect().top, "*"); // Tell IFrame parent to do the scrolling. If this is not a test environment, replace "*" with the parent domain.
else
elm.scrollIntoView(); // If not scroll into view as usual.
可选:使用 elm.getBoundingClientRect().top 修复 IOS IFrame 中的引导模式定位。
$('#modalId').css('top', elm.getBoundingClientRect().top); // This fixes modal not in view on Safari Iframes.
RequiresIframeScrollFix() 主要由一些很好的文档代码组成,围绕 SO 确定我们是在 iPad 还是 iPhone 上的 iframe 中。
// Used to help identify problematic userAgents.
var debugNavigator = false;
// Detects an issue on mobile where the Parent is an iframe which cannot have it's scroll bars removed.
// Presumably not a bug as safari will autosize it's iframes: https://salomvary.com/iframe-resize-ios-safari.html
// Can use "scrolling=no" fix instead if the parent knows the initial size of your iframe.
function RequiresIframeScrollFix() {
try {
// Debug navigator Agent
if (debugNavigator)
alert(navigator.userAgent);
// We know this issue happens inside an IFrame on;
// Safari iPhone
// Safari iPad
// Safari Desktop Works fine.
// Check for safari
var is_safari = navigator.userAgent.indexOf("Safari") > -1;
// Chrome has Safari in the user agent so we need to filter (https://stackoverflow.com/a/7768006/1502448)
var is_chrome = navigator.userAgent.indexOf('Chrome') > -1;
if ((is_chrome) && (is_safari)) { is_safari = false; }
// If we need to narrow this down even further we can use a more robust browser detection (https://stackoverflow.com/questions/5916900)
// Problematic browsers can be adjusted here.
if (is_safari && inIframe() && (
navigator.userAgent.match(/iPad/i) ||
navigator.userAgent.match(/iPhone/i)
))
return true;
else
return false;
} catch (e) {
alert(e.message);
}
}
// (https://stackoverflow.com/questions/326069/)
function inIframe() {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
}
父网站
我们的父网站拥有由 Safari Mobile 自动调整大小的 IFrame。因此,父站点现在有它自己的滚动条,而不是 IFrame。我们在父站点内设置监听器,以便在它收到来自 IFramed 站点的消息时自行滚动。
// Safari Mobile Iframe Cross Domain Scroll Fix.
window.onload = function () {
// Calback function to process our postMessages.
function receiveMessage(e) {
try {
// Set the scroll position from our postMessage data.
// Non-Test pages should uncomment the line below.
//if (e.origin.includes("your-iframe-domain.com"))
window.scrollTo(0, e.data);
}
catch (err) {
}
}
// Setup and event to receives messages form our iframe (or window)
window.addEventListener('message', receiveMessage);
}
希望这有助于其他人剖析移动设备上的 Safari iframe 问题。另外,如果我忽略了更好的解决方案,请告诉我。