68

I dynamically load an iframe with JavaScript. After it's loaded, how can I make it scroll down a specific number of pixels (ie. after the page in the iframe has loaded, how can I make the iframe scroll by itself to the a specified region of the page?)

Brett DeWoody
  • 59,771
  • 29
  • 135
  • 184
rawrrrrrrrr
  • 3,647
  • 7
  • 28
  • 33

9 Answers9

61

You can use the onload event to detect when the iframe has finished loading, and there you can use the scrollTo function on the contentWindow of the iframe, to scroll to a defined position of pixels, from left and top (x, y):

var myIframe = document.getElementById('iframe');
myIframe.onload = function () {
    myIframe.contentWindow.scrollTo(xcoord,ycoord);
}

You can check a working example here.

Note: This will work if both pages reside on the same domain.

Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
  • So if the pages are not on the same domain, this will not work? – OdinX Jun 19 '10 at 00:28
  • 2
    @Chief17 - that's right, it would violate the same domain policy for Javascript. – Steve Claridge Oct 25 '10 at 13:55
  • 15
    you can circumvent the same origin policy by having doubling up on iframes. Your main page embeds an iframe to a shim page on your own server. The shim page in turn just embeds an iframe of the foreign page. The master page can scroll the shim page since they're in the same origin. Ugly, but it works. – Nelson Apr 16 '11 at 22:58
  • 31
    If you know the dimensions of the content you want to show in the iframe beforehand, you can put the iframe in a containing div, set overflow: hidden on it, and then relatively position the iframe inside that. Similar effect, no javascript. – Chris Mar 12 '12 at 13:30
  • 5
    checked your fiddle, and it doesn't seem to work. the scrollbars of the iframe didn't move :( http://screencast.com/t/MEvAiJA6yMCb – mars-o Aug 19 '14 at 04:44
  • What about cross domain? I have access at both end so i can receive post message from iframe and fire some action. – Yatin Mistry Aug 07 '15 at 07:30
  • "Blocked a frame with origin \"http://null.jsbin.com\" from accessing a cross-origin frame." – Zhang Apr 09 '21 at 06:38
26

Inspired by Nelson's and Chris' comments, I've found a way to workaround the same origin policy with a div and an iframe:

HTML:

<div id='div_iframe'><iframe id='frame' src='...'></iframe></div>

CSS:

#div_iframe {
  border-style: inset;
  border-color: grey;
  overflow: scroll;
  height: 500px;
  width: 90%
}

#frame {
  width: 100%;
  height: 1000%;   /* 10x the div height to embrace the whole page */
}

Now suppose I want to skip the first 438 (vertical) pixels of the iframe page, by scrolling to that position.

JS solution:

document.getElementById('div_iframe').scrollTop = 438

JQuery solution:

$('#div_iframe').scrollTop(438)

CSS solution:

#frame { margin-top: -438px }

(Each solution alone is enough, and the effect of the CSS one is a little different since you can't scroll up to see the top of the iframed page.)

Community
  • 1
  • 1
Sony Santos
  • 5,435
  • 30
  • 41
  • 2
    I was not able to get this to work. All it does it scroll the div and the iframe inside the div doesn't do anything. Could you demonstrate in a jsfiddle? Could you also explain the 438 constant? – whiteshooz May 20 '15 at 21:33
  • 1
    @whiteshooz, exact, the scroll stays in the div, which contains the whole iframe with the page. That way I can scroll the page through the div instead of the iframe, without violating the same-origin policy (which applies to the iframe only). 438 is the initial height I want to scroll, in this example (I'll edit my answer, thank's for your comment). – Sony Santos May 21 '15 at 17:27
  • I feel anything with an iframe is hacky, but to demo an idea I used this answer to create this demo http://jsfiddle.net/1b5s489z/ Load iframe on button click, hides the header of the target content (using css margin-top) and scrolls to a set point in the document using js solution. – timtom Oct 04 '18 at 10:23
25

Inspired by Nelson's comment I made this.

Workaround for javascript Same-origin policy with regards to using.ScrollTo( ) on document originating on an external domain.

Very simple workaround for this involves creating a dummy HTML page that hosts the external website within it, then calling .ScrollTo(x,y) on that page once it's loaded. Then the only thing you need to do is have a frame or an iframe bring up this website.

There are a lot of other ways to do it, this is by far the most simplified way to do it.

*note the height must be large to accommodate the scroll bars maximum value.

--home.html

<html>
<head>
<title>Home</title>
</head>

<frameset rows="*,170">
<frame src=body.htm noresize=yes frameborder=0 marginheight=0 marginwidth=0 scrolling="no">
<frame src="weather.htm" noresize=yes frameborder=0 marginheight=0 marginwidth=0 scrolling="no">
</frameset>
</html>

--weather.html

<html>
<head>
<title>Weather</title>
</head>

<body onLoad="window.scrollTo(0,170)">

<iframe id="iframe" src="http://forecast.weather.gov/MapClick.php?CityName=Las+Vegas&state=NV&site=VEF&textField1=36.175&textField2=-115.136&e=0" height=1000 width=100% frameborder=0 marginheight=0 marginwidth=0 scrolling=no>
</iframe>

</body>
</html>
yaswanthkoneri
  • 408
  • 4
  • 16
Greg
  • 251
  • 3
  • 3
11

Use the scrollTop property of the frame's content to set the content's vertical scroll-offset to a specific number of pixels (like 100):

<iframe src="foo.html" onload="this.contentWindow.document.documentElement.scrollTop=100"></iframe>
Justin Ludwig
  • 3,311
  • 2
  • 24
  • 17
5

A jQuery solution:

$("#frame1").ready( function() {

  $("#frame1").contents().scrollTop( $("#frame1").contents().scrollTop() + 10 );

});
Steve Claridge
  • 10,650
  • 8
  • 33
  • 35
2

Based on Chris's comment

CSS
.amazon-rating {
  width: 55px;
  height: 12px;
  overflow: hidden;
}

.rating-stars {
  left: -18px;
  top: -102px;
  position: relative;
}
HAML
.amazon-rating
  %iframe.rating-stars{src: $item->ratingURL, seamless: 'seamless', frameborder: 0, scrolling: 'no'}
Community
  • 1
  • 1
Chloe
  • 25,162
  • 40
  • 190
  • 357
1

Or, you can set a margin-top on the iframe...a bit of a hack but works in FF so far.

#frame {
margin-top:200px;
}
1

The main issue when programming the scroll is related to getting the whole document embedded into the page, remember than an Iframe would be a full-page (head and all) inside your main doc, for this reason, before actually scrolling, you need to get the inner document, not just the container, so you can actually scrollTo.

We add a validation to sendure compatibility, and the differences betwen contentDocument and windows can be found here

Havign this, the final code would be:

var $iframe = document.getElementByID('myIfreme');
var childDocument = iframe.contentDocument ? iframe.contentDocument : iframe.contentWindow.document;
 childDocument.documentElement.scrollTop = 0;
Camilo Casadiego
  • 907
  • 3
  • 9
  • 33
  • 2
    This answer was flagged as low-quality because of its length and content. Please make it more applicable to the OP. – crthompson Nov 08 '13 at 00:06
0

I've also had trouble using any type of javascript "scrollTo" function in an iframe on an iPad. Finally found an "old" solution to the problem, just hash to an anchor.

In my situation after an ajax return my error messages were set to display at the top of the iframe but if the user had scrolled down in what is an admittedly long form the submission goes out and the error appears "above the fold". Additionally, assuming the user did scroll way down the top level page was scrolled away from 0,0 and was also hidden.

I added

<a name="ptop"></a>

to the top of my iframe document and

<a name="atop"></a>

to the top of my top level page

then

    $(document).ready(function(){
      $("form").bind("ajax:complete",
        function() {
          location.hash = "#";
          top.location.hash = "#";
          setTimeout('location.hash="#ptop"',150);
          setTimeout('top.location.hash="#atop"',350);
        }
      )
    });

in the iframe.

You have to hash the iframe before the top page or only the iframe will scroll and the top will remain hidden but while it's a tiny bit "jumpy" due to the timeout intervals it works. I imagine tags throughout would allow various "scrollTo" points.