Three Discussions on Iframe Adaptive Height Code

Three Discussions on Iframe Adaptive Height Code
When building a B/S system interface, you often encounter the situation where other pages are nested in the main page index.html. Although some libraries already provide controls (such as jQuery easy UI), sometimes the use of iframe is inevitable. This article should give you a relatively practical answer. As the article says, most things on the Internet are garbage or unreliable! The original text is compiled by KOUBEI UED!
Why three talks?
Why three talks? One reason is that this is a topic that has been talked about a lot, and the other reason is that Master Tai wrote this article n years ago discussing the adaptive height of iframe. The reason why I bring up this issue again is that I did encounter all aspects of this problem in previous projects, and it is necessary to summarize it. I hope this helps, please point out any mistakes.
The simplest case is when the height of the sub-pages in the same domain does not increase dynamically. You can directly obtain the actual height of the sub-page through the script and modify the height of the iframe element. But there are two points to note:
If there are absolutely positioned elements or uncleared floating elements on the page, the situation is a bit complicated. Different browsers handle the results differently, even browsers with Webkit kernels. Please see this demo for details. So you either have to do browser detection, or calculate a maximum value with Math.max, or you have to think of another way.
The page contained in the iframe may be very large and require a long time to load. Therefore, when calculating the height directly, it is very likely that the page has not been downloaded yet and there will be problems with the height calculation. So it's better to calculate the height in the onload event of the iframe. It should also be noted here that the Microsoft event model obj.attachEvent must be used to bind the onload event in IE. For other browsers, you can also use obj.onload = function(){} directly.

Copy code
The code is as follows:

(function(){
var frame = document.getElementById("frame_content_parent"),
setIframeHeight = function(){
var frameContent = frame.contentWindow.document,
frameHeight = Math.max(frameContent.body.scrollHeight,frameContent.documentElement.scrollHeight);
frame.height = frameHeight;
};
if(frame.addEventListener){
frame.addEventListener("load",setIframeHeight,false);
}else{
frame.attachEvent("onload",setIframeHeight);
}
})();

The height of the same domain and sub-pages will increase dynamically. The principle is the same as the first case. An additional timer is added to keep detecting the height of the sub-page. When the height of the sub-page is inconsistent with the height of the iframe, the height of the iframe is reset. You can also add a try here to add a sufficient height when a js error occurs.

Copy code
The code is as follows:

(function(){
var _reSetIframe = function(){
var frame = document.getElementById("frame_content_parent")
try {
var frameContent = frame.contentWindow.document,
bodyHeight = Math.max(frameContent.body.scrollHeight,frameContent.documentElement.scrollHeight);
if (bodyHeight != frame.height){
frame.height = bodyHeight;
}
}
catch(ex) {
frame.height = 1800;
}
}
if(frame.addEventListener){
frame.addEventListener("load",function(){setInterval(_reSetIframe,200);},false);
}else{
frame.attachEvent("onload",function(){setInterval(_reSetIframe,200);});
}
})();

In the second example, the script error is taken into account. But what if the script is not executed at all? The content in the iframe will not be displayed because the height of the iframe is not enough. For this reason, we usually set a sufficient height in advance. For the convenience of front-end control, I think it is more appropriate to write it in the CSS file. When modification is needed, only the CSS needs to be modified. Here I set selector{ height:1800px; }. It should be noted that the styles written in the style sheet cannot be directly obtained using node.style[property]. For the Microsoft model, node.currentStyle[property] should be used (off topic: the tragic IE model does not support CSS pseudo-classes). For the W3C model, window.getComputedStyle(node,null)[property] should be used. I just used YUI for convenience.
There is another problem here. When the height of the iframe is set to be greater than the height of the page it contains, each browser handles it differently. For example, in Firefox, the height of the body element must be calculated, and the height of the html element is equal to the height of the iframe. However, if the page happens to have absolutely positioned and unclear floating elements, it cannot be obtained through the body element. Obviously, the first method has fewer disadvantages. Please see this Demo for details.
From the demo above, we can see that except for IE browser, other browsers calculate the height of the iframe, which is #frame_content_parent{ height:1800px; } set in CSS. What IE calculates is the actual height of the page referenced by the iframe.

Copy code
The code is as follows:

#frame_content_parent{ height:1800px; }
(function(){
var $ = YAHOO.util.Dom,
frame = $.get("frame_content_parent");
function reSetIframe(){
var frameContent = frame.contentWindow.document,
bodyHeight = Math.max(frameContent.documentElement.scrollHeight,frameContent.body.scrollHeight);
if (bodyHeight != $.getStyle(frame, "height")){
$.setStyle(frame, "height", bodyHeight + "px");
}
}
if(frame){
$.setStyle(frame,"height","auto");
setInterval(reSetIframe,300);
}
})();

Here is a cross-domain Iframe proxy method, and briefly explains the principle. Suppose there are 3 pages, namely the main page A.html, the sub-page B.html, and the proxy page C.html. A and B are cross-domain, while A and C are in the same domain. Their relationship: A contains B, B contains C. Obviously, A and B, as well as B and C, cannot communicate with each other because they are across domains, but A and C are in the same domain and can communicate with each other. For this reason, we thought of letting page C tell page A how high page B is. Because B and C are also cross-domain and cannot communicate with each other, it is not feasible to directly use window.parent.document.body.scrollHeight in page C. Therefore, we can only let page B calculate its own height, and then tell page C through some method, and then page C tells page A. One method here is to generate an Iframe node on page B, then set its src attribute, append a parameter to this address, that is, the height calculated by page B, and then page C can get the address in the address bar through window.location, extract the height value, find page A through window.top, and set the height of the Iframe of page A. The basic principle is this, let's look at the code:
DEMO

Copy code
The code is as follows:

//B page script
//Task: Calculate its actual height, then generate an iframe node, and assign the height as part of the address of the proxy page C to the Src attribute
(function(){
var agent_iframe = document.createElement("iframe"),
b_height = Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);
agent_iframe.src = "http://demo.zhouqicf.com/js/2010/iframe_height/agent_iframe_once.html#" + b_height;
document.body.appendChild(agent_iframe);
agent_iframe.style.display = "none";
})();


Copy code
The code is as follows:

//C page script
//Task: Get the height value in the request address and assign it to the height of the Iframe of page A
window.top.document.getElementById("frame_content_parent").height = parseInt(window.location.hash.substring(1),10);

Cross-domain, word page height changes dynamically

Here, the second and fourth methods are combined. My idea is to use a timer on page B to continuously calculate the height of page B. Once it changes, the src attribute of the iframe tag will be modified immediately. Page C also has a timer that continuously monitors the changes in src and changes the height of the Aiframe tag. It should be noted that simply changing the anchor value after the src attribute (such as "#1234") will not refresh the page or re-request it, which is why a timer is added to page C.


Copy code
The code is as follows:

//B page script
(function(){
var getHeight = function(){
return Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);
};
var preHeight = getHeight(),
agent_iframe;
var createIframe = function(height){
agent_iframe = document.createElement("iframe");
agent_iframe.style.height = "0";
agent_iframe.style.width = "0";
agent_iframe.style.border = "none";
agent_iframe.src = "http://demo.zhouqicf.com/js/2010/iframe_height/agent_iframe.html#" + height;
document.body.appendChild(agent_iframe);
}
createIframe(preHeight);
var checkHeight = function(){
var currentHeight = getHeight();
if(currentHeight != preHeight){
agent_iframe.src = "http://demo.zhouqicf.com/js/2010/iframe_height/agent_iframe.html#" + currentHeight;
preHeight = currentHeight;
}
setTimeout(checkHeight,500);
}
setTimeout(checkHeight,500);
})();


Copy code
The code is as follows:

//C page script
(function(){
var preHeight = parseInt(window.location.hash.substring(1),10),
ifrmae = window.top.document.getElementById("frame_content_parent");
ifrmae.height = preHeight;
setInterval(function(){
var newHeight = parseInt(window.location.hash.substring(1),10);
if (newHeight !== preHeight){
ifrmae.height = newHeight;
preHeight = newHeight;
}
},500);
})();

There is another solution here, which is to let the iframe re-request each time, so that page C does not need a timer, but if the height is calculated twice, it will cause the value of the src attribute to be the same, so the browser is likely to not re-request the page, and the script in page C will not run. It's easy to fix this problem by adding a random number parameter to each calculated src attribute. For example, http://demo.zhouqicf.com/js/2010/iframe_height/agent_iframe.html?temp=123123423712937#1563


Copy code
The code is as follows:

//B page key script
agent_iframe.src = "http://demo.zhouqicf.com/js/2010/iframe_height/agent_iframe.html?a=" + Math.random() + "#" + currentHeight;
//C page script
window.top.document.getElementById("frame_content_parent").height = parseInt(window.location.hash.substring(1),10);

<<:  Detailed explanation of the reasons and solutions for floating elements to collapse the height of their parent elements

>>:  Textarea text area width and height width and height automatic adaptation implementation code

Recommend

How to implement rounded corners with CSS3 using JS

I found an example when I was looking for a way t...

Detailed explanation of MySQL basic operations (Part 2)

Preface This article contains 1. Several major co...

4 ways to avoid duplicate insertion of data in Mysql

The most common way is to set a primary key or un...

MySQL joint table query basic operation left-join common pitfalls

Overview For small and medium-sized projects, joi...

A detailed introduction to Linux memory management and addressing

Table of contents 1. Concept Memory management mo...

How to use Greek letters in HTML pages

Greek letters are a very commonly used series of ...

Pure CSS3 realizes the effect of div entering and exiting in order

This article mainly introduces the effect of div ...

How to run the react project on WeChat official account

Table of contents 1. Use the a tag to preview or ...

React implements multi-component value transfer function through conetxt

The effect of this function is similar to vue的pro...

Vue-cli creates a project and analyzes the project structure

Table of contents 1. Enter a directory and create...

How to configure /var/log/messages in Ubuntu system log

1. Problem Description Today I need to check the ...

Getting Started Guide to Converting Vue to React

Table of contents design Component Communication ...

Detailed example of mysql similar to oracle rownum writing

Rownum is a unique way of writing in Oracle. In O...