Динамическое изменение размера iframe

ситуация: Я работаю над адаптивным дизайном, который включает типичную комбинацию 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 px. Проблема в том, что установка атрибутов width и height добавляет их непосредственно к элементу, а не к самому классу. Таким образом удаление класса не удаляет новую ширину и высоту. Я попытался принудительно удалить атрибуты, используя removeAttr() (комментарий выше), но это не сработало.

кто-нибудь видит, где код выше пошел не так? Или какие-либо предложения о том, как добиться более эффективного использования отзывчивого iframe? Главное, что требуется, чтобы iframe должен быть внутри <div></div> и div может не обязательно иметь определенную ширину или высоту. В идеале Родительский div должен иметь ширину и высоту, явно определенные, но способ настройки этого сайта в настоящее время не всегда будет возможен.

дополнительные: В случае, если выше не было достаточно ясно, попробуйте следующее, чтобы воспроизвести проблему:

  • откройте браузер на настольном компьютере. Я использую Chrome на компьютер Windows. Не разворачивайте браузер.
  • откройте jsfiddle выше (http://jsfiddle.net/TBJ83/). Вы заметите, что содержимое iframe охватывает всю ширину панели предварительного просмотра.
  • вручную измените ширину вниз, пока все окно не будет
  • вручную измените ширину резервной копии, пока все окно не будет >> 480px. Цель данного содержимого iframe в вернуть всю ширину панели предварительного просмотра. Вместо этого содержимое сохраняет измененную ширину и высоту с момента .css() функция применяет изменения css непосредственно к элементам, а не к классам.

спасибо заранее!

4 ответов


вы можете сделать это примерно за 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
});

вот как я бы это сделал, код намного короче: 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 только один раз, а не несколько раз.


для тех, кто использует 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
});

Это можно сделать с помощью чистого CSS, как показано ниже:

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

установите высоту и ширину в минимальный размер, который вы хотите, он только кажется, растет, а не сжимается.