jkupczak
jkupczak

Reputation: 3041

iFramed pages in IE9/10/11/Firefox do not update document.scrollHeight when the page changes in size?

I'm attempting to send the height of my page from an iframe to the parent page using the postMessage API. The idea is that when the total page height of the iframed page changes, it will send that height to the parent. The parent will then adjust the iframe's height to match. I currently have this working great in the latest Google Chrome.

Unfortunately, I've run into a hiccup with IE9/10/11 and Firefox. Once the .scrollHeight has been set to its largest, it stays there. Attempting to send a smaller height just sends the previously highest height, even though the originating page's height is considerably less.

I've figured that it's probably because the iframe the page is being held in is affecting the originating page's height. So this may actually have a CSS related solution?

Here is a reduced test case I put together. This parent page contains an iframe that holds a page that can increase and decrease its own height using two buttons I added. Additionally, a third button grabs the pages height and sends it to the parent using the postMessage API.

Example Page: http://iaviglobal.com/parent.html

I've made it so that the height that is sent and received is logged in the console. Test the functionality by adding the orange block and sending the document height. Then hide the orange block and send the height again. Works great in the latest Chrome, not so much in IE and FF.

Any help would be greatly appreciated.

EDIT: I've determined that I can avoid this issue if I use the height of any element other than <html> and <body>. For instance, reporting the height of <div id="main"> will give an accurate number regardless of browser. <html> and <body> seem to report the full iframe height in IE and Firefox even if the content inside them don't fill that much space.

However, it would still be preferred if I could get the accurate <html> or <body> height instead of using a <div>.

Upvotes: 1

Views: 1095

Answers (3)

MK.
MK.

Reputation: 5149

I believe IE/FF are giving you the correct behavior, as explicitly setting an element height to a value greater than the content height makes the scroll height equal to that value example.

You should be using offsetHeight instead:

function postit() {
  parent.postMessage(document.getElementsByClassName("global-embed")[0].offsetHeight,"http://iaviglobal.com");
  console.log("iframe sent this height: " + document.getElementsByClassName("global-embed")[0].offsetHeight);
};

Here is a working copy of your example.

Update

Looks like in IE9/10 html element inherits the iframe height, but using the body element instead works as expected:

//http://stackoverflow.com/a/17907562/328072
function getInternetExplorerVersion()
{
  var rv = -1;
  if (navigator.appName == 'Microsoft Internet Explorer')
  {
    var ua = navigator.userAgent;
    var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
    if (re.exec(ua) != null)
      rv = parseFloat( RegExp.$1 );
  }
  else if (navigator.appName == 'Netscape')
  {
    var ua = navigator.userAgent;
    var re  = new RegExp("Trident/.*rv:([0-9]{1,}[\.0-9]{0,})");
    if (re.exec(ua) != null)
      rv = parseFloat( RegExp.$1 );
  }
  return rv;
}
function postit() {
  var elm = document.getElementsByClassName("global-embed")[0];
  var ie  = getInternetExplorerVersion();
  var h   = ie == -1 || ie >= 11 ? elm.offsetHeight : document.body.scrollHeight;     
  parent.postMessage(h,"http://iaviglobal.com");
  console.log("iframe sent this height: " + h);
};

Updated working example here.

Upvotes: 1

Mystic
Mystic

Reputation: 25

I tested this in IE11 and Firefox 29. It works perfectly when I moved the class="global-embed" from the head-element to the body-element inside the iFrame!

<html id="global-embed" lang="en">
<body class="global-embed">

Upvotes: 1

mfirdaus
mfirdaus

Reputation: 4592

Interestingly, this behaviour is perhaps the "correct" behaviour.

The scrollHeight attribute must return the result of running these steps:

  1. Let viewport height be the height of the viewport excluding the height of the scroll bar, if any, or zero if there is no viewport.
  2. If the element is the root element and the Document is not in quirks mode return max(viewport scrolling area height, viewport height).
  3. If the element is the HTML body element, the Document is in quirks mode and the element has no associated scrolling box, return max(viewport scrolling area height, viewport height).
  4. If the element does not have any associated CSS layout box return zero and terminate these steps. 5.Return the height of the element's scrolling area.

reference: http://dev.w3.org/csswg/cssom-view/#dom-element-scrollheight

According to this (somewhat old) comparison body.clientHeight and body.offsetHeight seems to give the values you want in standards mode.

Upvotes: 2

Related Questions