【问题标题】:How do I forbid an iFrame from scrolling its parent window?如何禁止 iFrame 滚动其父窗口?
【发布时间】:2022-03-14 19:16:46
【问题描述】:

我有一个 HTML 文档,它的底部包含一个 iframe。

在这种情况下,iframe 嵌入了一个 Google 电子表格,代码如下:

<iframe id="gsheet-group" width="100%" height="400" src="https://docs.google.com/spreadsheets/d/<!----DOCUMENT_KEY----->/edit?usp=sharing&rm=minimal&gid=0&single=true&widget=false&chrome=false&headers=false">Loading sheet..</iframe>

我相信这个 iframe 包含一些 javascript,这些 javascript 在某些事件上会导致其 parent window to scroll to the top,例如当它的加载完成或它的内容以某些方式导航时。 (如果 iframe 嵌入到第二个 iframe 中,此行为仍然存在。)

如果我不能直接修改iframe的源代码,是否可以在iframe嵌入的内容中防止父窗口被javascript操作?

我尝试过的

感谢评论者的建议,遗憾的是,这些建议都没有解决问题:

  • sandbox="allow-scripts allow-forms allow-pointer-lock allow-same-origin" 添加到&lt;iframe&gt; 元素(以删除allow-top-navigation;@CBroe)。
  • 覆盖window.scrollTo (@Ryano)
  • 将 iframe 放入单独的 iframe (@Ryano)

【问题讨论】:

  • "此 iframe 包含一些 javascript ..." 删除脚本?
  • 我认为无法编辑 iframe 的内容?
  • 它是否在操纵父文档的 URL 哈希...?如果父页面启用了后者,这可能会导致“跳转”或平滑滚动 - 并且不受同源策略的限制,允许对父页面的位置进行写访问。在这种情况下,对 iframe 进行沙盒处理以删除 allow-top-navigation 可能会有所帮助。
  • 我同意@Cbroe,如果这不起作用,可以尝试在您的页面上覆盖 window.scrollTo?或添加一些 CSS 使您的页面不可滚动?或者变得很脏并将iframe放入另一个iframe中?任何适合:)
  • 现在没时间检查了,但是 IIRC scrollIntoView 会让你的父页面滚动,即使从跨域 iframe 中调用也是如此。不知道如何防止这种情况发生。

标签: javascript html css iframe


【解决方案1】:

Element#scrollIntoView() 是一个这样的 API,它甚至允许跨域 iframe 滚动顶部文档。我没有检查您的嵌入页面确实在做什么,但这听起来是一个非常合理的解释。

这是一个最小的例子。重现:

  • 运行 sn-p
  • 立即手动滚动到页面顶部。
  • 等待大约 2 秒,让 sn-p 自动滚动回查看:

(也可以点击结果iframe再次调用scrollIntoView,2s后)。

onclick = e => setTimeout(() => {
  document.body.scrollIntoView();
}, 2000);
onclick();
Scroll to the top of the top page and wait 2s.

在挖掘了规格之后,恐怕没有现成的解决方案可以防止这种行为......
一件值得注意的事情是Chrome will not scroll to fixed elements in an iframe。这意味着我们实际上可以绕过这个错误来定义一个“滚动停止”层:您可以将目标 iframe 包装在另一个 iframe 中,将这个内部 iframe 的位置设置为固定,这样它完全覆盖了包装 iframe。这将阻止 Chrome 滚动此 iframe 的祖先:

iframe { position: fixed; top: 0; width: 100vw; height: 100vh; border: none; padding: 0; margin: 0; }
<iframe srcdoc="
<script>
  onclick = e => setTimeout(() => {
    document.querySelector('h1').scrollIntoView();
  }, 2000);
  onclick();
</script>
<h1 style='margin-top: 100vh' >I still scroll into view, but not the top page.</h1>
"></iframe>

然而,这是一个完整的破解,它基本上是一个漏洞利用,它显然不适用于其他网络浏览器,如果他们解决了这个问题,它甚至可能在 Chrome 的未来版本中失败。
但这是我目前唯一能找到的。

我邀请您做的是在W3C's CSS working group's Github repo 上表明您的观点,以便他们考虑添加一个正式允许此功能的属性。

【讨论】:

  • 在我的情况下,窗口滚动到顶部,而不是 iframe 的位置,但如果原因与您描述的行为类似,我不会感到惊讶。我开了一个issue at W3C;请做出贡献,特别是如果我误解了你的观点!
【解决方案2】:

在遵循@Kaiido 的建议在 W3C 跟进这件事后,那里的 cmets 确认当前标准确实不支持所需的行为。如果接受,proposal 将允许通过以下方式禁用垂直滚动:

<iframe src="..." allow="vertical-scroll 'none'"></iframe>

提案状态可追踪here

【讨论】:

  • (“意志”在这里很重要 ;-) 这个问题在过去 4 年里没有得到太多更新。希望您的问题能让事情再次走上正轨。)
猜你喜欢
  • 2013-03-30
  • 2013-08-11
  • 2012-09-07
  • 1970-01-01
  • 2013-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-12
相关资源
最近更新 更多