Muchos servicios multimedia, como YouTube o SoundCloud, utilizan el viejo elemento <iframe> para insertar el contenido en otras webs. Y que conste que digo “viejo” con todo el cariño. En los días que corren dónde el diseño adaptativo es más una obligación que una opción, tenemos que hacer el <iframe> también responsive. La solución basada en CSS que veremos en este post es también aplicable a elementos <video> y a los ya menos utilizados <object> y <embed>.

Lo primero que tenemos que saber es que el elemento <iframe> necesita obligatoriamente los atributos width y height. Por ejemplo, este es el código que me ha dado YouTube para un vídeo:

<iframe width="560" height="315" src="https://www.youtube.com/embed/eZJMzAHa-uQ" frameborder="0" allowfullscreen></iframe>

Si quito los atributos width y height, el iframe desaparecerá. Compruébalo.

Se te puede pasar por la cabeza hacer lo mismo que se hace con imágenes y otros elementos tipo block para que sean responsive: aplicar una anchura máxima del 100% y una altura automática. Por ejemplo:

iframe {
    max-width: 100%;
    height: auto;
}

Esto tampoco funcionará. Puede ser un apaño pero la altura (height) automática no se aplica correctamente en elementos iframe y, por otro lado, si ponemos un height fijo el resultado es un iframe que no mantiene las proporciones (aspect ratio) y el contenido puede aparecer deformado.

Solución: mantener el aspect ratio constante

Se necesita una solución que no sólo se adapte a diferentes tamaños de pantalla sino que mantenga el aspect ratio. Las soluciones más difundidas en Internet parecen venir todas de Creating Intrinsic Ratios For Video, de Thierry Koblentz, con ligeras variaciones.

Básicamente la solución consiste en poner el <iframe> dentro un div contenedor y posicionar el iframe de forma absoluta respecto a este contenedor. Para mantener el aspect ratio, a este contenedor se le da una altura de cero y un padding-bottom en porcentaje en función del aspect ratio. Por ejemplo, 75% para un aspect ratio 4:3 y 56.25% para un aspect ratio 16:9. Estos son los dos aspect ratios más utilizados pero puedes usar cualquier otro: simplemente haz una regla de tres que te diga el porcentaje que representa la altura en relación a la anchura. Por ejemplo, para un aspect ratio 3:2 sería (2/3)*100 = 66.66%.

Al poner ese porcentaje como padding-bottom y una altura cero, se mantiene el aspect ratio y damos el espacio necesario para el iframe que posicionaremos de forma absoluta dentro del contenedor. Utilizando el iframe que nos dio YouTube y que puse al principio llegaríamos a este markup:

<div class="embed-container">
    <iframe width="560" height="315" src="https://www.youtube.com/embed/eZJMzAHa-uQ" frameborder="0" allowfullscreen></iframe>
</div>

Y este CSS:

.embed-container {
    position: relative;
    padding-bottom: 56.25%;
    height: 0;
    overflow: hidden;
}
.embed-container iframe {
    position: absolute;
    top:0;
    left: 0;
    width: 100%;
    height: 100%;
}

Con esto tendríamos nuestro iframe con una proporción 16:9 totalmente responsive. Si quisiéramos un aspecto ratio 4:3 bastaría cambiar el padding-bottom del contenedor a 75%. O podríamos crear clases diferentes para cada aspect ratio:

.embed-container {
    position: relative;
    height: 0;
    overflow: hidden;
}
.16by9 {
    padding-bottom: 56.25%;
}
.4by3 {
    padding-bottom: 75%;
}
.embed-container iframe {
    position: absolute;
    top:0;
    left: 0;
    width: 100%;
    height: 100%;
}

Aunque he utilizado como ejemplo el iframe de un vídeo de YouTube, puedes utilizarlo para cualquier otro servicio que utilice iframes para insertar contenido, como SoundCloud, Vimeo, Google Maps y, en general, cualquier iframe cuyo contenido necesite mantener un aspect ratio fijo.

Consejo: Si utilizas WordPress puedes utilizar el filtro embed_oembed_html para añadir el marcado HTML que hemos descrito a los elementos insertados mediante oEmbed. Por ejemplo:

add_filter( 'embed_oembed_html', 'cyb_oembed_html' );
function cyb_oembed_html( $output ) {
    return '<div class="embed-container 16by9">' . $output . '</div>';
}

Soluciones basadas en JavaScript

Si no puedes o no quieres utilizar CSS, no puedes controlar que los editores añadan el markup o cualquier otra de esas situaciones que escapan de las manos del desarrollador web, puedes pensar en utilizar una solución basada en javascript. No te voy a poner código aquí pero te voy a recomendar los dos proyectos listos para ser utilizados más populares: FluidVids (standalone) y FitVids (plugin para jQuery).

iframe responsive con aspect ratio variable

Además de los contenidos multimedia de terceros, el iframe se puede utilizar para miles de cosas más y mantener el aspect ratio no siempre es lo que necesitamos (y si no que se lo pregunten a Jose Corbalán, mira su comentario). No hay nada más que hacer que utilizar la técnica más básica del diseño responsive: utilizar media queries para definir la anchura y altura del iframe para cada tamaño de pantalla. Por ejemplo:

/* CSS general */
.mi-iframe {
  width: 100px;
  height: 50px;
}

/* CSS pantallas de 320px o superior */
@media (min-width: 320px) {

  .mi-iframe {
    width: 200px;
    height: 150px;
  } 

}

/* CSS pantalla 768px o superior */
@media (min-width: 768px) {

  .mi-iframe {
    width: 500px;
    height: 350px;
  } 

}
  • Maria

    Hola! Muy buen artículo! introduzco pero no consigo que se vea en iphone y ipad el video sólo en la web. ¿Me podrían echar una mano? Muchas gracias de antemano!

    <div class=.delimitador{width:560px;margin:auto}">
    <div class= ".embed-container{position : relative ;height: 0; overflow: hidden ; max-width:560px; padding-top: 56.25% ;} "><div style="text-align: center;"><iframe{position:absolute; top:0 ; left: 0 ; width : 0 ; height:100%;}
    src="codígo youtube" frameborder="0" allowfullscreen=""></iframe></div></div>
  • Galicer

    Hola, por alguna razon toda la informacion que esta despues de que cierro el div contenedor desaparece, tanto texto como imagenes. El codigo esta igual al presentado. ¿Alguien sabe por qué?

  • Angela Maria Ramirez Londoño

    Buenos Días, muy interesante tu aporte. Ya inclui el codigo para hacer responsive un mapa. Sin embargo en la web lo veo bienpero en el movil no lo veo. que plugin deberia incluir para que se vea un mapa en el movil. Muchas Gracias

  • Xoco

    Muy buen artículo, estaría bien por eso subir en .zip los .html y .css de los ejemplos que vas dando a cualquier servidor de archivos (mega, dropbox, box, etc.) y así los neófitos podemos descargarlos y hacer pruebas. Más que nada por los ejemplos del código html son parciales y supongo que faltan etiquetas o la llamada al .css
    Gracias.

  • Claudia Solano

    Excelente!!! Muchísimas Gracias!!! Me ayudó muchísimo.

  • Danilo Contreras

    https://uploads.disquscdn.com/images/734d13343a057df5cd629ddfbc407a3695304d80abe37a5bdcec6390a4749c07.png

    Muy interesante, como lo puedo aplicar a una pagina donde llame, 4 iframe distintos y que sea responsive como la imagen.

  • Tan sencillo como eso! Gracias!!!

  • Erick Leonel Mariano Malagon

    excelente solucion para la implementacion de iframes, que no ayudan en nada en como se comportan los elementos, pero con esta tecnica posiblemente vuelva a usar muchos iframes…. claro, sin abusar de ellos!!

  • Eduardo

    Mil gracias, me funciono como queria 😀

  • Jose Antonio Nicolas

    Gracias por la información tan completa, pero no consigo dejar funcionando el iframe. ¿Podrías ayudarme a ver donde está el error?. Gracias anticipadas y enhorabuena por el blog 🙂

  • Emercab

    Amigo, excelente tu explicación, era justo lo que necesitaba. Gracias por compartir tus conocimientos.

  • Daniel Pintó Casas

    Interesante. Muy bien expuesto 🙂

  • josemainol

    Grande, muchas gracias

  • Ignacio Tröndle

    Excelente, muchas gracias!!

  • Fasterworks Luis Pérez

    Hola como estan? Alguien sabe como puedo hacer para que el iframe ocupe el 100% de ancho y el 100% de alto en cualquier pantalla? Pero teniendo en cuenta que arriba tengo una barrita de menu que ocupa 50px osea que tiene que estar debajo de eso, intento hacerlo pero no puedo. Les agradezco sus comentarios!

    • Jorge Cifuentes

      Hola, pudiste solucionar tu problema, yo tengo la misma inquietud y no doy con la solucion.

      saludos y gracias

    • Fasterworks Luis Pérez

      Hola, no pude! Tuve que darle un alto fijo y me sobra lugar en algunas páginas, el problema en el iPhone o iPad, no se porque no se comporta como en la pc o Android.

    • Siento no haber contestado, pero es que tengo por costumbre no contestar comentarios que no estén estrictamente relacionados con el post. Estos son los comentarios para un post en concreto, no es un foro, y vuestros comentarios no tienen nada que ver con hacer un iframe adaptativo.

      Pero bueno. Me salto la regla.

      Podéis darle un height del 100% al iframe, o un height de calc( 100% – 50px) si lo necesiáis. El problema que tenéis al no poder hacerlo es que un height expresado en porcentaje indica el porcentaje de la altura del elemento padre que tomará el elemento hijo. Esto es igualmente aplicable a la propiedad width.

      Entoces, estoy casi seguro que si no obtienes el resultado esperado con height en porcentaje es porque el elemento padre no tiene la altura definida.

      Si el iframe es descendiente del body, como el body es descendiente de la “ventana” del navegador:

      body, html {
      height: 100%;
      }
      #mi-iframe {
      height: 100%;
      }

      Y el HTML:

      La otra alternativa es posicionar de forma absoluta el iframe para que la altura de referencia no dependa necesariamente de la altura del elemento padre directo. Pero eso ya depende de vuestra situación concreta.

      Por favor, si seguís con dudas sobre esto utilizad un foro adecuado.

      Saludos!!

  • joaquin

    Hola Juan excelente tu post, pero no puedo hacerlo funcionar, yo creo que mi problema es que es un tema de wordpress

    como puedes ver el iframe esta ahi, pero no lo puedo hacer responsive, espero me puedas ayudar con este asunto, saludos!

    • Por favor, pon el código HTML que utilizas para el iframe y el CSS que le aplicas en lugar del enlace a tu web.

  • Alirio García Diseño Gráfico

    Saludos Juan

    Utilice tu código para incluir la página de una tienda online en mi web adaptando las medidas tanto para la versión desktop como para la tablet. Muchas gracias, resultó super útil.

  • Jose Corbalán

    Muchas gracias, me ha sido muy útil. Hay una cosa que me sucede y no sé si tiene solución. En el iframe estoy poniendo un html responsive y con la solución de este blog se comporta correctamente cuando modifico el ancho de la página. La cuestión es que el contenido del html, al estrechar la página principal, ocupa más de largo, pero el iframe no “crece” de alto por lo que hay que hacer scroll en el iframe para ver el contenido. Si modifico la altura del iframe a mano para que quepa cuando está estrecho, sobrará espacio en blanco en horizontal ¿cómo se podría hacer?
    Gracias.

    • Parece que lo que planteas no es hacer un iframe responsive, sino hacer que el iframe se adapte a su contenido, que son dos cosas diferentes. Nota que lo primero responde al tamaño de su contexto externo (al tamaño de la ventana del navegador, por ejemplo) y lo segundo responde al tamaño de su contexto interno (tamaño de su contenido). En resumen, quieres que el tamaño del iframe se adapte automáticamente al tamaño de su contenido.

      Hasta dónde yo se, no hay forma de hacer eso con CSS (salvo casos concretos como iframe full-screen). Con CSS podrías tener un width y un height fijos e ir variándolos con el cambio de la anchura de la ventana, pero sería una solución válida para un iframe que cargue un contenido específico, ya que necesitas conocer exactamente el tamaño del contenido. Si quieres una solución universal vas a tener que buscar soluciones basadas en JavaScript.

    • Jose Corbalán

      Es verdad ¿Y sería posible, ya que conozco el tamaño del html para cada ancho de página (320, 768, 1024 y 1200), hacer que el iframe sea de un tamaño concreto para cada ancho de página? Muchas gracias.

    • Igual que con cualquier otro elemento, al iframe también puedes aplicar diferentes propiedades CSS utiilzando media-queries. Es a lo que me refería con tener un width y un height fijos para cada anchura de ventana ¿Dónde tienes el problema exactamente?

      /* CSS general */
      .mi-iframe {
      width: 100px;
      height: 50px;
      }

      /* CSS para anchura de ventana 320px o superior */
      @media (min-width: 320px) {

      .mi-iframe {
      width: 200px;
      height: 150px;
      }

      }

      /* CSS para anchura de ventana 768px o superior */
      @media (min-width: 768px) {

      .mi-iframe {
      width: 500px;
      height: 350px;
      }

      }

    • Jose Corbalán

      ¡Muchas gracias!! Ya me funciona, el iframe se redimensiona cuando abro y cierro la venta. El problema ahora es que no me recarga el contenido. Es curioso, porque cuando la ventana no se redimensionaba sí que lo hacía el contenido ¿Qué crees que puede ser?

    • El contenido de un iframe se carga al cargarse el documento principal, si quieres que se recargue tienes que recurrir a JavaScript, pero no se si he entendido bien lo que quieres decir por que primero dices “no me recarga el contenido” y luego “cuando la ventana no se redimensionaba sí que lo hacía el contenido”.

      De todas formas, parece que esta conversación se está alejando ya bastante del tema sobre el que trata el post y me gusta mantener las conversacones on topic.

      Saludos!!

    • Jose Corbalán

      Sí, se está convirtiendo en un helpdesk, perdona.
      Muchas gracias por todo..

  • Marcos Krausse

    hola como estan , estoy tratando de utilizar un iframe dentro de sharepoint estoy tratando de levantar el css dentro de el editor de el codigo html , el problema es que cuando aplico los estilos estos chocan para todos lados, y no responde como deberia , claramente esta llamando a la carpeta css correcta por que cuando quito el archivo la web vuelve a su correcto funcionamiento. Pero cuando aplico los estilos el iframe se monta sobre toda la web , y no llega a la altura correcta alguna idea ?

  • MARIALMAR

    Hola! Gracias por la solución!

    Aunque quizá es pregunta de otro tema, pero porqué dices que si no queremos usar CSS? Probando mi página con Google Speed, indica la carga de CSS’s como un aspecto que ralentiza, yo utilizo bootstrap.ccs y uno propio. Ralentiza demasiado? Es preferible utilizar JavaScript?
    Gracias!

    • Hola!!!

      El uso de CSS no es en sí mismo un aspecto negativo en la velocidad de una web, de hecho el 100% de las webs de Internet utilizan CSS. El tema al que te refieres es prácticamente igual para CSS que para JavaScript, lo que tienen en cuenta los test de velocidad no es que utilices CSS, JavaScript o ninguno de ellos, lo que miden estos tests es, sobre todo, como los utilizas.

      Para mí, en este caso concreto, es mejor utilizar CSS. Y por cierto, Bootstrap ya viene con el CSS adecuado para hacer un iframe responsive (y otros tipos de contenidos insertados similares), no tienes que añadir nada de CSS ni JavaScript propio para esto. Aquí tienes las instrucciones: http://getbootstrap.com/components/#responsive-embed

    • MARIALMAR

      Es verdad, gracias!
      Pues mi css adicional no es muy grande, no se porque me lo muestra como algo a mejorar. Lo que es verdad que es un poco lenta al cargar:
      Gracias. Saludos!!!

    • Probablemente sea por que tu CSS propio lo cargas por separado, lo que supone dos solicitudes HTTP, una para tu CSS y otra para el de Bootstrap. Si combinas ambos en un solo arachivo lo puedes servir mediante una única solicitud HTTP y así optimizar la carga de CSS. Hay que tratar de disminuir el número de solicitudes HTTP al máximo. Pero bueno, este tema ya se desvía mucho del propósito de este post. Puedes buscar en Internet sobre optimizar la carga de CSS, seguro que encuentras miles (literalmente) de ejemplos, tutoriales y recursos.

    • MARIALMAR

      Sí gracias!! 😀

  • jorge

    muy intersante, llevo loco buscando soluciones pero en vez de un iframe para youtube, necesitaba un iframe para embeber una web, pero claro con el típico iframe al verlo en smartphone o tablet simplemente no funciona, no se adapta y encima no puedes hacer nada dentro del marco donde esta embebida, el tactil no responde. Voy a probar esta solución, ¿algun consejo para este caso en concreto de web embebida en un iframe?
    y ante todo muchas gracias voy a seguir tu blog me ha parecido muy interesante

    • Hola Jorge!!

      Como se menciona en el post, da igual que sea de YouTube o de cualquier otra web, un es un y la técnica funcionará igual. Eso sí, que el contenido dentro del sea responsive o no eso ya no se puede controlar desde la página padre.

      El problema que tienes con el contenido dentro del iframe que no responde en pantallas táctiles es muy extraño. No sabría decirte a que se puede debe sin ver el completo de la página. Yo empezaría a comprobar el z-index del iframe y si tiene algún elemento solapado con mayor z-index, aunque en ese caso tampoco debería responder el ratón y no sólo afectar a los eventos táctiles. Pero bueno, ese tema ya queda fuera de lo que se trata aquí sobre los iframes adaptativos.