сделать высоту iframe динамической на основе содержимого внутри JQUERY / Javascript

202

Я загружаю aspx веб-страницу в iframe. Содержимое в Iframe может иметь большую высоту, чем высота iframe. У iframe не должно быть полос прокрутки.

У меня есть divтег- обертка внутри iframe, который в основном весь контент. Я написал несколько jQuery для изменения размера:

$("#TB_window", window.parent.document).height($("body").height() + 50);

где TB_windowdiv, в котором Iframeсодержится

body - тег body aspx в iframe.

Этот скрипт прикреплен к контенту iframe. Я получаю TB_windowэлемент с родительской страницы. Хотя это отлично работает на Chrome, но TB_window рушится в Firefox. Я действительно смущен / потерян на том, почему это происходит.

Karry
источник
что страница .aspx iframe с того же доменного имени?
AlexC
Вы можете проверить, что $ ("body"). height () имеет значение в Firefox?
Майкл Л Уотсон
да .. iframe находится в том же домене, что и страница контейнера
karry
@MichaelLWatson Похоже, что окно просмотра firebug имеет значение 0 для роста ... Chrome действительно имеет значение
karry
Пример угловой
Эдуардо Куомо,

Ответы:

212

Вы можете получить высоту IFRAMEсодержимого с помощью: contentWindow.document.body.scrollHeight

После IFRAMEзагрузки вы можете изменить высоту, выполнив следующие действия:

<script type="text/javascript">
  function iframeLoaded() {
      var iFrameID = document.getElementById('idIframe');
      if(iFrameID) {
            // here you can make the height, I delete it first, then I make it again
            iFrameID.height = "";
            iFrameID.height = iFrameID.contentWindow.document.body.scrollHeight + "px";
      }   
  }
</script>   

Затем на IFRAMEтеге вы подключаете обработчик следующим образом:

<iframe id="idIframe" onload="iframeLoaded()" ...

Некоторое время назад у меня была ситуация, когда мне дополнительно нужно было позвонить iframeLoadedот самого IFRAMEсебя после того, как была отправлена ​​форма. Вы можете сделать это, выполнив следующие действия в IFRAMEскриптах содержимого:

parent.iframeLoaded();
Аристос
источник
153
Он не поддерживает Cross Domain.
Soumya
3
@Soumya Кросс-домен не имеет ничего общего с этим кодом. Существует проблема безопасности, которую вы обходите командой.
Аристос
9
@Soumya Ищите, X-FRAME-OPTIONSчтобы добавить строку как: Response.AddHeader("X-FRAME-OPTIONS", "SAMEORIGIN");илиresponse.addHeader("X-FRAME-OPTIONS", "Allow-From https://some.othersite.com");
Аристос
15
Это решает междоменную проблему определения размера iframe github.com/davidjbradshaw/iframe-resizer
Дэвид Брэдшоу
2
@deebs Вы также можете попробовать перейти iFrameID.height = "";на iFrameID.height = "20px";. Высота iframe в браузере по умолчанию равна 150px, что и ""сбрасывает его обратно.
Philfreo
112

Немного улучшенный ответ Аристосу ...

<script type="text/javascript">
  function resizeIframe(iframe) {
    iframe.height = iframe.contentWindow.document.body.scrollHeight + "px";
  }
</script>  

Затем объявите в своем iframe следующее:

<iframe onload="resizeIframe(this)" ...

Есть два небольших улучшения:

  1. Вам не нужно получать элемент через document.getElementById - так как он у вас уже есть в обратном вызове onload.
  2. Нет необходимости устанавливать значение, iframe.height = ""если вы собираетесь переназначить его в следующем утверждении. Это на самом деле влечет за собой накладные расходы, когда вы имеете дело с элементом DOM.

Редактировать: если содержимое во фрейме постоянно меняется, тогда позвоните:

parent.resizeIframe(this.frameElement); 

изнутри iframe после обновления. Работает для того же происхождения.

Или для автоматического определения:

  // on resize
  this.container = this.frameElement.contentWindow.document.body;

  this.watch = () => {
    cancelAnimationFrame(this.watcher);

    if (this.lastScrollHeight !== container.scrollHeight) {
      parent.resizeIframeToContentSize(this.frameElement);  
    }
    this.lastScrollHeight = container.scrollHeight;
    this.watcher = requestAnimationFrame(this.watch);
  };
  this.watcher = window.requestAnimationFrame(this.watch);
BlueFish
источник
6
Что бы вы сделали, если содержимое фрейма постоянно меняется?
Кевин
Если размер контента продолжает изменяться и / или если ваш iframe предназначен для размещения в других доменах, отличных от домена, из которого iframe перетаскивает страницу, вам нужно будет сделать что-то другое.
BlueFish
4
Для этого ... решение состоит в том, чтобы использовать postMessage и receiveMessage. Я решил эту проблему с помощью github.com/jeffomatic/nojquery-postmessage
BlueFish
Идея состоит в том, чтобы рассчитать новую высоту и отправить сообщение в родительский фрейм, который должен получить сообщение, и соответствующим образом отрегулировать высоту фрейма.
BlueFish
Для меня всегда было мало пикселей, поэтому я придумал следующее: function resizeIframe(iframe) { var size=iframe.contentWindow.document.body.scrollHeight; var size_new=size+20; iframe.height = size_new + "px"; }
Мартин Мюль
56

Я обнаружил, что принятого ответа недостаточно, поскольку X-FRAME-OPTIONS: Allow-From не поддерживается в Safari или Chrome . Вместо этого пошли с другим подходом, который можно найти в презентации Бена Винегара из Disqus. Идея состоит в том, чтобы добавить прослушиватель событий в родительское окно, а затем внутри iframe, использовать window.postMessage, чтобы отправить событие родителю, сказав ему сделать что-то (изменить размер iframe).

Поэтому в родительском документе добавьте прослушиватель событий:

window.addEventListener('message', function(e) {
  var $iframe = jQuery("#myIframe");
  var eventName = e.data[0];
  var data = e.data[1];
  switch(eventName) {
    case 'setHeight':
      $iframe.height(data);
      break;
  }
}, false);

А внутри фрейма напишите функцию для отправки сообщения:

function resize() {
  var height = document.getElementsByTagName("html")[0].scrollHeight;
  window.parent.postMessage(["setHeight", height], "*"); 
}

Наконец, внутри iframe добавьте onLoad в тег body, чтобы запустить функцию изменения размера:

<body onLoad="resize();">
Марти Маллиган
источник
1
Для того, чтобы это работало для меня, я должен был изменить "window.parent" на просто "parent".
программер
Большой! но он загружает только высоту один раз. Если вы хотите, чтобы iframe был действительно отзывчивым, я предпочитаю вызывать метод изменения размера каждую секунду, например так:setInterval(resize, 1000);
Jules Colle
12

Добавьте это в iframe, это работает для меня:

onload="this.height=this.contentWindow.document.body.scrollHeight;"

И если вы используете jQuery, попробуйте этот код:

onload="$(this).height($(this.contentWindow.document.body).find(\'div\').first().height());"
Мохит Анеджа
источник
6

Существует четыре различных свойства, на которые вы можете посмотреть, чтобы получить высоту содержимого в iFrame.

document.documentElement.scrollHeight
document.documentElement.offsetHeight
document.body.scrollHeight
document.body.offsetHeight

К сожалению, все они могут дать разные ответы, и они несовместимы между браузерами. Если вы установите поле для тела в 0, то document.body.offsetHeightлучший ответ. Чтобы получить правильное значение, попробуйте эту функцию; которая берется из библиотеки iframe-resizer, которая также следит за сохранением правильного размера iFrame при изменении содержимого или изменении размера браузера.

function getIFrameHeight(){
    function getComputedBodyStyle(prop) {
        function getPixelValue(value) {
            var PIXEL = /^\d+(px)?$/i;

            if (PIXEL.test(value)) {
                return parseInt(value,base);
            }

            var 
                style = el.style.left,
                runtimeStyle = el.runtimeStyle.left;

            el.runtimeStyle.left = el.currentStyle.left;
            el.style.left = value || 0;
            value = el.style.pixelLeft;
            el.style.left = style;
            el.runtimeStyle.left = runtimeStyle;

            return value;
        }

        var 
            el = document.body,
            retVal = 0;

        if (document.defaultView && document.defaultView.getComputedStyle) {
            retVal =  document.defaultView.getComputedStyle(el, null)[prop];
        } else {//IE8 & below
            retVal =  getPixelValue(el.currentStyle[prop]);
        } 

        return parseInt(retVal,10);
    }

    return document.body.offsetHeight +
        getComputedBodyStyle('marginTop') +
        getComputedBodyStyle('marginBottom');
}
Дэвид Брэдшоу
источник
Это не работает с элементами, которые «свертываются», например, datatables или плавающие div. Высота зависит от того, какой будет нормальная развернутая высота, а не от конечной высоты.
djack109
@ djack109 Скорее всего, что-то в вашем CSS останавливает сокращение элемента на вашей странице
Дэвид Брэдшоу
3

Другие ответы не работали для меня, поэтому я сделал некоторые изменения. Надеюсь, это поможет

$('#iframe').on("load", function() {
    var iframe = $(window.top.document).find("#iframe");
    iframe.height(iframe[0].ownerDocument.body.scrollHeight+'px' );
});
Ravi
источник
2

Вместо того, чтобы использовать javscript / jquery, я нашел самый простой способ:

<iframe style="min-height:98vh" src="http://yourdomain.com" width="100%"></iframe>

Здесь 1vh = 1% от высоты окна браузера. Таким образом, теоретическое значение высоты, которое должно быть установлено, составляет 100vh, но практически 98vh сделал магию.

Бинод
источник
9
Это не учитывает высоту содержимого iframe.
Адриан Поли
Это становится достаточно близко, когда у вас нет простого способа обойти междоменную драму ...
dsghi
2

На всякий случай это кому-нибудь поможет. Я вырывал свои волосы, пытаясь заставить это работать, затем я заметил, что у iframe была запись класса с высотой: 100%. Когда я убрал это, все работало как ожидалось. Поэтому, пожалуйста, проверьте наличие конфликтов CSS.

user8640976
источник
2

Вы также можете добавить повторяющийся requestAnimationFrame в свой resizeIframe (например, из ответа @ BlueFish), который всегда будет вызываться до того, как браузер раскрасит макет, и вы можете обновить высоту iframe, когда его содержимое изменило свою высоту. например, формы ввода, ленивый загруженный контент и т. д.

<script type="text/javascript">
  function resizeIframe(iframe) {
    iframe.height = iframe.contentWindow.document.body.scrollHeight + "px";
    window.requestAnimationFrame(() => resizeIframe(iframe));
  }
</script>  

<iframe onload="resizeIframe(this)" ...

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

user2520818
источник
1
Это очень удобное решение, которое после начального тестирования работает очень хорошо. Я был бы заинтересован в последствиях использования этого.
KFE
Просто столкнулся с делом, Uncaught TypeError: Cannot read property 'scrollHeight' of nullтак как bodyесть null, однако обычно работает.
около
1

Вы можете отослать связанный вопрос здесь - Как сделать ширину и высоту iframe такими же, как у родительского div?

Установить динамическую высоту -

  1. Нам нужно общаться с междоменными iFrames и родителем
  2. Затем мы можем отправить высоту прокрутки / высоту содержимого iframe в родительское окно

И коды - https://gist.github.com/mohandere/a2e67971858ee2c3999d62e3843889a8

Мохан Дере
источник
1

Я использую JQuery и приведенный ниже код работает на меня,

var iframe = $(window.top.document).find("#iframe_id_here");
iframe.height(iframe.contents().height()+'px' );
srijishks
источник
0

Я нашел ответ от Трои, не работал. Это тот же код, переработанный для AJAX:

$.ajax({                                      
    url: 'data.php',    
    dataType: 'json',                             

    success: function(data)
    {
        // Put the data onto the page

        // Resize the iframe
        var iframe = $(window.top.document).find("#iframe");
        iframe.height( iframe[0].contentDocument.body.scrollHeight+'px' );
    }
});
Мартин Лестер
источник
0

Чтобы добавить к окну, которое кажется обрезанным внизу, особенно когда у вас нет прокрутки, я использовал:

function resizeIframe(iframe) {
    var addHeight = 20; //or whatever size is being cut off
    iframe.height = iframe.contentWindow.document.body.scrollHeight + addHeight + "px";
  }
Мэтт Стейси
источник
0

Это полезно, когда вам требуется решение без jquery. В этом случае вы должны попробовать добавить контейнер и установить для него отступ в процентах.

HTML пример кода:

<div class="iframecontainer">
    <iframe scrolling="no" src="..." class="iframeclass"width="999px" height="618px"></iframe>
</div>

Пример кода CSS:

.iframeclass{
    position: absolute;
    top: 0;
    width: 100%;
}

.iframecontainer{
    position: relative;
    width: 100%;
    height: auto;
    padding-top: 61%;
}
Хуан М
источник
0

Простое решение состоит в том, чтобы измерить ширину и высоту области содержимого, а затем использовать эти измерения для расчета процентного содержания нижнего отступа.

В этом случае размеры составляют 1680 x 720 пикселей, поэтому отступ снизу составляет 720/1680 = 0,43 * 100, что составляет 43%.

.canvas-container {    
    position: relative;
    padding-bottom: 43%; // (720 ÷ 1680 = 0.4286 = 43%)
    height: 0;
    overflow: hidden;   
}

.canvas-container iframe {    
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;   
}
Loek
источник
0

Немного улучшенный ответ на BlueFish ...

function resizeIframe(iframe) {
    var padding = 50;
    if (iframe.contentWindow.document.body.scrollHeight < (window.innerHeight - padding))
        iframe.height = iframe.contentWindow.document.body.scrollHeight + "px";
    else
        iframe.height = (window.innerHeight - padding) + "px";
}

Это учитывает высоту экрана Windows (браузер, телефон), который хорош для адаптивного дизайна и фреймов, которые имеют огромную высоту. Заполнение представляет собой заполнение, которое вы хотите выше и ниже фрейма в случае, если оно проходит через весь экран.

Тадей Венгуст
источник
0
jQuery('.home_vidio_img1 img').click(function(){
    video = '<iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>';
    jQuery(this).replaceWith(video);
});

jQuery('.home_vidio_img2 img').click(function(){
    video = <iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>;
    jQuery('.home_vidio_img1 img').replaceWith(video);
    jQuery('.home_vidio_img1 iframe').replaceWith(video);
});

jQuery('.home_vidio_img3 img').click(function(){
    video = '<iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>';
    jQuery('.home_vidio_img1 img').replaceWith(video);
    jQuery('.home_vidio_img1 iframe').replaceWith(video);
});

jQuery('.home_vidio_img4 img').click(function(){
    video = '<iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>';
    jQuery('.home_vidio_img1 img').replaceWith(video);
    jQuery('.home_vidio_img1 iframe').replaceWith(video);
});
Кейур Савсани
источник
0

Пример с использованием PHP htmlspecialchars () + проверка, если высота существует и> 0:

$my_html_markup = ''; // Insert here HTML markup with CSS, JS... '<html><head></head><body>...</body></html>'
$iframe = '<iframe onload="if(this.contentWindow.document.body.scrollHeight) {this.height = this.contentWindow.document.body.scrollHeight;}" width="100%" src="javascript: \''. htmlspecialchars($my_html_markup) . '\'"></iframe>';
jteks
источник
0

просто сделайте позицию контейнера iframe: absolute, и iframe автоматически изменит свою высоту в соответствии с его содержимым

<style>
   .iframe-container {
       display: block;
       position: absolute;
       /*change position as you need*/
       bottom: 0;
       left: 0;
       right: 0;
       top: 0;
   }
   iframe {
       margin: 0;
       padding: 0;
       border: 0;
       width: 100%;
       background-color: #fff;
   }
 </style>
 <div class="iframe-container">
     <iframe src="http://iframesourcepage"></iframe>
 </div>
Хатем Бадави
источник
-1
$(document).height() // - $('body').offset().top

и / или

$(window).height()

См. Вопрос переполнения стека. Как получить высоту элемента тела .

Попробуйте это, чтобы найти высоту тела в jQuery:

if $("body").height()

Не имеет значения, если Firebug . Возможно, это проблема.

Майкл Л Уотсон
источник
Я пытался сделать оба ... это все еще происходит в Firefox. Firefox почему-то не получает window.height () в iframe. Как я уже упоминал, скрипт прикреплен к содержимому Iframe, и я
вызываю