最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
详谈Iframe自适应高度实现方法及原理
时间:2022-06-25 14:44:51 编辑:袖梨 来源:一聚教程网
同域、子页面高度不会动态增加
这种情况最简单,直接通过脚本获取字页面实际高度,修改iframe元素高度即可。但有二点必须注意:
如果页面内有绝对定位或者没有清浮动的元素,情况有些复杂,不同浏览器处理结果不同,甚至包括webkit内核的浏览器,具体请看这个demo。所以你要么进行浏览器检测,要么用math.max计算一个最大值,要么你想别的方法。
iframe所包含页面可能非常大,需要很长的加载时间,为此直接计算高度的时候,很可能页面还没下载完,高度计算就会有问题。所以最好在iframe的onload事件中计算高度。这里还要注意的是,ie下必须使用微软事件模型obj.attachevent来绑定onload事件。而别的浏览器直接obj.onload = function(){}也可以。
(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);
}
})();
同域、子页面高度会动态增加
原理与第一种情况一样,多一个计时器,一直检测字页面高度,当子页面高度和iframe的高度不一致时,重新设置iframe的高度。这边也可以加一个try在js出错时,加一个足够的高度。
(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.;
}
}
if(frame.addeventlistener){
frame.addeventlistener("load",function(){setinterval(_resetiframe,200);},false);
}else{
frame.attachevent("onload",function(){setinterval(_resetiframe,200);});
}
})();
同域、子页面高度会动态增加、脚本可能完全失效
第二个例子中,考虑到了脚本出错的情况,但是万一脚本根本不执行了呢,那iframe中的内容就会因为iframe的高度不够而显示不了。为此我们通常事先设置一个足够的高度,为了前端控制方便,我觉得写在css教程文件中比较合适,需要修改时只改css就行了。这里我设置了selector{ }。需要注意的是,写在样式表里的样式,不能直接用node.style[property]来取,对于微软模型,要用node.currentstyle[property](题外话:悲剧的ie模型不支持css伪类),对于w3c模型,要用window.getcomputedstyle(node,null)[property]来取。我这里图方便直接用了yui。
这里又有一个问题,设置iframe的高度大于其包含页面的高度时,各个浏览器的处理不一样。例如在firefox下,必须计算body元素的高度,而html元素的高度等于iframe的高度,然而当恰巧这个页面又有绝对定位、未清浮动元素时,又不能通过body元素来取,显然第一种方法缺点更小一些。具体请看这个demo。
从上面这个demo可以看到,除ie浏览器外,别的浏览器计算出来的都是iframe的高度,即css里设置的#frame_content_parent{ }。而ie计算出来的是iframe所引用页面的实际高度。
#frame_content_parent{ }
(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);
}
})();
跨域
这里提供一个iframe代理的方法,简单地说一下原理。假设有3个页面,分别是主页面a.html,字页面b.html,代理页面c.html。其中a与b是跨域的,而a和c是同域的。它们的关系:a包含b,b包含c。很显然a和b,以及b和c,因为跨域不能相互通信,而a和c同域,可以相互通信。为此我们就想到让c页面告诉a页面,b页面到底有多少高。因为b和c也是跨域的不能相互通信,所以想在c页面中,直接window.parent.document.body.scrollheight这样是行不通的,所以我们只能让b页面自己计算自身的高度,然后通过某种方法告诉c页面,再由c页面告诉a页面。这里的一个方法就是在b页面生成一个iframe节点,然后设置它的src属性,在这个地址上附加一个参数,即b页面计算出来的高度,然后c页面就可以通过window.location获取这个地址栏中的地址,提取出高度值,通过window.top找到a页面,设置a页面的iframe的高度。基本的原理就是这样,看代码吧:
demo
//b页面脚本
//任务:计算其实际高度,然后生成一个iframe节点,将高度作为代理页面c的地址的一部分赋值给src属性
(function(){
var agent_iframe = document.createelement("iframe"),
b_height = math.max(document.documentelement.scrollheight,document.body.scrollheight);
agent_iframe.src = "http://www.111com.net#" + b_height;
document.body.appendchild(agent_iframe);
agent_iframe.style.display = "none";
})();
//c页面脚本
//任务:获取请求地址中的高度值,将其赋值给a页面的iframe的高度
window.top.document.getelementbyid("frame_content_parent").height = parseint(window.location.hash.substring(1),10);
跨域、字页面高度动态变化
这里结合了第2、第4两种方法,我的想法是在b页面通过一个计时器,不停计算b页面的高度,一但变化,马上修改iframe标签的src属性,而c页面也有计时器不断监听src的变化,改变aiframe标签的高度。需要注意的是仅仅修改src属性后面的锚点值(如"#1234"),页面并不会刷新,不会重新请求,这也是在c页面增加计时器的原因。
demo
//b页面脚本
(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.;
agent_iframe.style.;
agent_iframe.style.border = "none";
agent_iframe.src = "http://www.111com.net#" + height;
document.body.appendchild(agent_iframe);
}createiframe(preheight);
var checkheight = function(){
var currentheight = getheight();
if(currentheight != preheight){
agent_iframe.src = "http://www.111com.net#" + currentheight;
preheight = currentheight;
}
settimeout(checkheight,500);
}settimeout(checkheight,500);
})();
//c页面脚本
(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);
})();
这里还有另一种方案,就是让iframe每一次都重新请求,这样c页面就不需要计时器了,但是如果2次计算高度重复的话,就会导致src属性的值相同,这样浏览器就很可能不重新请求该页面了,那么c页面中的脚本也就不运行了。要修复这个问题很简单,只要在每次计算出来的src属性上增加一个随机数的参数就行了。比如http://www.111com.net
//b页面关键脚本
agent_iframe.src = "http://www.111com.net/a.php?a=" + math.random() + "#" + currentheight;
//c页面脚本
window.top.document.getelementbyid("frame_content_parent").height = parseint(window.location.hash.substring(1),10);
相关文章
- 《无限暖暖》天星之羽获得位置介绍 12-20
- 《流放之路2》重铸台解锁方法介绍 12-20
- 《无限暖暖》瞄准那个亮亮的成就怎么做 12-20
- 《无限暖暖》魔气怪终结者完成方法 12-20
- 《无限暖暖》曙光毛团获得位置介绍 12-20
- 《无限暖暖》日光果获得位置介绍 12-20