Come rendere reattivo un IFrame in iOS Safari?


134

Il problema è che quando devi usare IFrame per inserire contenuti in un sito web, nel moderno mondo web ci si aspetta che anche l'IFrame sia reattivo. In teoria è semplice, semplicemente un aiuto<iframe width="100%"></iframe> o impostare l'ampiezza CSS su come iframe { width: 100%; }in pratica non è poi così semplice, ma può esserlo.

Se la iframe contenuto è completamente reattivo e può ridimensionarsi senza barre di scorrimento interne, iOS Safari ridimensionerà iframesenza problemi reali.

Se si considera il seguente codice:

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

Quindi funziona senza problemi in iOS 7.1 Safari. Puoi cambiare tra paesaggio e ritratto senza problemi.

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

Tuttavia, semplicemente modificando il CSS Content.html aggiungendo questo:

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

Ottieni questo:

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

Come si può vedere, anche se il content.html contenuto è pienamente rispondente ( div # ScrolledArea ha overflow: scrollset) e l'iframe larghezza è 100% l'iframe prende ancora l'intera larghezza del div # ScrolledArea come se l'overflow non esistesse. dimostrazione

In casi come questo, il iframecontenuto ha aree di scorrimento su di esso, la domanda diventa, come ottenere il iframereattivo, quando il contenuto di iframe ha aree di scorrimento orizzontale? Il problema qui non è nel fatto che Content.html non risponde, ma nel fatto che iOS Safari ridimensiona semplicemente l'iframe in modo che div#ScrolledAreasia completamente visibile.


Puoi condividere un link con noi? Stai dicendo che iOS espanderà un iFrame per l'intera larghezza della pagina all'interno se la pagina all'interno ha contenuti con white-space: nowrapstile?
DA.

@DA Ho aggiunto demo sia al problema che alla soluzione. E no, white-space: nowrapil problema non è di per sé. Lo sto semplicemente usando per ottenere una larghezza estrema div#ScrolledArea. Il problema si presenta quando il contenuto di IFrame contiene aree scorrevoli orizzontalmente al suo interno. In tal caso, iOS Safari ignora semplicemente le impostazioni di larghezza e mostra il contenuto della buca e interrompe la reattività del sito.
Idra,

Hmm ... Mi chiedo se sia una "caratteristica". Sarebbe imbarazzante avere un'area scorrevole (iFrame) che contenga contenuti scorrevoli. Sarebbe molto difficile interagire con un touchscreen.
DA.

@DA Naturalmente questo è un caso nipote, e ciò che hai detto può essere vero (dipende dall'implementazione, funziona per noi) e la maggior parte dei siti non ha aree scorrevoli orizzontalmente, ma quando lo fai ... non puoi nemmeno immaginare quanto tempo ho trascorso su questo. Ma questo può essere un problema anche se hai immagini che sono nascoste e fatte scorrere con pulsanti o qualcosa del genere.
Idra,

Sembra che ci siano domande correlate su questo: stackoverflow.com/questions/5267996/… Sembra essere una 'caratteristica' del safari mobile ... sta cercando di assicurarsi che il contenuto sia dimensionato in modo che l'utente possa interagire ancora con esso. Non sono sicuro che cosa accadrebbe se si avesse un contenuto a scorrimento in un iframe a scorrimento ... come Safari interpreterebbe un colpo all'interno di elementi di scorrimento nidificati?
DA.

Risposte:


289

La soluzione a questo problema è in realtà abbastanza semplice e ci sono due modi per risolverlo. Se hai il controllo su Content.html, modifica semplicemente la div#ScrolledArealarghezza CSS in:

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

Fondamentalmente l'idea qui è semplice, si imposta widthsu qualcosa che è più piccolo del viewport (in questo caso la larghezza iframe) e quindi lo si sovrascrive min-width: 100%per consentire effettivamente width: 100%quale iOS Safari sovrascrive di default. Il *width: 100%;c'è modo che il codice sarebbe rimasto IE6 compatibile, ma se non si cura per IE6 può essere omesso. dimostrazione

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

Come puoi vedere ora, la div#ScrolledArealarghezza è in realtà del 100% e laoverflow: scroll; puoi fare ciò che è nascosto e nascondere il contenuto traboccante. Se hai accesso al contenuto di iframe, allora è preferibile.

Tuttavia, se non hai accesso al contenuto iframe (per qualsiasi motivo), puoi effettivamente utilizzare la stessa tecnica sull'iframe stesso. Usa semplicemente lo stesso CSS sull'iframe:

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

Tuttavia, esiste una limitazione con questo, è necessario disattivare le barre di scorrimento con scrolling="no"l'iframe affinché funzioni:

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

Se le barre di scorrimento sono consentite, questo non funzionerà più sull'iframe. Detto questo, se si modifica Content.html invece, è possibile conservare lo scorrimento nell'iframe. dimostrazione


1
Come accennato da @NickGottlieb, ho dovuto aggiungere !importantl' widthattributo per preparare l'iframe responsive-web-design pronto su un iPhone 4 con iOS 7
malisokan

@ ЮнгвиртТони Non dovrebbe essere necessario che la soluzione alternativa funzioni, è possibile che sia widthstato impostato in precedenza con !importanto un CSS con priorità più elevata lo abbia sovrascritto. In casi isolati in iPhone 4 iOS7 non era necessario.
Idra,

Non avevo bisogno! Importante neanche. Funziona benissimo anche su iOS 8. Saluti
Sam Potts,

Ho bisogno di scrolling = no solo quando necessario, altrimenti scrolling = yes. Quindi cosa dovrei rilevare? È un problema iOS? o un problema con il webkit? o...?
Gerbz,

@ggwarpig si tratta di un problema iOS, in cui Safari iOS attiva automaticamente l'attributo senza interruzioni e non è possibile sovrascriverlo. Se si ha il controllo sul contenuto, è necessario modificarlo per scrolling="yes"non avere altrimenti modo di correggerlo, perché la correzione funzioni su IFRAME è necessario solo scrolling="no"su IFRAME
Idra

24

Il problema, a quanto pare, è che Mobile Safari rifiuterà di obbedire alla larghezza del tuo iFrame se il documento in esso contenuto è più largo di quello che hai specificato. Esempio:

http://jsbin.com/hapituto/1

Su un browser desktop, vedrai un iFrame e un Div entrambi impostati su 300px. Il contenuto è più ampio in modo da poter scorrere l'iFrame.

Su Safari mobile, tuttavia, noterai che l'iFrame si espande automaticamente fino alla larghezza del contenuto.

La mia ipotesi è che questa è una soluzione alternativa per problemi di vecchia data con lo scorrimento dei contenuti all'interno di una pagina. In passato, se avessi un grande iframe a scorrimento su un dispositivo touch, resteresti "bloccato" nell'iframe poiché lo scorrimento sarebbe invece della pagina stessa. Sembra che Apple abbia deciso che il comportamento predefinito di un iFrame è "no scroll" e si espande per impedirlo.

Un'opzione potrebbe essere questa soluzione alternativa. Invece di supporre che l'iFrame scorrerà, posiziona l'iframe in un DIV su cui hai il controllo e lascia che scorra.

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

Esempio di markup:

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

Su Safari mobile, ora puoi scorrere il contenuto dell'iFrame ora completamente espanso tramite il div che lo contiene.

Il trucco: sembra davvero brutto su un browser desktop, dato che ora hai doppie barre di scorrimento. Quindi potresti dover fare un po 'di rilevamento del browser con JS per aggirare questo.


1
Continuerei a sostenere che questo non rientra realmente nell'ambito della domanda, perché la soluzione che hai mostrato qui è il modo standard come falsificare lo scrolling iframe buco in iOS Safari, ma prendere in considerazione questo problema iOS è un problema relativo allo scorrimento IFrame (contenuto o altro) quindi è bello averlo qui.
Idra,

1
Immagino di non comprendere appieno la tua domanda. Da quello che ho capito, il problema che stai riscontrando è che in iOS, Mobile Safari cerca di impedire a un iFrame di scorrere in primo luogo e impone una larghezza su di esso. Sto fraintendendo il tuo problema?
DA.

In sostanza, questo è il problema, è solo che la soluzione richiesta è diversa. Nel problema iniziale, il contenuto di IFrame era reattivo, pur avendo contenuto a scorrimento orizzontale, quindi la domanda non era come emulare lo scorrimento dell'iframe , ma come far sì che la larghezza dell'iframe fosse al 100% cioè reattiva, mentre si ha lo scorrimento orizzontale del contenuto con in quell'iframe. Ecco perché l'approccio di cui sopra non funziona in questo caso, perché la reattività progettata è stata interrotta e devi scorrere per vedere il contenuto completo, anche in luoghi in cui normalmente non avresti bisogno.
Idra,

1
Mi scuso, mi sono reso conto di averti ingannato su uno dei commenti. L'iframe non scorre. Questo era il punto, l'iframe non avrebbe dovuto scorrere solo parti del suo contenuto, ad esempio il div#ScrolledArea(in verde) nel mio esempio. Ho appena letto male prima. Ma l'iframe non dovrebbe scorrere solo ridimensionandosi in base all'elemento contenitore, ovvero averewidth: 100%;
Idra,

18

Avevo bisogno di una soluzione cross-browser. I requisiti erano:

  • doveva funzionare sia su iOS che altrove
  • non hanno accesso al contenuto in iFrame
  • ne ho bisogno per scorrere!

Costruendo ciò che ho imparato da @Idra in merito allo scrolling = "no" su iOS e questo post su come adattare il contenuto di iFrame allo schermo in iOS, ecco cosa ho finito. Spero che aiuti qualcuno =)

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

}

1
votato, ma ... perché la regola IE6 nella classe "ios"? :-)
J. Bruni

12

Il problema con tutte queste soluzioni è che l'altezza del file iframe non cambia mai veramente.

Ciò significa che non sarai in grado di centrare gli elementi all'interno iframedell'uso di Javascript position:fixed;, o position:absolute;dal momento cheiframe stesso non scorre mai.

La mia soluzione qui dettagliata è quella di racchiudere tutto il contenuto dell'iframe all'interno di un divutilizzo di questo CSS:

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

In questo modo Safari ritiene che il contenuto non abbia altezza e ti consente di assegnare l'altezza del valore iframecorretto. Ciò consente anche di posizionare gli elementi nel modo desiderato.

Puoi vedere una demo veloce e sporca qui.


1
Questa è l'unica soluzione che ha funzionato per me. Certo, può essere usato solo se controlli i contenuti di iframe, ma nel mio caso, lo faccio. Saluti!
Vince,

Hmm. Il tuo esempio non sembra essere reattivo su iOS?
BrandonRicevato

È stato 2 anni fa quando ho scritto questo. Puoi presentare un problema nel repository?
Pier

dopo aver perso ore e ore su questo problema con Ionic / Cordova su iOS, questa è l'unica cosa che ha funzionato. Grazie!
Andrew,

1
Questo è fantastico, l'unico che ha funzionato, ho trascorso 1 giorno alla ricerca di una soluzione come questa @Pier 100pti per te
Carlos E

5

Questo problema è presente anche su iOS Chrome.

Ho dato un'occhiata a tutte le soluzioni sopra, la maggior parte sono molto confuse.

Se non hai bisogno di supporto per browser meno recenti, imposta la larghezza dell'iframe su 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: controllare il supporto per le unità viewport https://caniuse.com/#feat=viewport-units


1
Chrome per iOS è solo Safari sotto. Utilizza WKWebView. Nessun altro motore di rendering web è consentito in iOS.
Pier,

3

Sto lavorando con ionic2 e la configurazione del sistema è la seguente:


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

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



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

Per me questo problema è stato risolto con questo codice -
per html iframe tag-

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

Vedi CSS dello stesso


.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 proprietà position gioca un ruolo vitale qui nel mio caso.
position: relative;

Potrebbe aiutarti anche tu !!!


0

Solo soluzione 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%;
}

DEMO

Un'altra demo qui con la pagina HTML in iframe


Forse sto implementando la tua soluzione in modo errato, ma quando l'ho provata con il mio caso di test isolato, allora non ha funzionato, in iOS Safari 7.1 iPhone 4. Potresti approfondire come dovrebbe funzionare?
Idra,

OK, sembra che tu abbia frainteso il problema, controlla questo link è il tuo nuovo contenuto demo iframe integrato senza alcun CSS aggiuntivo applicato all'iframe. E se lo guardi in iOS Safari, è ancora reattivo, questo perché questa pagina non ha alcuno scorrimento orizzontale che costringerebbe la larghezza dell'iframe ad essere più ampia della finestra. Come descritto nella domanda, su un sito come questo non è necessario fare nulla affinché iframe sia reattivo.
Idra,

quindi cosa esattamente vuoi che si comporti, fai un esempio per il tuo dato link?
4dgaurav,

0

Ho avuto un problema con la larghezza nel riquadro del contenuto durante la creazione di una barra di scorrimento orizzontale per l'iframe. Si è scoperto che un'immagine manteneva la larghezza più ampia del previsto. Sono stato in grado di risolverlo impostando tutte le immagini css max-width su una percentuale.

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

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

0

infatti per me ho appena lavorato in iOS disabilitando lo scroll

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

e trattare il sistema operativo tramite script.


0

Per me le soluzioni CSS non hanno funzionato. Ma l'impostazione della larghezza a livello di codice fa il lavoro. Al caricamento iframe impostare la larghezza a livello di codice:

 $('iframe').width('100%');
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.