如何获取跨域iframe高度

【技术研究】如何动态获取跨域iframe高度

引言

iframe是一个“好东西”,但是又会带给你很多头疼的“问题”,特别是在ios的兼容性问题。在ios当中,iframe里的页面不会随着外层的网页大小自适应弹性缩放。相比之下,PC浏览器浏览器和安卓的浏览器则是可以实现缩放,这导致了差异性。这时候第一时刻,想到的是兼容的写法。专门针对ios专门设置iframe的scrolling属性为“no”,其他浏览器为“yes”,如下方源码。但是如果iframe子页面中存在响应式部件tab,高度进行变化,则会引起重绘重排,导致页面突然跳到顶部。

<div id="url-wrapper"></div>
html, body{
    height: 100%;
}

#url-wrapper{
    margin-top: 51px;
    height: 100%;
}

#url-wrapper iframe{
    height: 100%;
    width: 100%;
}

#url-wrapper.ios{
    overflow-y: auto;
    -webkit-overflow-scrolling:touch !important;
    height: 100%;
}

#url-wrapper.ios iframe{
    height: 100%;
    min-width: 100%;
    width: 100px;
    *width: 100%;
}
function create_iframe(url){

    var wrapper = jQuery('#url-wrapper');

    if(navigator.userAgent.match(/(iPod|iPhone|iPad)/)){
        wrapper.addClass('ios');
        var scrolling = 'no';
    }else{
        var scrolling = 'yes';
    }

    jQuery('<iframe>', {
        src: url,
        id:  'url',
        frameborder: 0,
        scrolling: scrolling
    }).appendTo(wrapper);
}

上述的兼容写法能解决部分网站的问题,但是如果是响应式网页,页面跳动的情况还是会出现问题的。

随着技术的发展,iframe一般都是萎了满足跨域的页面。受限于浏览器的同源政策,父页面是没法跨域获取子网页的高度或者宽度。这时候,我们可能考虑将iframe的高和宽“定死”。跨域交换iframe内外的数据的方法有以下两种,一种是中间代理页面,一种是h5的API--postMessage。

中间代理页面

参考iframe高度自适应的6个方法的最后一种方法,这种方法是建立了在两个页面中一个中间代理层。原理很简单,用代理层网页地址的hash值传高度和宽度。假设www.a.com域名下的一个页面a.html要包含www.b.com下的一个页面b.html。这时,我们需要在a域名下添加一个agent.html,代理层的代码如下,放置在自己的服务器。

//agent.html
<script type="text/javascript">
    var other = window.parent.parent.document.getElementById("other");
    var hash_url = window.location.hash;
    if (hash_url.indexOf("#") >= 0) {
        var hash_width = hash_url.split("#")[1].split("|")[0] + "px";
        var hash_height = hash_url.split("#")[1].split("|")[1] + "px";
        other.style.width = hash_width;
        other.style.height = hash_height;
    }
</script>

而它是被iframe目标页面所引用,iframe把高度和宽度值组织好到代理页面的链接。由于链接的调用不受跨域的限制,也算是走了个“后门”,把你想要的值“偷偷”传到代理页面上。而代理页面和主页面同源,不构成跨域,所以避免了浏览器的跨域限制。我们还需要在iframe目标页面添加一段代码,就是把添加一个iframe把数据往链接上拼接。在b.html的尾部加上这段js。

//b.html
(function autoHeight() {
    var b_width = document.body.clientWidth;
    var b_height = document.body.clientHeight;
    var agent = document.getElementById("agent");
    agent.src = agent.src + "#" + b_width + "|" + b_height;  // 这里通过hash传递b.htm的宽高
})();

而在a.html还是原封不动的那个iframe就可以了。

<!--a.html-->
<iframe src="./othersite.html" id="other" frameborder="0" scrolling="no" style="border:0px;"></iframe>

源码参考brandonxiang/iframe-height

postMessage

有些人觉得上面的方法非常难理解,因为中间代理层的缘故,增加了请求量,影响了加载效率。

随着HTML5 API的发展,postMessage是不同的html页面之间进行数据通信的方法,大大简化了上述方法的步骤。

在b.html中添加一段代码,在它加载完成后,往父页面跨域发送自己的高和宽,并且可以限制你发送的父网站的ip地址,大大保证安全性。

//b.html
document.addEventListener('DOMContentLoaded', function () {
    var tbody = document.body
    var width = tbody.clientWidth
    var height = tbody.clientHeight
    window.parent.postMessage({ height: height, width: width }, '*')
}, false)

还需要在a.html网站添加一个事件监听,获取iframe内的b.html发送的高与宽,从而设置父页面的iframe的高与宽。

//a.html
var frame = document.getElementById('other')
window.addEventListener('message', function(e){
    frame.style.height = e.data.height+'px'
    frame.style.width = e.data.width+'px'
})

源码参考brandonxiang/iframe-height

总结

相比之下,第二种方法会比较简单和有效。但是由于跨域限制,你不得不要求对方添加一段代码去“消除”跨域限制,也是出于安全性不得已的实现方法。

总的来说,iframe在移动端受非常多的限制,尽可能地慎用。

参考

跨域iframe高度自适应的多种方法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,076评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,658评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,732评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,493评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,591评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,598评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,601评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,348评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,797评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,114评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,278评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,953评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,585评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,202评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,180评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,139评论 2 352

推荐阅读更多精彩内容

  • 1. 什么是跨域? 跨域一词从字面意思看,就是跨域名嘛,但实际上跨域的范围绝对不止那么狭隘。具体概念如下:只要协议...
    w_zhuan阅读 513评论 0 0
  • 来吧,少年,今天还能看文章学习的,一多半都是单身贵族,看朋友圈还会被虐,不如学习,上街还会被虐,不如学习,痛并快乐...
    范小饭_阅读 7,938评论 3 24
  • 1. 什么是跨域? 跨域一词从字面意思看,就是跨域名嘛,但实际上跨域的范围绝对不止那么狭隘。具体概念如下:只要协议...
    他在发呆阅读 822评论 0 0
  • 音频:白天就循环下之前的peppa,海尼曼,牛津树 视频:2aU7 玩:2aU7 分级:新开8本牛津树+eric ...
    麦太_ebbe阅读 174评论 0 0
  • 从来没有甘心驻足的风 却有无数想和风私奔的风筝 风筝割断连接大地的细长脐带 扑向心旷神怡的蓝 为什么飞也飞不高,追...
    子夜玄白阅读 240评论 3 4