¿Cómo hacer que un IFrame responda en iOS Safari?

134

El problema es que cuando tiene que usar IFrames para insertar contenido en un sitio web, entonces en el mundo web moderno se espera que el IFrame también responda. En teoría es simple, simplemente use <iframe width="100%"></iframe>o configure el ancho de CSS eniframe { width: 100%; } sin embargo, en la práctica no es tan simple, pero puede serlo.

Si el iframecontenido responde completamente y puede cambiar su tamaño sin barras de desplazamiento internas, iOS Safari cambiará el tamaño deliframe sin problemas reales.

Si considera el siguiente código:

<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=9,10,11" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Iframe Isolation Test</title>

    <style type="text/css" rel="stylesheet">

        #Main {
            padding: 10px;
        }
    </style>
</head>
<body>
    <h1>Iframe Isolation Test 13.17</h1>
    <div id="Main">
        <iframe height="950" width="100%" src="Content.html"></iframe>
    </div>
</body>
</html>

Con el Content.html :

<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=9,10,11" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Iframe Isolation Test - Content</title>

    <style type="text/css" rel="stylesheet">

        #Main {
            width: 100%;
            background: #ccc;
        }

    </style>
</head>
<body>
    <div id="Main">
        <div id="ScrolledArea">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc malesuada purus quis commodo convallis. Fusce consectetur mauris eget purus tristique blandit. Nam nec volutpat augue. Aliquam sit amet augue vitae orci fermentum tempor sit amet gravida augue. Pellentesque convallis velit eu malesuada malesuada. Aliquam erat volutpat. Nam sollicitudin nulla nec neque viverra, non suscipit purus tincidunt. Aenean blandit nisi felis, sit amet ornare mi vestibulum ac. Praesent ultrices varius arcu quis fringilla. In vitae dui consequat, rutrum sapien ut, aliquam metus. Proin sit amet porta velit, suscipit dignissim arcu. Cras bibendum tellus eu facilisis sodales. Vestibulum posuere, magna ut iaculis consequat, tortor erat vulputate diam, ut pharetra sapien massa ut magna. Donec massa purus, pharetra sed pellentesque nec, posuere ut velit. Nam venenatis feugiat odio quis tristique. 
        </div>      
    </div>
</body>
</html>

Entonces esto funciona sin problemas en iOS 7.1 Safari. Puede cambiar entre paisaje y retrato sin ningún problema.

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Sin embargo, simplemente cambiando Content.html CSS agregando esto:

    #ScrolledArea {
        width: 100%;
        overflow: scroll;
        white-space: nowrap;
        background: #ff0000;
    }

Obtienes esto:

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Como puede ver, aunque el contenido Content.html es totalmente receptivo ( div # ScrolledArea se ha overflow: scrollestablecido) y el ancho del iframe es del 100%, el iframe todavía toma el ancho completo del div # ScrolledArea como si el desbordamiento no existiera.Manifestación

En casos como este, si el iframecontenido tiene áreas de desplazamiento, la pregunta es cómo iframeresponder, cuando el contenido del iframe tiene áreas de desplazamiento horizontal. El problema aquí no está en el hecho de que Content.html no responde, sino en el hecho de que iOS Safari simplemente cambia el tamaño del iframe para que div#ScrolledAreasea ​​completamente visible.

Idra
fuente
¿Puedes compartir un enlace con nosotros? ¿Estás diciendo que iOS expandirá un iFrame al ancho completo de la página si la página tiene contenido con white-space: nowrapestilo?
DA.
@DA Agregué demos tanto al problema como a la solución. Y no, white-space: nowrapen sí mismo no es el problema. Simplemente lo estoy usando para obtener un ancho extremo div#ScrolledArea. El problema surge cuando el contenido de IFrame tiene áreas desplazables horizontalmente. Si ese es el caso, iOS Safari simplemente ignora la configuración de ancho y muestra el contenido del agujero y rompe la capacidad de respuesta del sitio.
Idra
Hmm ... Me pregunto si esa es una 'característica'. Sería incómodo tener un área desplazable (iFrame) que contenga contenido desplazable. Sería muy difícil interactuar con una pantalla táctil.
DA.
@DA Por supuesto, este es un caso de sobrina, y lo que dijiste puede ser cierto (depende de la implementación, funciona para nosotros) y la mayoría de los sitios no tienen áreas de desplazamiento horizontal, pero cuando lo haces ... ni siquiera puedes imaginar cuánto tiempo he pasado en esto. Pero esto puede ser un problema incluso si tiene imágenes ocultas y desplazadas con botones o algo así.
Idra
Parece que hay preguntas relacionadas con esto: stackoverflow.com/questions/5267996/… Parece ser una 'característica' del safari móvil ... está tratando de garantizar que el contenido se dimensione de manera que el usuario pueda Todavía interactuar con él. No estoy seguro de qué sucedería si tuviera contenido de desplazamiento en un iframe de desplazamiento ... ¿cómo interpretaría Safari un deslizamiento dentro de elementos de desplazamiento anidados?
DA.

Respuestas:

289

La solución para este problema es en realidad bastante simple y hay dos formas de solucionarlo. Si tiene control sobre Content.html , simplemente cambie el div#ScrolledAreaancho CSS a:

        width: 1px;
        min-width: 100%;
        *width: 100%;

Básicamente, la idea aquí es simple, establece el valor widthen algo que es más pequeño que la ventana gráfica (ancho del iframe en este caso) y luego lo sobrescribe min-width: 100%para permitir width: 100%que el Safari de iOS sobrescriba por defecto. El *width: 100%;está ahí por lo que el código seguiría siendo compatible IE6, pero si no le importa para IE6 se puede omitir. Manifestación

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Como puede ver ahora, el div#ScrolledAreaancho es en realidad del 100% y overflow: scroll;puede hacer lo suyo y ocultar el contenido desbordado. Si tiene acceso al contenido del iframe, entonces es preferible.

Sin embargo, si no tiene acceso al contenido del iframe (por cualquier razón), puede utilizar la misma técnica en el propio iframe. Simplemente use el mismo CSS en el iframe:

    iframe {
        width: 1px;
        min-width: 100%;
        *width: 100%;
    }

Sin embargo, hay una limitación con esto, debe desactivar las barras de desplazamiento con scrolling="no"el iframe para que esto funcione:

<iframe height="950" width="100%" scrolling="no" src="Content.html"></iframe>

Si las barras de desplazamiento están permitidas, esto ya no funcionará en el iframe. Dicho esto, si modifica Content.html en su lugar, puede retener el desplazamiento en el iframe. Manifestación

Idra
fuente
1
Como mencionó @NickGottlieb, tuve que agregar !importantal widthatributo para tener listo el diseño web sensible al iframe en un iPhone 4 con iOS 7
malisokan
@ ЮнгвиртТони No debería ser necesario que la solución funcione, es posible que widthse haya configurado anteriormente !importanto que una CSS de mayor prioridad lo sobrescribiera. En casos aislados en iPhone 4 iOS7 no era necesario.
Idra
¡No necesitaba! Importante tampoco. Funciona muy bien en iOS 8 también. Saludos
Sam Potts
Necesito desplazamiento = no solo cuando sea necesario, de lo contrario, desplazamiento = sí. Entonces, ¿qué debo detectar? ¿Es esto un problema de iOS? o un problema de webkit? o...?
gerbz
@ggwarpig este es un problema de iOS, donde el Safari de iOS activa automáticamente el atributo sin interrupciones y no puede sobrescribirlo. Si tiene control sobre el contenido, entonces necesita modificar el contenido para tenerlo, de lo scrolling="yes"contrario no hay forma de corregir esto, para que la solución funcione en IFRAME solo necesita tenerlo scrolling="no"en el IFRAME
Idra
24

Parece que el problema es que Mobile Safari se negará a obedecer el ancho de su iFrame si el documento que contiene es más ancho de lo que ha especificado. Ejemplo:

http://jsbin.com/hapituto/1

En un navegador de escritorio, verá un iFrame y un Div ambos configurados en 300 px. El contenido es más amplio para que pueda desplazarse por el iFrame.

Sin embargo, en el safari móvil, notará que el iFrame se expande automáticamente al ancho del contenido.

Supongo que esta es una solución para problemas de larga data con el desplazamiento de contenido dentro de una página. En el pasado, si tenía un iframe de desplazamiento grande en un dispositivo táctil, se quedaba 'atascado' en el iframe, ya que se desplazaría en lugar de la página en sí. Parece que Apple ha decidido que el comportamiento predeterminado de un iFrame es 'sin desplazamiento' y se expande para evitarlo.

Una opción puede ser esta solución alternativa. En lugar de suponer que el iFrame se desplazará, coloque el iframe en un DIV sobre el que tenga control y deje que se desplace.

ejemplo: http://jsbin.com/zakedaja/1

Marcado de ejemplo:

<div style="overflow: scroll; -webkit-overflow-scrolling: touch; width: 300px;">
   <iframe src="http://jsbin.com/roredora/1/" style="width: 600px;"></iframe>
</div>

En el safari móvil, ahora puede desplazarse por el contenido del iFrame ahora completamente expandido a través del div que lo contiene.

El truco: esto se ve realmente feo en un navegador de escritorio, ya que ahora tiene barras de desplazamiento dobles. Por lo tanto, es posible que deba detectar el navegador con JS para evitar esto.

DA.
fuente
1
Todavía mantendría que esto no está realmente en el alcance de la pregunta, porque la solución que mostró aquí es la forma estándar de falsificar el desplazamiento de iframe en iOS Safari, pero teniendo en cuenta este problema de iOS es un problema relacionado con el desplazamiento de IFrame (contenido o no) entonces es bueno tenerlo aquí.
Idra
1
Supongo que no entiendo completamente tu pregunta. Por lo que entiendo, el problema que tienes es que en iOS, Mobile Safari intenta evitar que un iFrame se desplace en primer lugar y fuerza un ancho sobre él. ¿Estoy malinterpretando tu problema?
DA.
En esencia, ese es el problema, solo la solución requerida es diferente. En el problema inicial, el contenido del IFrame era receptivo, mientras que tenía contenido de desplazamiento horizontal, por lo que la pregunta no era cómo emular el desplazamiento del iframe , sino cómo hacer que el ancho del iframe fuera 100%, es decir, receptivo, mientras que el contenido de desplazamiento horizontal está en ese iframe Es por eso que el enfoque anterior no funciona en este caso, porque la capacidad de respuesta diseñada se ha roto y debe desplazarse para ver el contenido completo, incluso en lugares que fueron diseñados por lo que normalmente no necesitaría.
Idra
1
Me disculpo, me di cuenta de que te engañé en uno de los comentarios. El iframe no se desplaza. Ese era el punto, no se suponía que el iframe estuviera desplazando solo partes de su contenido, es decir, el div#ScrolledArea(en verde) en mi ejemplo. Acabo de leer mal antes. Pero el iframe no debería estar desplazándose solo cambiando su tamaño en función del elemento contenedor, es decir, tenerwidth: 100%;
Idra
18

Necesitaba una solución de navegador cruzado. Los requisitos fueron:

  • necesario para trabajar tanto en iOS como en otros lugares
  • no tengo acceso al contenido en el iFrame
  • lo necesito para desplazarme!

A partir de lo que aprendí de @Idra sobre el desplazamiento = "no" en iOS y esta publicación sobre cómo ajustar el contenido de iFrame a la pantalla en iOS, esto es lo que terminé. Espero que ayude a alguien =)

HTML

<div id="url-wrapper"></div>

CSS

html, body{
    height: 100%;
}

#url-wrapper{
    margin-top: 51px;
    height: 100%;
}

#url-wrapper iframe{
    height: 100%;
    width: 100%;
}

#url-wrapper.ios{
    overflow-y: auto;
    -webkit-overflow-scrolling:touch !important;
    height: 100%;
}

#url-wrapper.ios iframe{
    height: 100%;
    min-width: 100%;
    width: 100px;
    *width: 100%;
}

JS

function create_iframe(url){

    var wrapper = jQuery('#url-wrapper');

    if(navigator.userAgent.match(/(iPod|iPhone|iPad)/)){
        wrapper.addClass('ios');
        var scrolling = 'no';
    }else{
        var scrolling = 'yes';
    }

    jQuery('<iframe>', {
        src: url,
        id:  'url',
        frameborder: 0,
        scrolling: scrolling
    }).appendTo(wrapper);

}
gerbz
fuente
1
votado, pero ... ¿por qué la regla IE6 en la clase "ios"? :-)
J. Bruni
12

El problema con todas estas soluciones es que la altura del iframenunca cambia realmente.

Esto significa que no podrá centrar elementos dentro del iframeuso de Javascript position:fixed;, o position:absolute;ya que el iframemismo nunca se desplaza.

Mi solución detallada aquí es envolver todo el contenido del iframe dentro de un divuso de este CSS:

#wrap {
    position: fixed;
    top: 0;
    right:0;
    bottom:0;
    left: 0;
    overflow-y: scroll;
    -webkit-overflow-scrolling: touch;
}

De esta manera, Safari cree que el contenido no tiene altura y le permite asignar la altura del contenido iframecorrectamente. Esto también le permite colocar elementos de la forma que desee.

Puedes ver una demostración rápida y sucia aquí.

Muelle
fuente
1
Esta es la única solución que funcionó para mí. Por supuesto, solo se puede usar si controlas el contenido de iframe, pero en mi caso, lo hago. ¡Salud!
Vince
Hmm ¿Su ejemplo no parece responder en iOS?
BrandonReid
Fue hace 2 años cuando escribí esto. ¿Puedes presentar un problema en el repositorio?
Muelle
Después de perder horas y horas en este problema con Ionic / Cordova en iOS, esto es lo único que funcionó. ¡Gracias!
Andrew
1
Esto es increíble, lo único que funcionó, me pasé 1 día buscando una solución como esta @Pier 100pts para ti
Carlos E
5

Este problema también está presente en iOS Chrome.

Eché un vistazo a todas las soluciones anteriores, la mayoría son muy hacky.

Si no necesita soporte para navegadores antiguos, simplemente configure el ancho del iframe en 100vw;

iframe {
  max-width: 100%; /* Limits width to 100% of container */
  width: 100vw; /* Sets width to 100% of the viewport width while respecting the max-width above */
}

Nota: Verifique el soporte para unidades de viewport https://caniuse.com/#feat=viewport-units

Prathamesh Gharat
fuente
1
Chrome para iOS es solo Safari debajo. Utiliza WKWebView. Ningún otro motor de renderizado web está permitido en iOS.
Muelle
3

Estoy trabajando con ionic2 y la configuración del sistema es la siguiente:


******************************************************

Your system information:

Cordova CLI: 6.4.0 
Ionic Framework Version: 2.0.0-beta.10
Ionic CLI Version: 2.1.8
Ionic App Lib Version: 2.1.4
ios-deploy version: Not installed
ios-sim version: 5.0.8 
OS: OS X Yosemite
Node Version: v6.2.2
Xcode version: Xcode 7.2 Build version 7C68



******************************************************

Para mí, este problema se resolvió con este código,
para la etiqueta html iframe,

<div class="iframe_container">
      <iframe class= "animated fadeInUp" id="iframe1" [src]='page' frameborder="0" >
        <!--  <img src="img/video-icon.png"> -->
      </iframe><br>
   </div>

Ver css de lo mismo que-


.iframe_container {
  overflow: auto; 
  position: relative; 
  -webkit-overflow-scrolling: touch;
  height: 75%;
}

iframe {
  position:relative;
  top: 2%;
  left: 5%;
  border: 0 !important;
  width: 90%;
}

La propiedad de posición juega un papel vital aquí en mi caso.
posición: relativa;

¡Puede que también te ayude!

S.Yadav
fuente
0

Solución solo CSS

HTML

<div class="container">
    <div class="h_iframe">
        <iframe  src="//www.youtube.com/embed/9KunP3sZyI0" frameborder="0" allowfullscreen></iframe>
    </div>
</div>

CSS

html,body {
    height:100%;
}
.h_iframe iframe {
    position:absolute;
    top:0;
    left:0;
    width:100%;
    height:100%;
}

MANIFESTACIÓN

Otra demostración aquí con página HTML en iframe

4dgaurav
fuente
Tal vez estoy implementando su solución de forma incorrecta, pero cuando lo probé con mi caso de prueba aislado, no funcionó, en absoluto en iOS Safari 7.1 iPhone 4. ¿Podría explicar cómo debería funcionar?
Idra
OK, parece que entendiste mal el problema, mira este enlace , es tu nuevo contenido de iframe de demostración integrado sin ningún CSS adicional aplicado al iframe. Y si lo revisa en iOS Safari, todavía responde, porque esta página no tiene ningún desplazamiento horizontal que obligue a que el ancho del iframe sea más ancho que la ventana gráfica. Como se describe en la pregunta, en un sitio como este no necesita hacer nada para que el iframe responda.
Idra
Entonces, ¿qué es exactamente lo que quieres que se comporte, da un ejemplo para tu enlace dado?
4dgaurav
0

Tuve un problema con el ancho en el panel de contenido al crear una barra de desplazamiento horizontal para el iframe. Resultó que una imagen tenía el ancho más ancho de lo esperado. Pude resolverlo estableciendo todas las imágenes css max-width en un porcentaje.

<meta name="viewport" content="width=device-width, initial-scale=1" />

img {
        max-width: 100%;
        height:auto;
    }
Dr. Aaron Dishno
fuente
0

de hecho para mí solo trabajé en ios deshabilitando el pergamino

<iframe src="//www.youraddress.com/" scrolling="no"></iframe>

y tratar el sistema operativo a través de script.

Luiz Rossi
fuente
0

Para mí, las soluciones CSS no funcionaron. Pero establecer el ancho mediante programación hace el trabajo. En la carga de iframe, configure el ancho mediante programación:

 $('iframe').width('100%');
umer
fuente