uaktywnij wysokość ramki iframe na podstawie zawartości wewnątrz - JQUERY / Javascript


202

Ładuję stronę internetową aspx w ramce iframe. Zawartość w ramce iframe może mieć większą wysokość niż wysokość ramki iframe. Ramka iframe nie powinna mieć pasków przewijania.

Mam divtag otoki wewnątrz iframe, który w zasadzie jest całą zawartością. Napisałem jQuery, aby zmienić rozmiar:

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

gdzie TB_windowjest div, w którym Iframejest zawarty.

body - znacznik body aspx w ramce iframe.

Ten skrypt jest dołączony do treści iframe. Otrzymuję TB_windowelement ze strony nadrzędnej. Chociaż działa to dobrze w Chrome, ale TB_window zwija się w Firefox. Jestem naprawdę zdezorientowany / zagubiony, dlaczego tak się dzieje.


ta strona iframe .aspx pochodzi z tej samej nazwy domeny?
AlexC

czy możesz sprawdzić $ („body”). wysokość () ma wartość w firefoxie?
Michael L Watson,

tak .. iframe jest w tej samej domenie co strona kontenera
karry

@MichaelLWatson Wygląda na to, że okno zegarka firebug ma wartość wysokości 0 dla wysokości ciała ... Chrome ma jednak wartość
karry

Odpowiedzi:


211

Możesz pobrać wysokość IFRAMEzawartości, używając: contentWindow.document.body.scrollHeight

Po IFRAMEzaładowaniu można zmienić wysokość, wykonując następujące czynności:

<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>   

Następnie na IFRAMEtagu podłączasz moduł obsługi w następujący sposób:

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

Jakiś czas temu miałem sytuację, w której dodatkowo musiałem zadzwonić iframeLoadedod IFRAMEsiebie po złożeniu formularza. Możesz to zrobić, wykonując następujące czynności w IFRAMEskryptach treści:

parent.iframeLoaded();

152
Nie obsługuje w wielu domenach.
Soumya

3
@Soumya Cross domain nie ma nic wspólnego z tym kodem. Występuje problem bezpieczeństwa, który można obejść za pomocą polecenia.
Aristos

9
@Soumya Poszukaj, X-FRAME-OPTIONSaby dodać linię jako: Response.AddHeader("X-FRAME-OPTIONS", "SAMEORIGIN");lubresponse.addHeader("X-FRAME-OPTIONS", "Allow-From https://some.othersite.com");
Aristos

15
To rozwiązuje problem zmiany
David Bradshaw

2
@deebs Możesz także spróbować zmienić iFrameID.height = "";na iFrameID.height = "20px";. Domyślna wysokość ramki iframe w przeglądarce wynosi 150 pikseli, co ""powoduje jej przywrócenie.
philfreo

112

Nieco ulepszona odpowiedź dla Aristosa ...

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

Następnie zadeklaruj w swoim ramce iframe w następujący sposób:

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

Istnieją dwie niewielkie poprawki:

  1. Nie musisz pobierać elementu za pośrednictwem document.getElementById - ponieważ już go masz w wywołaniu zwrotnym onload.
  2. Nie ma potrzeby ustawiania, iframe.height = ""jeśli zamierzasz zmienić przypisanie w następnej instrukcji. Takie postępowanie wiąże się z dodatkowymi kosztami związanymi z elementem DOM.

Edycja: Jeśli zawartość ramki zawsze się zmienia, to wywołaj:

parent.resizeIframe(this.frameElement); 

z poziomu elementu iframe po aktualizacji. Działa dla tego samego pochodzenia.

Lub automatycznie wykryć:

  // 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);

6
Co byś zrobił, gdyby zawartość ramki zawsze się zmieniała?
Kevin

Jeśli rozmiar zawartości ciągle się zmienia i / lub jeśli element iframe jest przeznaczony do umieszczania w domenach innych niż domena, z której element iframe pobiera stronę, musisz zrobić coś innego.
BlueFish

4
W tym celu ... rozwiązaniem jest użycie postMessage i receiveMessage. Rozwiązałem to za pomocą github.com/jeffomatic/nojquery-postmessage
BlueFish

Chodzi o to, aby obliczyć nową wysokość i wysłać wiadomość do ramki nadrzędnej, która musi ją odebrać, i odpowiednio dostosować wysokość ramki iframe.
BlueFish

Zawsze było dla mnie kilka pikseli, więc wymyśliłem to: function resizeIframe(iframe) { var size=iframe.contentWindow.document.body.scrollHeight; var size_new=size+20; iframe.height = size_new + "px"; }
Martin Mühl

56

Przekonałem się, że zaakceptowana odpowiedź nie była wystarczająca, ponieważ OPCJE X-FRAME: Allow-From nie jest obsługiwane w Safari ani Chrome . Zamiast tego zastosowano inne podejście, przedstawione w prezentacji Ben Vinegar z Disqus. Chodzi o to, aby dodać detektor zdarzeń do okna nadrzędnego, a następnie w elemencie iframe użyć window.postMessage, aby wysłać zdarzenie do elementu nadrzędnego z poleceniem, aby coś zrobił (zmiana rozmiaru elementu iframe).

Zatem w dokumencie nadrzędnym dodaj detektor zdarzeń:

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);

Wewnątrz elementu iframe napisz funkcję, aby opublikować wiadomość:

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

Na koniec wewnątrz elementu iframe dodaj tag onLoad do tagu body, aby uruchomić funkcję zmiany rozmiaru:

<body onLoad="resize();">

1
Aby to zadziałało, musiałem zmienić „window.parent” na „rodzic”.
prograhammer,

Wspaniały! ale ładuje wysokość tylko raz. Jeśli chcesz, aby iframe naprawdę reagował, wolę wywoływać metodę zmiany rozmiaru co sekundę, w ten sposób:setInterval(resize, 1000);
Jules Colle

12

Dodaj to do iframe, to zadziałało dla mnie:

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

A jeśli używasz jQuery, wypróbuj ten kod:

onload="$(this).height($(this.contentWindow.document.body).find(\'div\').first().height());"

6

Istnieją cztery różne właściwości, na które można spojrzeć, aby uzyskać wysokość zawartości w ramce iFrame.

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

Niestety wszyscy mogą udzielić różnych odpowiedzi, które są niespójne między przeglądarkami. Jeśli ustawisz margines ciała na 0, to document.body.offsetHeightdaje najlepszą odpowiedź. Aby uzyskać poprawną wartość, wypróbuj tę funkcję; który jest pobierany z biblioteki iframe-resizer, która również dba o utrzymanie iFrame właściwego rozmiaru przy zmianie zawartości lub zmianie rozmiaru przeglądarki.

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');
}

Nie działa to z elementami, które „zwijają”, np. Dane lub pływające div. Wysokość zależy od normalnej wysokości rozwiniętej, a nie od wysokości końcowej.
djack109

@ djack109 najprawdopodobniej coś w twoim CSS zatrzymuje element kurczący się na twojej stronie
David Bradshaw,

3

Inne odpowiedzi nie działały dla mnie, więc wprowadziłem pewne zmiany. Mam nadzieję, że to pomoże

$('#iframe').on("load", function() {
    var iframe = $(window.top.document).find("#iframe");
    iframe.height(iframe[0].ownerDocument.body.scrollHeight+'px' );
});

2

Zamiast używać javscript / jquery najłatwiej znalazłem:

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

Tutaj 1vh = 1% wysokości okna przeglądarki. Więc teoretyczna wartość wysokości, którą należy ustawić, to 100vh, ale praktycznie 98vh zrobiło magię.


9
Nie uwzględnia to wysokości treści elementu iframe.
Adrian Pauly,

Jest to wystarczająco blisko, gdy nie masz prostego sposobu obejścia dramatu między domenami ...
dsghi 18.09.19

2

Na wszelki wypadek pomaga to każdemu. Wyciągałem włosy, próbując sprawić, żeby to zadziałało, a potem zauważyłem, że iframe ma klasę o wysokości: 100%. Kiedy to usunąłem, wszystko działało zgodnie z oczekiwaniami. Więc sprawdź, czy nie ma żadnych konfliktów css.


2

możesz również dodać powtarzające się żądanieAnimationFrame do ramki resizeIframe (np. z odpowiedzi @ BlueFish), które zawsze będzie wywoływane, zanim przeglądarka maluje układ, i możesz zaktualizować wysokość ramki iframe, gdy jej zawartość zmieni wysokość. np. formularze wejściowe, leniwie ładowana treść itp.

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

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

oddzwanianie powinno być wystarczająco szybkie, aby nie miało większego wpływu na ogólną wydajność


1
jest to bardzo sprytne rozwiązanie, które od wstępnych testów działa bardzo dobrze. Byłbym zainteresowany implikacjami związanymi z wydajnością korzystania z tego.
KFE

Właśnie natknąłem się na skrzynkę, Uncaught TypeError: Cannot read property 'scrollHeight' of nullponieważ bodyjest null, jednak zwykle działa.
caot


1

Korzystam z jQuery i poniższy kod działa dla mnie,

var iframe = $(window.top.document).find("#iframe_id_here");
iframe.height(iframe.contents().height()+'px' );

0

Odkryłem, że odpowiedź Troya nie zadziałała. To jest ten sam kod przerobiony dla 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

Aby dodać do części okna, która wydaje się odcinać na dole, szczególnie gdy nie masz przewijania, użyłem:

function resizeIframe(iframe) {
    var addHeight = 20; //or whatever size is being cut off
    iframe.height = iframe.contentWindow.document.body.scrollHeight + addHeight + "px";
  }

0

Ten przydaje się, gdy potrzebujesz rozwiązania bez jquery. W takim przypadku powinieneś spróbować dodać pojemnik i ustawić wypełnienie w procentach

Przykładowy kod HTML:

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

Przykładowy kod CSS:

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

.iframecontainer{
    position: relative;
    width: 100%;
    height: auto;
    padding-top: 61%;
}

0

Prostym rozwiązaniem jest zmierzenie szerokości i wysokości obszaru zawartości, a następnie użycie tych pomiarów do obliczenia procentu dolnego wypełnienia.

W tym przypadku wymiary wynoszą 1680 x 720 pikseli, więc wypełnienie na dole to 720/1680 = 0,43 * 100, co stanowi 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%;   
}

0

Nieco ulepszona odpowiedź na 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";
}

Bierze to pod uwagę wysokość ekranu systemu Windows (przeglądarki, telefonu), co jest dobre dla responsywnego projektu i ramek iframe o dużej wysokości. Wypełnienie reprezentuje dopełnienie, które chcesz powyżej i poniżej ramki iframe w przypadku, gdy przechodzi przez cały ekran.


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

Przykład za pomocą PHP htmlspecialchars () + sprawdź, czy wysokość istnieje i wynosi> 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>';

0

po prostu ustaw pozycję kontenera iframe: wartość bezwzględna, a iframe automatycznie zmieni wysokość zgodnie z zawartością

<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

i / lub

$(window).height()

Zobacz pytanie Przepełnienie stosu Jak uzyskać wysokość elementu nadwozia .

Spróbuj tego, aby znaleźć wysokość ciała w jQuery:

if $("body").height()

Nie ma wartości, jeśli Firebug . Być może to jest problem.


Próbowałem zrobić obie rzeczy ... to wciąż dzieje się w przeglądarce Firefox. firefox jakoś nie dostaje window.height () w ramce iframe. Jak wspomniałem, skrypt jest dołączony do zawartości iframe i
wywołuję
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.