haga que la altura del iframe sea dinámica en función del contenido interno: JQUERY / Javascript


202

Estoy cargando una página web aspx en un iframe. El contenido en el iframe puede ser más alto que la altura del iframe. El iframe no debe tener barras de desplazamiento.

Tengo una divetiqueta de contenedor dentro del iframe que básicamente es todo el contenido. Escribí algo de jQuery para que el cambio de tamaño suceda:

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

¿Dónde TB_windowestá el div en el que Iframeestá contenido?

body - la etiqueta del cuerpo del aspx en el iframe.

Este script se adjunta al contenido del iframe. Estoy obteniendo el TB_windowelemento de la página principal. Si bien esto funciona bien en Chrome, pero la ventana TB_ se derrumba en Firefox. Estoy realmente confundido / perdido sobre por qué sucede eso.


esa página de iframe .aspx es del mismo nombre de dominio?
AlexC

¿puedes comprobar que $ ("body"). height () tiene un valor en firefox?
Michael L Watson

sí .. el iframe está en el mismo dominio que la página del contenedor
karry

@MichaelLWatson Parece que la ventana de vigilancia de Firebug tiene el valor 0 para la altura del cuerpo ... Sin embargo, Chrome tiene un valor
karry

Ejemplo de altura automática de iFrame angular: gitlab.com/reduardo7/angular-iframe-auto-height
Eduardo Cuomo el

Respuestas:


212

Puede recuperar la altura del IFRAMEcontenido de 's utilizando: contentWindow.document.body.scrollHeight

Después de que IFRAMEse cargue, puede cambiar la altura haciendo lo siguiente:

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

Luego, en la IFRAMEetiqueta, conecta el controlador de esta manera:

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

Tuve una situación hace un tiempo en la que además necesitaba llamar iframeLoadeddesde el IFRAMEmismo después de que ocurriera un envío de formulario. Puede lograrlo haciendo lo siguiente dentro de los IFRAMEscripts de contenido de:

parent.iframeLoaded();

153
No es compatible con Cross Domain.
Soumya

3
@Soumya El dominio cruzado no tiene nada que ver con este código. Hay un problema de seguridad que se omite con un comando.
Aristos

9
@Soumya Busque para X-FRAME-OPTIONSagregar una línea como: Response.AddHeader("X-FRAME-OPTIONS", "SAMEORIGIN");oresponse.addHeader("X-FRAME-OPTIONS", "Allow-From https://some.othersite.com");
Aristos

15
Esto resuelve el problema de dimensionamiento de iframe de dominio cruzado github.com/davidjbradshaw/iframe-resizer
David Bradshaw

2
@deebs También puedes intentar cambiar iFrameID.height = "";a iFrameID.height = "20px";. La altura predeterminada del iframe del navegador es de 150 px, que es a lo que se ""restablece.
philfreo

112

Una respuesta ligeramente mejorada para Aristos ...

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

Luego declare en su iframe de la siguiente manera:

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

Hay dos mejoras menores:

  1. No necesita obtener el elemento a través de document.getElementById, ya que ya lo tiene en la devolución de llamada de carga.
  2. No es necesario establecer iframe.height = ""si va a reasignarlo en la siguiente declaración. Hacerlo en realidad incurre en una sobrecarga ya que se trata de un elemento DOM.

Editar: si el contenido en el marco siempre está cambiando, llame al:

parent.resizeIframe(this.frameElement); 

desde dentro del iframe después de la actualización. Funciona para el mismo origen.

O para detectar automáticamente:

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

66
¿Qué harías si el contenido del marco siempre cambia?
Kevin

Si el tamaño del contenido sigue cambiando y / o si su iframe está diseñado para ubicarse en otros dominios que no sean el dominio desde el cual el iframe extrae la página, deberá hacer algo diferente.
BlueFish

44
Para esto ... la solución es usar postMessage y recibirMessage. Resolví
BlueFish

La idea es calcular la nueva altura y enviar un mensaje al marco principal que necesita recibir el mensaje y ajustar la altura del iframe en consecuencia.
BlueFish

Siempre fue un corto de píxeles para mí, así que se me ocurrió esto: function resizeIframe(iframe) { var size=iframe.contentWindow.document.body.scrollHeight; var size_new=size+20; iframe.height = size_new + "px"; }
Martin Mühl

56

Descubrí que la respuesta aceptada no era suficiente, ya que X-FRAME-OPTIONS: Allow-From no es compatible con Safari o Chrome . En su lugar, se utilizó un enfoque diferente, que se encuentra en una presentación dada por Ben Vinegar de Disqus. La idea es agregar un detector de eventos a la ventana principal y luego, dentro del iframe, usar window.postMessage para enviar un evento al principal diciéndole que haga algo (cambiar el tamaño del iframe).

Entonces, en el documento principal, agregue un detector de eventos:

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

Y dentro del iframe, escriba una función para publicar el mensaje:

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

Finalmente, dentro del iframe, agregue un onLoad a la etiqueta del cuerpo para activar la función de cambio de tamaño:

<body onLoad="resize();">

1
Para que esto funcione para mí, tuve que cambiar "window.parent" a solo "parent".
prograhammer

¡Excelente! pero solo carga la altura una vez. Si desea que el iframe sea realmente receptivo, prefiero llamar al método de cambio de tamaño cada segundo, de esta manera:setInterval(resize, 1000);
Jules Colle el

12

Agregue esto al iframe, esto funcionó para mí:

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

Y si usa jQuery intente este código:

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

6

Hay cuatro propiedades diferentes que puede ver para obtener la altura del contenido en un iFrame.

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

Lamentablemente, todos pueden dar diferentes respuestas y estas son inconsistentes entre los navegadores. Si establece el margen del cuerpo en 0, entonces document.body.offsetHeightda la mejor respuesta. Para obtener el valor correcto, pruebe esta función; que se toma de la biblioteca iframe-resizer que también se encarga de mantener el iFrame del tamaño correcto cuando cambia el contenido o se cambia el tamaño del navegador.

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

Esto no funciona con elementos que "se acumulan", por ejemplo, tablas de datos o divs flotantes. La altura se basa en la altura normal desenrollada y no en la altura final.
djack109

@ djack109 lo más probable es que algo en su CSS detenga un elemento que se encoge en su página
David Bradshaw

3

Otras respuestas no funcionaban para mí, así que hice algunos cambios. Espero que esto ayude

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

2

En lugar de usar javscript / jquery, la forma más fácil que encontré es:

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

Aquí 1vh = 1% de la altura de la ventana del navegador. Entonces, el valor teórico de la altura a establecer es 100vh pero prácticamente 98vh hizo la magia.


9
Esto no tiene en cuenta la altura del contenido del iframe.
Adrian Pauly

Esto se acerca lo suficiente, cuando usted no tiene una forma sencilla de trabajo alrededor de teatro dominios ...
dsghi

2

Por si acaso esto ayuda a alguien. Me estaba arrancando el pelo tratando de hacer que esto funcionara, luego noté que el iframe tenía una entrada de clase con altura: 100%. Cuando eliminé esto, todo funcionó como se esperaba. Por lo tanto, compruebe si hay conflictos de CSS.


2

también puede agregar un requestAnimationFrame repetido a su resizeIframe (por ejemplo, desde la respuesta de @ BlueFish) que siempre se llamaría antes de que el navegador pintara el diseño y podría actualizar la altura del iframe cuando su contenido haya cambiado sus alturas. por ejemplo, formularios de entrada, contenido cargado perezoso, etc.

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

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

su devolución de llamada debe ser lo suficientemente rápida como para no tener un gran impacto en su rendimiento general


1
Esta es una solución muy ingeniosa que, desde las pruebas iniciales, funciona muy bien. Me interesarían las implicaciones de rendimiento de usar esto.
KFE

Acabo de encontrarme con un caso Uncaught TypeError: Cannot read property 'scrollHeight' of nullya que bodyes null, sin embargo, generalmente funciona.
Caot


1

Estoy usando jQuery y el siguiente código funciona para mí,

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

0

Encontré que la respuesta de Troya no funcionaba. Este es el mismo código modificado para 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

Para agregar al trozo de ventana que parece estar cortado en la parte inferior, especialmente cuando no tienes desplazamiento, usé:

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

0

Este es útil cuando necesita una solución sin jquery. En ese caso, intente agregar un contenedor y establecer un relleno en porcentajes

Código de ejemplo HTML:

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

Código de ejemplo CSS:

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

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

0

La solución simple es medir el ancho y la altura del área de contenido y luego usar esas medidas para calcular el porcentaje de relleno inferior.

En este caso, las medidas son 1680 x 720 px, por lo que el relleno en la parte inferior es 720/1680 = 0,43 * 100, lo que equivale 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 respuesta ligeramente mejorada 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";
}

Esto toma en consideración la altura de la pantalla de Windows (navegador, teléfono) que es buena para el diseño receptivo y los iframes que tienen una altura enorme. El relleno representa el relleno que desea encima y debajo del iframe en caso de que atraviese toda la pantalla.


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

Muestra usando PHP htmlspecialchars () + verifica si la altura existe y es> 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

simplemente haga la posición del contenedor de iframe: absoluto e iframe cambiará automáticamente su altura de acuerdo con su contenido

<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

y / o

$(window).height()

Consulte la pregunta sobre desbordamiento de pila Cómo obtener la altura de un elemento del cuerpo .

Pruebe esto para encontrar la altura del cuerpo en jQuery:

if $("body").height()

No tiene valor si Firebug . Quizás ese sea el problema.


Intenté hacer ambas cosas ... todavía sucede en Firefox. Firefox de alguna manera no obtiene window.height () en el iframe. Como mencioné, el script está adjunto al contenido de Iframe y lo llamo en la función document.ready ()
karry
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.