使用iframe加載其他頁面的時候,需要自適應iframe的高度
這里加載了兩個不同內容高度的頁面至iframe中
1. 沒有設置高度
<div class="iframe-wrapper"> <iframe name="iframe1" src="iframe1.html" frameborder="0" width="100%"></iframe> <iframe name="iframe2" src="iframe2.html" frameborder="0" width="100%"></iframe> </div>
默認長這樣

有滾動條,可以看到iframe並不會因為內容高度自動撐開
2. 顯示地設置高度
<div class="iframe-wrapper"> <iframe name="iframe1" src="iframe1.html" frameborder="0" width="100%" height="300px"></iframe> <iframe name="iframe2" src="iframe2.html" frameborder="0" width="100%" height="300px"></iframe> </div>

內容長這樣,但可以看到,高度定死了,沒有自適應
3. 在onload事件觸發時,根據body的高度自適應iframe的高度
<div class="iframe-wrapper"> <iframe name="iframe1" onload="this.height=this.contentWindow.document.body.scrollHeight" src="iframe1.html" frameborder="0" width="100%"></iframe> <iframe name="iframe2" onload="this.height=iframe2.document.body.scrollHeight" src="iframe2.html" frameborder="0" width="100%"></iframe> </div>
注意到這里的 this.contentWindow 其實就類似與下方的 name值對應的iframe2,兩種引用方式是等價的

可以發現,高度雖然能自適應,不過只支持高度了“從小到大”的自適應
如iframe2的內容比iframe1的高,后者動態加載出前者能自適應,但前者動態加載出后者就不行了,這種高度減小不了
最后的解決辦法是
4. 在onload事件中動態設置高度為body高度之前,先將原高度還原為auto或空值
可以用setTimeout(fn,0)將高度設置放到下一輪事件循環中執行,或者在 onbeforeunload 事件中先把高度設置為auto
setTimeout
var iframes = document.getElementsByTagName('iframe'); for (var i = 0, j = iframes.length; i < j; ++i) { // 放在閉包中,防止iframe觸發load事件的時候下標不匹配 (function(_i) { iframes[_i].onload = function() { // 提前還原高度 this.setAttribute('height', 'auto'); // 或設為'' // 再在下一輪事件循環中設置新高度 setTimeout(function() { iframes[_i].setAttribute('height', iframes[_i].contentWindow.document.body.scrollHeight); }, 0); } })(i); }
onbeforeunload
var iframes = document.getElementsByTagName('iframe'); for (var i = 0, j = iframes.length; i < j; ++i) { // 放在閉包中,防止iframe觸發load事件的時候下標不匹配 (function(_i) { iframes[_i].onload = function() { this.contentWindow.onbeforeunload = function() { iframes[_i].setAttribute('height', 'auto'); }; this.setAttribute('height', this.contentWindow.document.body.scrollHeight); }; })(i); }

基本ok了,不過偶爾(可能是電腦卡了?)會看到些抖動閃動的情況
5. 要避免這個情況,可暫時將它隱藏
先設置display為none,再設置為block;或者先設置visibility為hidden,再設置為visible 。 用visibility看起來變化地更自然一點
setTimeout
var iframes = document.getElementsByTagName('iframe'); for (var i = 0, j = iframes.length; i < j; ++i) { // 放在閉包中,防止iframe觸發load事件的時候下標不匹配 (function(_i) { iframes[_i].onload = function() { this.style.visibility = 'hidden'; // this.style.display = 'none'; // 提前還原高度 this.setAttribute('height', 'auto'); // 或設為'' // 再在下一輪事件循環中設置新高度 setTimeout(function() { iframes[_i].setAttribute('height', iframes[_i].contentWindow.document.body.scrollHeight); iframes[_i].style.visibility = 'visible'; // iframes[_i].style.display = 'block'; }, 0); } })(i); }
onbeforeunload
var iframes = document.getElementsByTagName('iframe'); for (var i = 0, j = iframes.length; i < j; ++i) { // 放在閉包中,防止iframe觸發load事件的時候下標不匹配 (function(_i) { iframes[_i].onload = function() { this.contentWindow.onbeforeunload = function() { iframes[_i].style.visibility = 'hidden'; // iframes[_i].style.display = 'none'; iframes[_i].setAttribute('height', 'auto'); }; this.setAttribute('height', this.contentWindow.document.body.scrollHeight); this.style.visibility = 'visible'; // this.style.display = 'block'; }; })(i); }
