rendere dinamica l'altezza iframe in base al contenuto interno - JQUERY / Javascript


202

Sto caricando una pagina web aspx in un iframe. Il contenuto nell'Iframe può essere più alto dell'altezza dell'iframe. L'iframe non dovrebbe avere barre di scorrimento.

Ho un divtag wrapper all'interno dell'iframe che sostanzialmente è tutto il contenuto. Ho scritto alcuni jQuery per rendere possibile il ridimensionamento:

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

dove TB_windowè il div in cui Iframeè contenuto.

body - il tag body dell'aspx nell'iframe.

Questo script è allegato al contenuto iframe. Ricevo l' TB_windowelemento dalla pagina principale. Mentre questo funziona bene su Chrome, ma la finestra TB_wind crolla in Firefox. Sono davvero confuso / perso sul perché ciò accada.


quella pagina iframe .aspx proviene dallo stesso nome di dominio?
AlexC,

puoi controllare $ ("body"). height () ha un valore in firefox?
Michael L Watson,

sì ... l'iframe si trova nello stesso dominio della pagina del contenitore
karry

@MichaelLWatson Sembra che la finestra dell'orologio firebug abbia il valore di 0 per l'altezza del corpo ... Chrome ha un valore però
Karry

Esempio di Auto-Height angolare iFrame: gitlab.com/reduardo7/angular-iframe-auto-height
Eduardo Cuomo

Risposte:


212

Puoi recuperare l'altezza del IFRAMEcontenuto usando: contentWindow.document.body.scrollHeight

Dopo aver IFRAMEcaricato, è possibile quindi modificare l'altezza procedendo come segue:

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

Quindi, sul IFRAMEtag, si collega il gestore in questo modo:

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

Qualche tempo fa ho avuto una situazione in cui avevo anche bisogno di chiamare iframeLoadedda IFRAMEsolo dopo l'invio di un modulo. Puoi farlo facendo quanto segue negli IFRAMEscript del contenuto:

parent.iframeLoaded();

153
Non supporta su Cross Domain.
Soumya,

3
@Soumya Il dominio incrociato non ha nulla a che fare con questo codice. Esiste un problema di sicurezza che si elude con un comando.
Aristos,

9
@Soumya Cerca l' X-FRAME-OPTIONSaggiunta di una riga come: Response.AddHeader("X-FRAME-OPTIONS", "SAMEORIGIN");oppureresponse.addHeader("X-FRAME-OPTIONS", "Allow-From https://some.othersite.com");
Aristos

15
Questo risolve il problema del dimensionamento degli iframe tra domini github.com/davidjbradshaw/iframe-resizer
David Bradshaw,

2
@deebs Puoi anche provare a cambiare iFrameID.height = "";in iFrameID.height = "20px";. L'altezza predefinita del iframe del browser è 150px, che è ciò che lo ""reimposta.
philfreo,

112

Una risposta leggermente migliorata ad Aristos ...

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

Quindi dichiarare nel tuo iframe come segue:

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

Ci sono due piccoli miglioramenti:

  1. Non è necessario ottenere l'elemento tramite document.getElementById, poiché è già presente nel callback onload.
  2. Non è necessario impostare il parametro iframe.height = ""se lo riassegnerai nella dichiarazione successiva. Ciò comporta effettivamente un sovraccarico quando si ha a che fare con un elemento DOM.

Modifica: se il contenuto nella cornice cambia sempre, chiama:

parent.resizeIframe(this.frameElement); 

dall'interno dell'iframe dopo l'aggiornamento. Funziona per la stessa origine.

O per rilevare automaticamente:

  // 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
Cosa faresti se il contenuto nella cornice cambia sempre?
Kevin,

Se la dimensione del contenuto continua a cambiare e / o se il tuo iframe è progettato per essere collocato su altri domini diversi dal dominio da cui l'iframe estrae la pagina, dovrai fare qualcosa di diverso.
BlueFish,

4
Per questo ... la soluzione è usare postMessage e receiveMessage. Ho risolto questo problema usando github.com/jeffomatic/nojquery-postmessage
BlueFish,

L'idea è di calcolare la nuova altezza e inviare un messaggio al frame principale che deve ricevere il messaggio e regolare l'altezza dell'iframe di conseguenza.
BlueFish,

Per me sono sempre stati dei pixel brevi, quindi ho pensato a questo: function resizeIframe(iframe) { var size=iframe.contentWindow.document.body.scrollHeight; var size_new=size+20; iframe.height = size_new + "px"; }
Martin Mühl il

56

Ho scoperto che la risposta accettata non era sufficiente, poiché X-FRAME-OPTIONS: Allow-From non è supportato in Safari o Chrome . È andato invece con un approccio diverso, trovato in una presentazione di Ben Vinegar di Disqus. L'idea è quella di aggiungere un listener di eventi alla finestra principale e quindi all'interno dell'iframe, utilizzare window.postMessage per inviare un evento al padre dicendogli di fare qualcosa (ridimensionare l'iframe).

Quindi nel documento principale, aggiungi un listener di eventi:

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

E all'interno dell'iframe, scrivi una funzione per pubblicare il messaggio:

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

Infine, all'interno dell'iframe, aggiungi un onLoad al tag body per attivare la funzione di ridimensionamento:

<body onLoad="resize();">

1
Affinché ciò funzionasse per me, ho dovuto cambiare "window.parent" in "genitore".
prograhammer,

Grande! ma carica l'altezza solo una volta. Se vuoi rendere l'iframe veramente reattivo, preferisco chiamare il metodo di ridimensionamento ogni secondo, in questo modo:setInterval(resize, 1000);
Jules Colle

12

Aggiungi questo all'iframe, ha funzionato per me:

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

E se usi jQuery prova questo codice:

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

6

Esistono quattro diverse proprietà che puoi guardare per ottenere l'altezza del contenuto in un iFrame.

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

Purtroppo tutti possono dare risposte diverse e queste sono incoerenti tra i browser. Se si imposta il margine del corpo su 0, si document.body.offsetHeightottiene la risposta migliore. Per ottenere il valore corretto provare questa funzione; che viene preso dalla libreria iframe-resizer che si occupa anche di mantenere l'iFrame della dimensione corretta quando il contenuto cambia o il browser viene ridimensionato.

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

Questo non funziona con elementi che "arrotolano", ad es. Banche dati o div galleggianti. L'altezza si basa su qualunque sia l'altezza normale srotolata e non sull'altezza finale.
djack109,

@ djack109 molto probabilmente qualcosa nel tuo CSS ferma un elemento che si restringe sulla tua pagina
David Bradshaw,

3

Altre risposte non funzionavano per me, quindi ho apportato alcune modifiche. Spero che questo possa aiutare

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

2

Invece di usare javscript / jquery il modo più semplice che ho trovato è:

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

Qui 1vh = 1% dell'altezza della finestra del browser. Quindi il valore teorico dell'altezza da impostare è 100vh ma praticamente 98vh ha fatto la magia.


9
Ciò non tiene conto dell'altezza del contenuto dell'iframe.
Adrian Pauly,

Questo si avvicina abbastanza quando non hai un modo semplice per aggirare il dramma tra domini ...
dsghi,

2

Nel caso in cui ciò aiuti chiunque. Mi stavo togliendo i capelli cercando di farlo funzionare, poi ho notato che l'iframe aveva una voce di classe con altezza: 100%. Quando l'ho rimosso, tutto ha funzionato come previsto. Quindi, si prega di verificare eventuali conflitti CSS.


2

potresti anche aggiungere una richiesta ripetutaAnimationFrame al tuo resizeIframe (ad es. dalla risposta di @ BlueFish) che verrebbe sempre chiamato prima che il browser dipinga il layout e potresti aggiornare l'altezza dell'iframe quando il suo contenuto ha cambiato le sue altezze. ad es. moduli di input, contenuto caricato in modo lento ecc.

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

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

il callback dovrebbe essere abbastanza veloce da non avere un grande impatto sulle prestazioni complessive


1
questa è una soluzione molto fluida che, dai test iniziali, funziona molto bene. Sarei interessato alle implicazioni prestazionali dell'utilizzo di questo.
KFE,

Appena incontrato un caso Uncaught TypeError: Cannot read property 'scrollHeight' of nullin quanto bodyè null, ma funziona di solito.
Caot


1

Sto usando jQuery e il codice seguente funziona per me,

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

0

Ho trovato la risposta di Troia non funzionava. Questo è lo stesso codice rielaborato per 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

Per aggiungere al pezzo di finestra che sembra tagliato in fondo, specialmente quando non hai lo scorrimento ho usato:

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

0

Questo è utile quando hai bisogno di una soluzione senza jquery. In tal caso dovresti provare ad aggiungere un contenitore e impostare un'imbottitura in percentuale

Codice esempio HTML:

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

Codice esempio CSS:

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

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

0

La soluzione semplice è misurare la larghezza e l'altezza dell'area del contenuto, quindi utilizzare quelle misurazioni per calcolare la percentuale di riempimento inferiore.

In questo caso, le misure sono 1680 x 720 px, quindi l'imbottitura sul fondo è 720/1680 = 0,43 * 100, che risulta al 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

Una risposta leggermente migliorata a 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";
}

Questo prende in considerazione l'altezza dello schermo di Windows (browser, telefono) che è buono per il design reattivo e iframe che hanno un'altezza enorme. L'imbottitura rappresenta l'imbottitura desiderata sopra e sotto l'iframe nel caso in cui passi attraverso l'intero schermo.


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

Esempio usando PHP htmlspecialchars () + controlla se l'altezza esiste ed è> 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

basta creare la posizione del contenitore iframe: assoluto e iframe cambierà automaticamente la sua altezza in base al suo contenuto

<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

e / o

$(window).height()

Vedi domanda Stack Overflow Come ottenere l'altezza di un elemento body .

Prova questo per trovare l'altezza del corpo in jQuery:

if $("body").height()

Non ha valore se Firebug . Forse è questo il problema.


Ho provato a fare entrambi ... succede ancora su Firefox. firefox in qualche modo non ottiene window.height () sull'iframe. Come ho già detto, lo script è allegato al contenuto di Iframe e lo sto chiamando nella funzione document.ready ()
karry
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.