自适应iframe高度

使用iframe嵌入页面很方便,但必须在父页面指定iframe的高度。如果iframe页面内容的高度超过了指定高度,会出现滚动条,很难看。

如何让iframe自适应自身高度,让整个页面看起来像一个整体?

在HTML5之前,有很多使用JavaScript的Hack技巧,代码量大,而且很难通用。随着现代浏览器引入了新的ResizeObserver API,解决iframe高度问题就变得简单了。

我们假设父页面是index.html,要嵌入到iframe的子页面是target.html,在父页面中,先向页面添加一个iframe

ini 复制代码
const iframe1 = document.createElement('iframe');
iframe1.src = 'target.html';
iframe1.onload = autoResize;
document.getElementById('sameDomain').appendChild(iframe1);

iframe载入完成后,触发onload事件,然后自动调用autoResize()函数:

ini 复制代码
function autoResize(event) {
    // 获取iframe元素:
    const iframeEle = event.target;
    // 创建一个ResizeObserver:
    const resizeRo = new ResizeObserver((entries) => {
        let entry = entries[0];
        let height = entry.contentRect.height;
        iframeEle.style.height = height + 'px';
    });
    // 开始监控iframe的body元素:
    resizeRo.observe(iframeEle.contentWindow.document.body);
}

通过创建ResizeObserver,我们就可以在iframebody元素大小更改时获得回调,在回调函数中对iframe设置一个新的高度,就完成了iframe的自适应高度。

跨域问题

ResizeObserver很好地解决了iframe的监控,但是,当我们引入跨域的iframe时,上述代码就失效了,原因是浏览器阻止了跨域获取iframebody元素。

要解决跨域的iframe自适应高度问题,我们需要使用postMessage机制,让iframe页面向父页面主动报告自身高度。

假定父页面仍然是index.html,要嵌入到iframe的子页面是http://xyz/cross.html,在父页面中,先向页面添加一个跨域的iframe

ini 复制代码
const iframe2 = document.createElement('iframe');
iframe2.src = 'http://xyz/cross.html';
iframe2.onload = autoResize;
document.getElementById('crossDomain').appendChild(iframe2);

cross.html页面中,如何获取自身高度?

我们需要现代浏览器引入的一个新的MutationObserver API,它允许监控任意DOM树的修改。

cross.html页面中,使用以下代码监控body元素的修改(包括子元素):

php 复制代码
// 创建MutationObserver:
const domMo = new MutationObserver(() => {
    // 获取body的高度:
    let currentHeight = body.scrollHeight;
    // 向父页面发消息:
    parent.postMessage({
        type: 'resize',
        height: currentHeight
    }, '*');
});
// 开始监控body元素的修改:
domMo.observe(body, {
    attributes: true,
    childList: true,
    subtree: true
});

iframe页面的body有变化时,回调函数通过postMessage向父页面发送消息,消息内容是自定义的。在父页面中,我们给window添加一个message事件监听器,即可收取来自iframe页面的消息,然后自动更新iframe高度:

ini 复制代码
window.addEventListener('message', function (event) {
    let eventData = event.data;
    if (eventData && eventData.type === 'resize') {
        iframeEle.style.height = eventData.height + 'px';
    }
}, false);

使用现代浏览器提供的ResizeObserverMutationObserver API,我们就能轻松实现iframe的自适应高度。

转载自:mp.weixin.qq.com/s/8NmYRzPlT...**

相关推荐
7ayl12 分钟前
Vue3 - Reactivity的核心流程
前端·vue.js
The 旺13 分钟前
【AI编程实战】零基础用ChatGPT+Cursor开发完整Web应用:30分钟从idea到上线
前端·chatgpt·ai编程
sulikey24 分钟前
Qt 入门简洁笔记:信号与槽
前端·c++·笔记·qt·前端框架·1024程序员节·qt框架
袁煦丞28 分钟前
安卓旧机变服务器,KSWEB部署Typecho博客并实现远程访问:cpolar内网穿透实验室第645个成功挑战
前端·程序员·远程工作
爱抽烟的大liu29 分钟前
iOS进阶1-combine
前端
俩毛豆30 分钟前
【图片】【编缉】图片增加水印(通过组件的Overlay方法增加水印)
前端·harmonyos
gustt30 分钟前
JS 变量那些坑:从 var 到 let/const 的终极解密
前端·javascript
出师未捷的小白31 分钟前
[NestJS] 手摸手~工作队列模式的邮件模块解析以及grpc调用
前端·后端
Z_B_L1 小时前
问题记录--elementui中el-form初始化表单resetFields()方法使用时出现的问题
前端·javascript·vue.js·elementui·1024程序员节
袁煦丞1 小时前
PandaWiki开源知识库系统破解内网限制:cpolar内网穿透实验室第616个成功挑战
前端·程序员·远程工作