动态调整 iframe 大小

Posted

技术标签:

【中文标题】动态调整 iframe 大小【英文标题】:Dynamically resize iframe 【发布时间】:2014-03-19 02:13:52 【问题描述】:

情况: 我正在研究一种涉及典型 html/CSS 组合的响应式设计。除了在 div 内有 iframe 的情况下,一切都运行良好。 iframe 应自动调整为父 div 的大小。纯粹的 css 解决方案尚未出现,因此我将使用 JQuery 方法。它工作得很好,除了在一种情况下,从较小的宽度调整到较大宽度的屏幕。

HTML:

<div class="container">
    <iframe class="iframe-class" src="http://www.cnn.com/"></iframe>
</div>

CSS:

.container 
    width: 100%;
    height: 250px;

.iframe-class 
    width: 100%;
    height: 100%;
    border: 1px solid red;
    overflow: auto;

Javascript:

$(function () 
    setIFrameSize();
    $(window).resize(function () 
        setIFrameSize();
    );
);

function setIFrameSize() 
    var ogWidth = 700;
    var ogHeight = 600;
    var ogRatio = ogWidth / ogHeight;

    var windowWidth = $(window).width();
    if (windowWidth < 480) 
        var parentDivWidth = $(".iframe-class").parent().width();
        var newHeight = (parentDivWidth / ogRatio);
        $(".iframe-class").addClass("iframe-class-resize");
        $(".iframe-class-resize").css("width", parentDivWidth);
        $(".iframe-class-resize").css("height", newHeight);
     else 
        // $(".iframe-class-resize").removeAttr("width");
        // $(".iframe-class-resize").removeAttr("height");
        $(".iframe-class").removeClass("iframe-class-resize");
    

http://jsfiddle.net/TBJ83/

问题: 随着窗口的尺寸变小,它会不断检查窗口宽度,一旦达到 iframe-class-resize 的类并将宽度和高度设置为该类。随着窗口的大小调整较大,一旦大小达到 480 像素,它就会删除该类。问题是设置宽度和高度属性将它们直接添加到元素而不是类本身。因此,删除类不会删除新的宽度和高度。我尝试使用removeAttr()(上面已注释掉)强制删除属性,但这没有用。

有人看到上面的代码哪里出错了吗?或者关于如何更有效地完成响应式 iframe 的任何建议?所需的主要内容是 iframe 必须在 &lt;div&gt;&lt;/div&gt; 内,并且 div 不一定要定义宽度或高度。理想情况下,父 div 应明确定义宽度和高度,但此站点当前的设置方式并不总是可行的。

补充: 如果以上内容不够清楚,请尝试以下方法重现问题:

在台式机上打开浏览器。我在 Windows 机器上使用 Chrome。不要最大化浏览器。 打开上面的 jsfiddle (http://jsfiddle.net/TBJ83/)。您会注意到 iframe 内容跨越了预览面板的整个宽度。 手动向下调整宽度,直到整个窗口小于 480 像素。此时,iframe 内容将非常小。 手动调整宽度,直到整个窗口为 >> 480 像素。目标是让 iframe 内容重新获得预览面板的整个宽度。相反,由于 .css() 函数将 css 更改直接应用于元素而不是类,因此内容会保留调整后的宽度和高度。

提前致谢!

【问题讨论】:

【参考方案1】:

您可以在大约 30 个字符内完成此操作。变化:

$(".iframe-class").removeClass("iframe-class-resize")

到:

$(".iframe-class").removeClass("iframe-class-resize").css( width : '', height : '' )

这将重置您应用于元素的宽度/高度。当您使用.css() 时,您将传入的任何内容添加到元素的style 属性中。当你传递一个空值时,jQuery 会从元素的 style 属性中移除该属性。

这是一个更新的小提琴:http://jsfiddle.net/TBJ83/3/

编辑

好的,这里对性能进行了一些调整(以及一些其他的做事方式):

$(function () 

    //setup these vars only once since they are static
    var $myIFRAME   = $(".iframe-class"),//unless this collection of elements changes over time, you only need to select them once
        ogWidth     = 700,
        ogHeight    = 600,
        ogRatio     = ogWidth / ogHeight,
        windowWidth = 0,//store windowWidth here, this is just a different way to store this data
        resizeTimer = null;

    function setIFrameSize() 
        if (windowWidth < 480) 

            var parentDivWidth = $myIFRAME.parent().width(),//be aware this will still only get the height of the first element in this set of elements, you'll have to loop over them if you want to support more than one iframe on a page
                newHeight      = (parentDivWidth / ogRatio);

            $myIFRAME.addClass("iframe-class-resize").css( height : newHeight, width : parentDivWidth );
         else 
            $myIFRAME.removeClass("iframe-class-resize").css( width : '', height : '' );
        
    

    $(window).resize(function () 

        //only run this once per resize event, if a user drags the window to a different size, this will wait until they finish, then run the resize function
        //this way you don't blow up someone's browser with your resize function running hundreds of times a second
        clearTimeout(resizeTimer);
        resizeTimer = setTimeout(function () 
            //make sure to update windowWidth before calling resize function
            windowWidth = $(window).width();

            setIFrameSize();

        , 75);

    ).trigger("click");//run this once initially, just a different way to initialize
);

【讨论】:

@jiminy 很高兴为您提供帮助。老实说,您的代码做得很好。您可以通过传入一个对象链接一些调用并组合.css() 调用。您还可以计算一次比率而不是每次调整大小以及限制您的调整大小事件处理程序。除此之外它看起来还不错。您可以简化,但要以改变整个方法为代价,而且节省的费用是微乎其微的。 我不知道,看看代码中有多少个 jQuery 选择器,比如 5 个。这是 5 次解析 DOM 来查找这些项目。我更新了我的,它只做 1 个选择器,然后重用对象。 @gfrobenius 我有点假设类选择器是有原因的,但如果不是,那么你是对的。代码确实假设页面上的单个元素$(".iframe-class").parent().width() 将仅返回单个宽度,用于它找到的第一个与选择器函数匹配的元素。但总而言之,在过去的几年里我做了很多性能测试和很多可用性测试,这些选择器不应该显着减慢脚本。 @Jasper 感谢您的反馈。很高兴知道代码的方向是正确的。 =) 我会看看你的建议。 我会玩弄代码,看看速度是否会成为一个重要问题。感谢你们两位指出这一点。【参考方案2】:

这可以使用纯 CSS 来完成,如下所示:

iframe 
  height: 300px;
  width: 300px;
  resize: both;
  overflow: auto;

将高度和宽度设置为您想要的最小尺寸,它似乎只是增大,而不是缩小。

【讨论】:

太棒了 - 这就是我想要的,而且非常简单! 我不明白为什么上面的 jQuery thing 存在。我用另一个src 测试了小提琴,但它没有用。然后,我删除了所有的 jQuery,只在 CSS 中添加了resize: both,效果很好。【参考方案3】:

我会这样做,代码要短得多:http://jsfiddle.net/TBJ83/2/

<div class="container">
    <iframe id="myframe" src="http://www.cnn.com/"></iframe>
</div>

<script>
$(function () 
    setIFrameSize();
    $(window).resize(function () 
        setIFrameSize();
    );
);

function setIFrameSize() 
    var parentDivWidth = $("#myframe").parent().width();
    var parentDivHeight = $("#myframe").parent().height();
    $("#myframe")[0].setAttribute("width", parentDivWidth);
    $("#myframe")[0].setAttribute("height", parentDivHeight);

</script>

我这样做是为了提高阅读能力,但你可以让它更短更快......

function setIFrameSize() 
    f = $("#myframe");
    f[0].setAttribute("width", f.parent().width());
    f[0].setAttribute("height", f.parent().height());

一个选择器,因此您只需查看 DOM 一次而不是多次。

【讨论】:

当宽度低于 480 像素时,该小提琴似乎不尊重硬编码的纵横比。 这在我的情况下最终不起作用。但是,我喜欢它的想法,我仍然会记住它以供将来参考。谢谢! 这非常适用于可调整大小的容器我需要一个嵌入式 iframe 来完全填充并在其中保持响应 -- 非常感谢。【参考方案4】:

对于那些使用 Prestashop 的人,这就是我使用代码的方式。

在 cms.tpl 文件中我添加了以下代码:

if $cms->id==2
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js?ver=1.3.2'></script>
<script type="text/javascript" src='../themes/myheme/js/formj.js'></script>
<div style="width: 100%; height: 800px;">
<iframe style=" width: 100%; height: 100%; border: overflow: auto;" src="https://cnn.com"></iframe>
</div>
/if

然后新建一个js文件:formj.js并添加如下代码:

$(function () 

    //setup these vars only once since they are static
    var $myIFRAME   = $(".iframe-class"),//unless this collection of elements changes over time, you only need to select them once
        ogWidth     = 970,
        ogHeight    = 800,
        ogRatio     = ogWidth / ogHeight,
        windowWidth = 0,//store windowWidth here, this is just a different way to store this data
        resizeTimer = null;

    function setIFrameSize() 
        if (windowWidth < 480) 

            var parentDivWidth = $myIFRAME.parent().width(),//be aware this will still only get the height of the first element in this set of elements, you'll have to loop over them if you want to support more than one iframe on a page
                newHeight      = (parentDivWidth / ogRatio);

            $myIFRAME.addClass("iframe-class-resize").css( height : newHeight, width : parentDivWidth );
         else 
            $myIFRAME.removeClass("iframe-class-resize").css( width : '', height : '' );
        
    

    $(window).resize(function () 

        //only run this once per resize event, if a user drags the window to a different size, this will wait until they finish, then run the resize function
        //this way you don't blow up someone's browser with your resize function running hundreds of times a second
        clearTimeout(resizeTimer);
        resizeTimer = setTimeout(function () 
            //make sure to update windowWidth before calling resize function
            windowWidth = $(window).width();

            setIFrameSize();

        , 75);

    ).trigger("click");//run this once initially, just a different way to initialize
);

【讨论】:

以上是关于动态调整 iframe 大小的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript iframe动态调整大小

iframe动态调整大小

将 iframe 内容高度设置为动态自动调整大小

根据动态内容动态调整 iframe 高度

跨域动态设置 iframe 高度

根据内容动态调整 iframe 高度