Chrome 154 响应式iframe|frame-sizing原生适配详解

AI 概述
Chrome154 Beta推出原生响应式iframe,通过父CSS`frame-sizing:content-height`与子页面meta双向授权,自动计算页面加载完成时的初始高度,替代传统ResizeObserver+postMessage方案的首次通信。该能力仅在load时计算一次,无法监听后续动态内容变更。静态内嵌场景可使用,异步渲染页面仍需保留JS通信;生产要限制可信源并做好浏览器兼容。
目录
文章目录隐藏
  1. iframe 有了响应式尺寸
  2. 为什么要两边同时授权?
  3. 它并不会持续跟随内容变化
  4. 为什么浏览器不持续监听?
  5. postMessage 还能删吗?
  6. 哪些场景不能使用?
  7. 最后的判断
  8. 最后

Chrome 154 响应式 iframe|frame-sizing 原生适配详解

做过 iframe 自适应高度开发的前端应该都深有体会:传统靠 ResizeObserver + postMessage 父子通信适配高度的方案,能用但非常繁琐。不仅要双向写代码、处理跨域校验,还要规避频繁刷新、布局抖动等各种坑。随着 Chrome 154 版本更新,浏览器终于原生支持响应式 iframe 尺寸适配,大幅简化了开发成本,但很多人容易误解它的能力边界。今天结合实测带大家吃透这项新特性,讲清优势、局限和生产落地方案。

前端在做 iframe 嵌入的小伙伴,大概都写过这样的代码:

const observer = new ResizeObserver(() => {
  window.parent.postMessage({
    type: 'resize',
    height: document.documentElement.scrollHeight
  }, '*');
});

observer.observe(document.body);

父页面再监听消息:

window.addEventListener('message', event => {
  iframe.style.height = `${event.data.height}px`;
});

这套方案能用,但一点也不省心。

你要约定消息格式、验证来源、处理异步内容变化,还得防止频繁测量、循环更新和异常高度。

更麻烦的是,这段代码通常需要父页面和子页面各维护一半。

到了 Chrome 154,浏览器终于开始原生处理这个问题了。

iframe 有了响应式尺寸

Chrome 154 Beta 新增了 responsively-sized iframe。

简单理解就是:

iframe 可以根据子文档的布局溢出尺寸,确定自己在父页面中的高度。

以前,即使 iframe 里的内容有 800px 高,如果没有显式设置尺寸,iframe 默认仍然只有大约 150px,剩余内容只能通过内部滚动条访问。

现在父页面可以这样声明:

iframe {
  width: 100%;
  frame-sizing: content-height;
}

子页面同时加入:

<meta
  name="responsive-embedded-sizing"
  content="allow-origins=*"
>

当两个页面都明确同意后,浏览器会在子文档加载完成时读取它的自然高度,并用这个高度参与父页面布局。

假设子页面内容高 420px,那么 iframe 不再停留在默认的 150px,而是自动变成约 420px。

不需要先测量 scrollHeight,也不需要为了初始高度发送一条 postMessage。

为什么要两边同时授权?

因为 iframe 不只是一个布局容器,它还是一个安全边界。

尤其在跨域场景中,父页面如果能够随意读取子页面内容所产生的尺寸变化,就可能把尺寸当成一条侧信道,用来推断子页面状态。

例如:

  • 用户登录和未登录时,页面高度不同;
  • 有权限和无权限时,展示内容不同;
  • 查询结果数量不同,页面高度也不同。

因此,这项能力没有被设计成父页面单方面开启。

它采用了双向授权:

父页面:frame-sizing: content-height
                    ↓
子页面:responsive-embedded-sizing
                    ↓
浏览器:允许按内容计算 iframe 高度

父页面通过 CSS 表示“我希望按照内容定高”,子页面通过 meta 表示“我允许自己的自然尺寸被用于外部布局”。

这套机制同时适用于同源和跨域 iframe。

不过在真实项目中,不建议直接照抄:

content="allow-origins=*"

如果嵌入关系是固定的,应该尽量限制允许的父页面来源,并配合服务端的 CSP frame-ancestors,只允许可信站点嵌入。

它并不会持续跟随内容变化

这是最容易产生误解的地方。

“响应式 iframe”听上去很像:

子页面高度发生变化,iframe 就会一直自动跟着变化。

但 Chrome 154 当前提供的并不是这种能力。

浏览器只会在子文档触发 load 时计算一次自然高度。

加载完成以后,子页面再发生这些变化:

  • 接口返回后渲染列表;
  • 评论继续加载;
  • 图片完成懒加载;
  • 展开折叠区域;
  • 字体加载导致重新排版;
  • 无限滚动追加内容;
  • 前端路由切换页面。

都不会让 iframe 再次自动计算高度。

我用 Chrome 154 Beta 做了一个跨源实验:

父页面端口:4173
子页面端口:4174

子页面加载时有 420px 内容,一秒后再异步加入 260px 内容。

实测结果是:

原生响应式 iframe:
初始高度 420px
异步更新后仍为 420px

ResizeObserver + postMessage:
异步更新后变为 680px

也就是说,这项能力解决的是“初始自然尺寸”,还不是“持续内容同步”。

为什么浏览器不持续监听?

这并不是 Chrome 少实现了一步,而是当前方案有意设置的边界。

如果子页面每次布局变化都会影响父页面尺寸,父页面的重新布局又可能改变 iframe 的可用宽度。

宽度变化会让子页面重新换行,进一步改变高度,然后再次触发父页面布局。

整个过程可能变成:

子页面高度变化
    ↓
iframe 高度变化
    ↓
父页面重新布局
    ↓
iframe 宽度变化
    ↓
子页面重新换行
    ↓
子页面高度再次变化

浏览器需要同时面对三个问题:

  • 反复布局带来的性能开销;
  • 页面不断跳动造成的 CLS;
  • 父子页面互相影响形成的无限布局循环。

因此,当前设计选择了更保守的one-shot sizing:只在加载完成时计算一次。

未来可能增加由子页面主动请求重新布局的 JavaScript API,但目前它还只是后续扩展方向。

postMessage 还能删吗?

可以删掉一部分,但不能全部删。

适合直接使用原生能力的场景:

  • 内容在首次加载时已经完整生成;
  • 教程中的静态示例;
  • 服务端渲染完成的营销组件;
  • 高度基本固定的低代码组件;
  • 不会继续追加内容的内嵌文档;
  • 父子页面均由自己或可信合作方控制。

仍然需要动态同步的场景:

  • 评论组件;
  • 聊天记录;
  • 异步搜索结果;
  • 图片或广告延迟加载;
  • 无限滚动列表;
  • 前端路由应用;
  • 用户可以展开和收起的复杂组件。

一个比较现实的迁移策略是:

iframe {
  frame-sizing: content-height;
}

先让支持该能力的浏览器负责初始尺寸。

对于加载后还会持续变化的页面,再保留 ResizeObserver + postMessage:

const notifyParent = () => {
  window.parent.postMessage(
    {
      type: 'iframe:resize',
      height: document.documentElement.scrollHeight
    },
    'https://parent.example.com'
  );
};

const observer = new ResizeObserver(notifyParent);
observer.observe(document.body);

父页面必须验证来源:

window.addEventListener('message', event => {
  if (event.origin !== 'https://child.example.com') {
    return;
  }

  if (event.data?.type !== 'iframe:resize') {
    return;
  }

  iframe.style.height = `${event.data.height}px`;
});

不要在生产环境中随手使用 “*”,也不要只凭一个 height 字段就信任任何页面发送过来的消息。

至少还应考虑:

  • 消息来源校验;
  • 数据结构校验;
  • 高度上下限;
  • 高频消息合并;
  • iframe 销毁后的监听清理;
  • 多个 iframe 的实例标识。

哪些场景不能使用?

首先,如果你无法修改子页面,就无法添加授权 meta,原生响应式尺寸不会生效。

所以很多无法协商的第三方页面,依然不能直接自动撑高。

其次,Fenced Frame 被明确排除在这项能力之外。

最后,Chrome 154 在本文写作时仍处于 Beta 阶段。如果产品需要兼容其他版本和浏览器,就不能把原有方案立即全部删除。

使用前可以先做能力检测:

const supported = CSS.supports(
  'frame-sizing',
  'content-height'
);

但这只能说明浏览器认识该 CSS 属性,不代表子页面已经完成授权。

最后的判断

frame-sizing: content-height不是 iframe 高度治理的终点。

它更像是浏览器终于接管了其中最稳定、也最适合标准化的一段工作:

根据加载完成时的内容,确定 iframe 的初始自然高度。

对于静态内容,它可能真的可以让你删除一套尺寸通信协议。

对于评论、低代码编辑器、异步组件和微前端页面,它只能减少第一次通信,后续变化仍需要应用层处理。

所以这次更准确的结论不是:

iframe 高度终于不用 postMessage 了。

而是:

iframe 的初始高度,终于可以不用 postMessage 了。

完整实验代码已经公开,包含跨源双向授权、异步内容变化和 ResizeObserver + postMessage 对照:

查看 Chrome 154 响应式 iframe 实验

代码状态:已运行。已使用 Chrome 154 Beta 154.0.8037.0 验证。

最后

Chrome 154 带来的 `frame-sizing` 是对传统 iframe 适配方案的绝佳优化,完美解决了页面初始加载高度自适应的痛点,解放了大量冗余代码。但它仅一次性生效、不支持后续动态内容更新的局限,决定了它无法完全替代 ResizeObserver + postMessage 方案。生产环境最稳妥的策略是新旧方案结合,用原生能力处理初始高度,用传统方案兜底动态内容,同时做好跨域校验与安全限制,兼顾开发效率、页面体验和项目安全性。

以上关于Chrome 154 响应式iframe|frame-sizing原生适配详解的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。

「点点赞赏,手留余香」

43

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » Chrome 154 响应式iframe|frame-sizing原生适配详解

发表回复