当URL包含片段时,iframe会导致父元素在Google Chrome上向上滚动

arn*_*ton 10 html iframe google-chrome jsfiddle

在Google Chrome(37.0.2062.122,OSX/Windows)上,带有包含片段的网址的iframe会导致父元素向上滚动.

它只发生在Chrome中(在Safari和Firefox中测试过).

这是一个显示问题的小提琴:http://jsfiddle.net/wmz5cu1y/1/(你必须点击Run 两次.)

如您所见,<body>包含iframe 的整体已向上滚动.标题是隐藏的,因为它现在位于窗口上方,并且页面底部有一个意外的空白区域.

怎么避免这个?

赏金提供了非js变通方法​​或简单的html文档来重现这个问题.

iframe溢出身体

Jam*_*lly 16

正如其他答案已经提到的那样,这里的问题特定于JSFiddle.我可以通过在此问题的StackOverflow片段中简单地包含相同的代码来轻松地向您展示:

iframe {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
Run Code Online (Sandbox Code Playgroud)
<iframe src="https://news02ycombinator02com2.mentionusercontent.net/item?id=8357207#up_8360397" width="100%" height="100%"></iframe>
Run Code Online (Sandbox Code Playgroud)


更简单的HTML文档

传递到iframeJSFiddle上的每个片段URL都会出现此问题.因此,我们可以复制这个问题,只需创建一个单独的JSFiddle演示并链接到我们的iframe.

我在这里创建了这个新的JSFiddle演示:http://fiddle.jshell.net/JamesD/k5vk2u9h/1/show/light/#test .

如你所见,这里的片段是#test.现在可以使用以下标记在新的JSFiddle演示中复制此问题:

<iframe src="http://fiddle.jshell.net/JamesD/k5vk2u9h/1/show/light/#test"></iframe>
Run Code Online (Sandbox Code Playgroud)

heightwidth为这个问题似乎仍然没有他们的属性是不相关的.

JSFiddle演示.


解决方法

这里的另一个答案表明修复是修改JSFiddle自己的HTML,以便正确地重新呈现页面.这不是一个很好的解决方案,因为在现实世界的情况下(即将某人链接到JSFiddle演示时),他们可能没有专业知识来实现​​这一点.

我们可以使用JavaScript解决这个问题.由于我创建的新HTML文档位于同一个域(http://jshell.net),我们可以在iframe自己内部执行JavaScript .手动设置location.hash属性也会触发此问题,因此我们可以做的是iframe直接滚动到我们希望关注的元素.

首先,从src我们的属性中的URL中删除片段iframe:

<iframe src="http://fiddle.jshell.net/JamesD/k5vk2u9h/1/show/light/"></iframe>
Run Code Online (Sandbox Code Playgroud)

如上所述,我使用的片段是一个id"测试" 的元素.这意味着获取元素的最简单方法是通过其id属性选择它:

var frame = frames[0],
    elem = frame.document.querySelector('#test'),
Run Code Online (Sandbox Code Playgroud)

这里frameiframe我们自己的文档中的引用,elem是我们的#test元素.我们可以通过以下方式获得匹配元素的位置getBoundingClientRect():

    position = elem.getBoundingClientRect();
Run Code Online (Sandbox Code Playgroud)

这将为我们提供如下的ClientRect对象:

ClientRect

有了这个,我们现在知道我们的#test元素位于我们的顶部3034px iframe.使用这个,我们现在可以使用window.scrollTo()(window我们iframe在这种情况下保存在我们的frame变量中)将页面自己滚动到这个位置:

frame.scrollTo(0, position.top);
Run Code Online (Sandbox Code Playgroud)

JSFiddle演示.

请注意,此解决方案仅在iframe指向同一域上托管的URL 的点或者在iframe嵌入的页面上启用了CORS 时才有效.


最好的选择

完成所有这些之后,最好的办法是简单地通知JSFiddle的开发人员这是一个错误.我在这里将它作为一个问题提到了他们的GitHub存储库:https://github.com/jsfiddle/jsfiddle-issues/issues/547.

  • @ arnaud576875这就是重点 - 你不能,因为它是一个JSFiddle错误.要重现它,您必须将代码JSFiddle复制到其结果窗格中包含的`iframe`元素.我不认为我应该为此做一个downvote,因为我已经展示了一个更简单的JSFiddle方法来重现bug,我提供了一个解决方法 - 两者都是问题中提到的东西.在[原始编辑](http://stackoverflow.com/revisions/668a4bbb-1f87-4df3-8998-26b504066382/view-source)中没有提到必须在JSFiddle之外复制这些错误. (6认同)

sli*_*oad 7

修订后的答案

这里显示了两个错误.

  1. 在使用片段加载iFrame时,JSFiddle丢失了部分标题.这在其他答案和我的"旧答案"部分中讨论.并且提出了一个github问题.
  2. Chrome上的iFrame处理碎片很严重.它们会导致父级滚动.(这可能是期望的行为是公平的).

Chrome iFrame问题

运行此窗口时,窗口将滚动,以便窗口中的片段位于页面顶部:

<iframe src="https://news02ycombinator02com2.mentionusercontent.net/item?id=8357207#up_8360397" width="100%" height="100%"></iframe>
Run Code Online (Sandbox Code Playgroud)

可以想象,这会导致像jsfiddle这样的固定高度网站出现问题.它也是Chrome独有的(我只在FF上测试,而不是IE),Firefox不会滚动父窗口.有一个关于在FF它不是讨论在这里.

Chrome iFrame父级滚动修复

小提琴

将onload事件添加到调用以下函数的iframe.并且不要使用原始片段:

<script>
    function loadorder() {
    document.getElementById("iframename").src= "https://news02ycombinator02com2.mentionusercontent.net/item?id=8357207#up_8360397";
    window.scrollTo(0,0);
}
</script>
<iframe width="830" src="https://news02ycombinator02com2.mentionusercontent.net/item?id=8357207" height="500" id="iframename"  onLoad="loadorder();"></iframe>
Run Code Online (Sandbox Code Playgroud)

正如您在小提琴和上面的片段中看到的那样,父窗口不再滚动,现在FF和Chrome的行为相同.

修复的来源.

旧答案(jsfiddle的替代修复)

好的,我做了一些测试:

  • 仅在Chrome上发布
  • 任何片段链接页面都会出现问题:示例
  • 问题特定于jsfiddle.CodePenjsbin工作正常.

因此,作为临时解决方法,要么使用其中一个,要么将其注入jsfiddle的html中:

margin-top: 30px; into the header bar like:

<div id="header" style="margin-top: 30px;">
Run Code Online (Sandbox Code Playgroud)

虽然每次加载jsfiddle都需要完成(但不是每次运行小提琴时都需要),所以有点痛苦.

要解决问题,应该在jsfiddle github页面上报告:https://github.com/jsfiddle/jsfiddle-issues/issues

编辑

这是一种在chrome上自动化它的方法:下载stylebot 扩展,并将此样式添加到jsfiddle.com(或特定的小提琴):

#header {
    margin-top: 30px;
}
Run Code Online (Sandbox Code Playgroud)

它工作得很好.


Arn*_*anc 0

复制脚本

找到了重现该错误的最小方法:http://jsfiddle.net/4oytgwon/1/embedded/result/(您可以在单击“加载 iframe”后看到错误发生)。

它也发生在 jsfiddle 之外,使用以下代码:

<!doctype html>
<html>
    <head>
        <style>
            body, html {
                padding: 0;
                border: 0;
                margin: 0;
                height: 100%;
                overflow: hidden;
            }
            #header {
                height: 50px;
                background: blue;
            }
            #content {
                position: absolute;
                top: 50px;
                right: 0;
                bottom: 0;
                left: 0;
            }
            #overflow {
                position: absolute;
                height: 50px;
                bottom: -50px;
            }
        </style>
        <script>
            function loadIframe() {
                var ifr = document.createElement('iframe');
                ifr.src = 'https://en.wikipedia.org/wiki/Stack_overflow#See_also';
                var content = document.getElementById('content');
                while (content.firstChild) {
                    content.removeChild(content.firstChild);
                }
                content.appendChild(ifr);
            }
            window.onload = function () {
                document.getElementById('btn').onclick = loadIframe;
            };
        </script>
    </head>
    <body>
        <div id=header>
            <button id=btn>load iframe</button>
        </div>
        <div id=content>
        </div>
        <div id=overflow>
            overflow
        </div>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)