Web design skills: iframe adaptive height problem

Web design skills: iframe adaptive height problem
Maybe some people have not come across this issue yet, so let me first explain what adaptive height is. The so-called iframe adaptive height means that, based on the consideration of interface aesthetics and interactivity, the iframe's border and scrollbar are hidden, making it impossible to tell that it is an iframe. If the iframe always calls a page with the same fixed height, we can just hard-code the iframe height. If the iframe needs to switch pages, or the included page needs to perform dynamic DOM operations, then the program is required to synchronize the iframe height with the actual height of the included page.
By the way, iframe should only be used when absolutely necessary, as it will bring too much trouble to front-end development.
There are two traditional approaches:
Method 1: After each included page has finished loading its own content, execute JS to obtain the height of this page, and then synchronize the iframe height of the parent page.
Method 2: Execute JS in the onload event of the main page iframe to obtain the height content of the included page, and then synchronize the height.
From the perspective of code maintenance, method 2 is better than method 1, because in method 1, each included page has to introduce the same piece of code to do this, creating many copies.
Both methods only deal with static things, that is, they are only executed when the content is loaded. If JS is used to manipulate the height changes caused by DOM, it is not very convenient.
If we make an Interval in the main window, constantly get the height of the included page, and then synchronize it, wouldn't it be convenient and solve the problem of JS operating DOM? The answer is yes.
Demo page: main page iframe_a.html, included pages iframe_b.htm and iframe_c.html
Main page code example:

Copy code
The code is as follows:

<iframe id="frame_content" src="iframe_b.html" scrolling="no" frameborder="0"></iframe><script type="text/javascript">
function reinitIframe(){
var iframe = document.getElementById("frame_content");
try{
iframe.height = iframe.contentWindow.document.documentElement.scrollHeight;
}catch (ex){}
}
window.setInterval("reinitIframe()", 200);
< /script>

If we keep executing it, will there be any problems with efficiency?
I did a test and opened 5 windows (IE6, IE7, FF, Opera, Safari) at the same time to execute this code. It had no impact on the CPU, even adjusting it to 2ms, and there was no impact (basically maintained at 0% occupancy).
Next, let's talk about the compatibility issues of various browsers and how to get the correct height, mainly comparing body.scrollHeight and documentElement.scrollHeight. Note that this article uses this doctype. Different doctypes should not affect the results, but if your page does not declare a doctype, you should add one first.

Copy code
The code is as follows:

< !DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "<a href="http://www.w3.org/TR/html4/strict.dtd">http://www.w3.org/TR/html4/strict.dtd</a>"> Append the following test code to the main page to output these two values. Code example:
<div><button>Check Height</button></div><script type="text/javascript">
function checkHeight() {
var iframe = document.getElementById("frame_content");
var bHeight = iframe.contentWindow.document.body.scrollHeight;
var dHeight = iframe.contentWindow.document.documentElement.scrollHeight;
alert("bHeight:" + bHeight + ", dHeight:" + dHeight);
}
< /script> When the page is loaded, you can switch an absolutely positioned layer to make the page height change dynamically. If the layer is expanded, it will increase the height of the page. Code example:
<div><button>Toggle Overlay</button>
< /div>
< div style="height:160px;position:relative">
< div id="overlay" style="position:absolute;width:280px;height:280px;display:none;"> </div>
< /div>
< script type="text/javascript">
function toggleOverlay() {
var overlay = document.getElementById('overlay');
overlay.style.display = (overlay.style.display == 'none') ? 'block' : 'none';
}
< /script>

The following lists the test values ​​of the above code in various browsers:

Copy code
The code is as follows:

(bHeight = body.scrollHeight, dHeight = documentElement.scrollHeight, red = wrong value, green = correct value)
/ When the layer is hidden When the layer is expanded
bHeight dHeight bHeight dHeight
IE6 184 184 184 303
IE7 184 184 184 303
FF 184 184 184 303
Opera 181 181 300 300
Safari 184 184 303 184

Ignoring for the moment the fact that Opera has 3 pixels less than the others… you can see that if nothing is absolutely positioned, the two values ​​are equal and it doesn’t matter which one you take.
But if there is, then each browser behaves differently, and no single value is correct. But we can find a rule, that is, taking the maximum value of the two values ​​can be compatible with all browsers. So our main page code needs to be transformed into this:

Copy code
The code is as follows:

function reinitIframe(){var iframe = document.getElementById("frame_content");
try{
var bHeight = iframe.contentWindow.document.body.scrollHeight;
var dHeight = iframe.contentWindow.document.documentElement.scrollHeight;
var height = Math.max(bHeight, dHeight);
iframe.height = height;
}catch (ex){}
}
window.setInterval("reinitIframe()", 200);

In this way, the compatibility problem is basically solved. By the way, not only the absolutely positioned layer will affect the value, but float will also cause the difference between the two values.
If you try the Demo, you will find that, except for IE, in other browsers, when the layer is expanded and then hidden, the height value obtained still remains at the expanded height of 303, rather than the actual value of 184 when it is hidden. This means that after growing taller, it cannot be shrunk back. This phenomenon also occurs when switching between different included pages. When switching from a tall page to a short page, the height obtained is still the tall value.
It can be summarized that when the iframe window height is higher than the actual document height, the height is taken from the window height, and when the window height is lower than the actual document height, the height is taken from the actual document height. Therefore, find a way to set the height to a value lower than the actual document before syncing the height. Therefore, add onload="this.height=100" to the iframe so that it will shrink to a low enough height when the page is loaded, and then synchronize to the same height.
This value is determined in practical applications. It should be short enough but not too short, otherwise there will be obvious flickering in browsers such as FF. The main page cannot monitor the DOM operation, so the height can only be reduced after the DOM operation is completed.
In one of my actual projects, I weighed the cost and benefit and did not do this because the cost was too high to insert this code into each DOM function. In fact, it was not so fatal if the layer shrunk but did not shrink. This was not done in the demo. If any readers have a better approach, please let me know.
This is the final main page code:
[/code]
<iframe id="frame_content" src="iframe_b.html" scrolling="no" frameborder="0"></iframe>
< script type="text/javascript">
function reinitIframe(){
var iframe = document.getElementById("frame_content");
try{
var bHeight = iframe.contentWindow.document.body.scrollHeight;
var dHeight = iframe.contentWindow.document.documentElement.scrollHeight;
var height = Math.max(bHeight, dHeight);
iframe.height = height;
}catch (ex){}
}
window.setInterval("reinitIframe()", 200);
< /script>
[/code]

<<:  The three new indexes added in MySQL 8 are hidden, descending, and functions

>>:  Mac+IDEA+Tomcat configuration steps

Recommend

Ubuntu 15.04 opens mysql remote port 3306

Ubuntu 15.04 opens MySQL remote port 3306. All th...

A brief analysis of controlled and uncontrolled components in React

Table of contents Uncontrolled components Control...

Why can't my tomcat start?

Table of contents Phenomenon: Port usage: Spellin...

Solution to the problem of mysql service starting but not connecting

The mysql service is started, but the connection ...

HTML+CSS+JS to implement the Don't Step on the Whiteboard game

Table of contents Background 1. Thought Analysis ...

Detailed Tutorial on Installing MySQL 5.7 on RedHat 6.5

RedHat6.5 installation MySQL5.7 tutorial sharing,...

File sharing between Ubuntu and Windows under VMware

This article records the method of sharing files ...

MySQL Constraints Super Detailed Explanation

Table of contents MySQL Constraint Operations 1. ...

Using Docker Enterprise Edition to build your own private registry server

Docker is really cool, especially because it'...

How to declare a cursor in mysql

How to declare a cursor in mysql: 1. Declare vari...

MySQL 8.0.24 version installation and configuration method graphic tutorial

This article records the installation and configu...

How to use LibreOffice to convert document formats under CentOS

Project requirements require some preprocessing o...

An article to help you understand Js inheritance and prototype chain

Table of contents Inheritance and prototype chain...

How to make your own native JavaScript router

Table of contents Preface Introduction JavaScript...