让动态的 iframe 内容高度自适应

使用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);
        }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏超然的博客

vue—你必须知道的

不要在实例属性或者回调函数中(例如,vm.$watch('a', newVal => this.myMethod())使用箭头函数。因为箭头函数会绑定父级上下文...

16420
来自专栏python3

tkinter -- Menu

程序每次打印出当前选中的语言,与 Checkbutton 不同的是,同一个组内只有一个处于选中状态

10130
来自专栏积累沉淀

JavaScript 事件对象

一.事件对象 事件处理三部分组成:对象.事件处理函数=函数。例如:单击文档任意处。 document.onclick = function () { alert...

216100
来自专栏柠檬先生

VUE 入门基础(2)

二,起步 引用方式可以使用  vue-cli     <script src="https://unpkg.com/vue/dist/vue.js"></scr...

23470
来自专栏从零开始学 Web 前端

从零开始学 Web 之 jQuery(七)事件冒泡,事件参数对象,链式编程原理

事件冒泡:当一个元素触发某个事件的时候,会把这个事件传播到其父元素,一直到顶层元素。

14640
来自专栏前端知识分享

第79天:jQuery事件总结(二)

       上一篇讲到jQuery中的事件,深入学习了加载DOM和事件绑定的相关知识,这篇主要深入讨论jQuery事件中的合成事件、事件冒泡和事件移除等内容。

12620
来自专栏编程坑太多

事件对象的使用、属性和方法

13430
来自专栏用户2442861的专栏

CSS基础(三):选择器

复合选择器, 由两个选择器直接构成,第一个必须是元素选择器,第二个必须是类选择器和ID选择器,这两个选择器之间不能有空格。

7210
来自专栏Python攻城狮

Javascript(2)-js进阶

备注:如果父元素进行了relative/absolute定位,offsetTop/offsetLeft就是相对父元素的顶部和左边的距离,如果父元素默认定位,就是...

26530
来自专栏从零开始学 Web 前端

从零开始学 Web 之 DOM(二)对样式的操作,获取元素的方式

14740

扫码关注云+社区

领取腾讯云代金券