iframe causes parent elements to scroll up on Google Chrome when URL contains fragment

arnaud.breton picture arnaud.breton · Sep 24, 2014 · Viewed 7k times · Source

On Google Chrome (37.0.2062.122, OSX / Windows), an iframe with an URL containing a fragment causes the parent elements to scroll up.

It's only happening in Chrome (tested in Safari and Firefox).

Here's a Fiddle showing the issue: http://jsfiddle.net/wmz5cu1y/1/ (you have to click Run twice.)

As you can see, the whole <body> containing the iframe has scrolled up. The header is hidden because it's now above the window, and there is an unexpected blank space at the bottom of the page.

How to avoid this ?

Bounty offered for a non-js workaround or a simpler html document reproducing the issue.

iframe overflows body

Answer

James Donnelly picture James Donnelly · Oct 16, 2014

As other answers have already mentioned, the issue here is specific to JSFiddle. I can show you that with ease by simply including the same code within a StackOverflow snippet on this question:

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


Simpler HTML document

This issue happens with every fragment URL passed into an iframe on JSFiddle. Because of this, we can replicate this issue simply be creating a separate JSFiddle demo and linking to that in our iframe.

I've created this new JSFiddle demo here: http://fiddle.jshell.net/JamesD/k5vk2u9h/1/show/light/#test.

As you can see, the fragment here is #test. This issue is now replicable in a new JSFiddle demo using the following markup:

<iframe src="http://fiddle.jshell.net/JamesD/k5vk2u9h/1/show/light/#test"></iframe>

The height and width attributes are irrelevant as the issue still appears without them.

JSFiddle demo.


A workaround

The other answer here suggests that the fix is to modify JSFiddle's own HTML in order to re-render the page correctly. This isn't a great solution as in a real world situation (i.e. when linking someone to a JSFiddle demo), they may not have the expertise to achieve this.

We can get around this by using JavaScript. As the new HTML document I've created is on the same domain (http://jshell.net) we can execute JavaScript within the iframe itself. Manually setting the location.hash property will also trigger this issue, so what we can do instead is scroll the iframe directly to the element we wish to focus on.

Firstly, remove the fragment from the URL in the src attribute of our iframe:

<iframe src="http://fiddle.jshell.net/JamesD/k5vk2u9h/1/show/light/"></iframe>

As mentioned above, the fragment I've used is an element whose id is "test". This means the easiest way to get our element is to select it by its id attribute:

var frame = frames[0],
    elem = frame.document.querySelector('#test'),

Here, frame is a reference to our iframe within our own document, and elem is our #test element. We can get our matched element's position by using getBoundingClientRect():

    position = elem.getBoundingClientRect();

This will give us a ClientRect object like the following:

ClientRect

With this we now know that our #test element is positioned 3034px from the top of our iframe. Using this, we can now scroll the page ourselves to this position using window.scrollTo() (where the window of our iframe in this case is held in our frame variable):

frame.scrollTo(0, position.top);

JSFiddle demo.

Note that this solution will only work if the iframe points to a URL hosted on the same domain or if CORS has been enabled on the page the iframe is embedding.


The best option

After doing all this though, the best bet is to simply notify the developers of JSFiddle that this is a bug. I've raised this as an issue on their GitHub repository here: https://github.com/jsfiddle/jsfiddle-issues/issues/547.