Wie kann ein IFrame in iOS Safari reagieren?

134

Das Problem ist, dass in der modernen Web-Welt erwartet wird, dass der IFrame auch reagiert, wenn Sie IFrames zum Einfügen von Inhalten in eine Website verwenden müssen. Theoretisch ist es einfach, einfach zu verwenden <iframe width="100%"></iframe>oder die CSS-Breite so einzustellen, iframe { width: 100%; }aber in der Praxis ist es nicht ganz so einfach, aber es kann sein.

Wenn der iframeInhalt vollständig reagiert und die Größe ohne interne Bildlaufleisten ändern kann, ändert iOS Safari die Größe iframeohne echte Probleme.

Wenn Sie den folgenden Code berücksichtigen:

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

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

Dann funktioniert dies ohne Probleme in iOS 7.1 Safari. Sie können problemlos zwischen Quer- und Hochformat wechseln.

Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein

Ändern Sie jedoch einfach das CSS Content.html, indem Sie Folgendes hinzufügen:

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

Du bekommst das:

Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein

Wie Sie sehen können, nimmt der Iframe die volle Breite der div # ScrolledArea an , obwohl der Content.html- Inhalt vollständig reagiert ( div # ScrolledArea wurde overflow: scrollfestgelegt) und die iframe-Breite 100% beträgt, als ob der Überlauf nicht einmal vorhanden wäre. Demo

Wenn in solchen Fällen der iframeInhalt Bildlaufbereiche enthält, stellt sich die Frage, wie die iframeReaktion erfolgen kann, wenn der Iframe-Inhalt horizontal Bildlaufbereiche aufweist. Das Problem liegt hier nicht in der Tatsache, dass die Content.html nicht reagiert , sondern in der Tatsache, dass die iOS-Safari die Größe des Iframes einfach so ändert, dass der div#ScrolledAreavollständig sichtbar ist.

Idra
quelle
Können Sie einen Link mit uns teilen? Wollen Sie damit sagen, dass iOS einen iFrame auf die gesamte Breite der Seite erweitert, wenn die Seite Inhalt mit white-space: nowrapStil enthält?
DA.
@DA Ich habe Demos sowohl zum Problem als auch zur Lösung hinzugefügt. Und nein, das white-space: nowrapan sich ist nicht das Problem. Ich benutze es einfach, um eine extreme Breite zu bekommen div#ScrolledArea. Das Problem tritt auf, wenn der IFrame-Inhalt horizontal scrollbare Bereiche enthält. In diesem Fall ignoriert die iOS-Safari einfach Ihre Breiteneinstellungen und zeigt den Lochinhalt an und beeinträchtigt die Reaktionsfähigkeit der Website.
Idra
Hmm ... ich frage mich, ob das ein "Feature" ist. Es wäre umständlich, einen scrollbaren Bereich (iFrame) zu haben, der scrollbaren Inhalt enthält. Es wäre sehr schwierig, auf einem Touchscreen damit zu interagieren.
DA.
@DA Natürlich ist dies ein Nichtenfall, und was Sie gesagt haben, kann wahr sein (hängt von der Implementierung ab, funktioniert für uns) und die meisten Websites haben keine horizontal scrollbaren Bereiche, aber wenn Sie dies tun ... können Sie sich nicht einmal vorstellen wie viel Zeit ich dafür aufgewendet habe. Dies kann jedoch auch dann ein Problem sein, wenn Sie Bilder haben, die ausgeblendet und mit Schaltflächen oder Ähnlichem gescrollt sind.
Idra
Es sieht so aus, als ob es verwandte Fragen dazu gibt: stackoverflow.com/questions/5267996/… Es scheint eine "Funktion" der mobilen Safari zu sein ... es wird versucht sicherzustellen, dass die Größe des Inhalts so bemessen wird, wie es der Benutzer kann interagiere immer noch damit. Ich bin mir nicht sicher, was passieren würde, wenn Sie Bildlaufinhalte in einem Bildlauf-Iframe haben ... Wie würde Safari einen Wisch in verschachtelten Bildlaufelementen interpretieren?
DA.

Antworten:

289

Die Lösung für dieses Problem ist eigentlich recht einfach und es gibt zwei Möglichkeiten. Wenn Sie die Kontrolle über Content.html haben, ändern Sie einfach die div#ScrolledAreaBreite des CSS in:

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

Grundsätzlich ist die Idee hier einfach: Sie setzen das widthauf etwas, das kleiner als das Ansichtsfenster ist (in diesem Fall die Iframe-Breite), und überschreiben es dann mit min-width: 100%, um zu berücksichtigen, width: 100%welches iOS Safari standardmäßig überschreibt. Das *width: 100%;ist da, damit der Code IE6-kompatibel bleibt, aber wenn Sie sich nicht für IE6 interessieren, können Sie ihn weglassen. Demo

Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein

Wie Sie jetzt sehen können, div#ScrolledAreabeträgt die Breite tatsächlich 100% und das overflow: scroll;kann es tun und den überfüllten Inhalt verbergen. Wenn Sie Zugriff auf den Iframe-Inhalt haben, ist dies vorzuziehen.

Wenn Sie jedoch keinen Zugriff auf den Iframe-Inhalt haben (aus welchem ​​Grund auch immer), können Sie dieselbe Technik auch für den Iframe selbst anwenden. Verwenden Sie einfach dasselbe CSS für den Iframe:

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

Es gibt jedoch eine Einschränkung: Sie müssen die Bildlaufleisten scrolling="no"auf dem Iframe deaktivieren, damit dies funktioniert:

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

Wenn die Bildlaufleisten zulässig sind, funktioniert dies auf dem Iframe nicht mehr. Wenn Sie jedoch stattdessen die Datei Content.html ändern , können Sie den Bildlauf im Iframe beibehalten. Demo

Idra
quelle
1
Wie @NickGottlieb erwähnt, musste ich !importantdas widthAttribut hinzufügen , um das Iframe Responsive-Web-Design auf einem iPhone 4 mit iOS 7 fertig zu stellen
Malisokan
@ ЮнгвиртТони Es sollte nicht erforderlich sein, damit die Problemumgehung funktioniert. Möglicherweise widthwurde das zuvor mit !importantCSS festgelegt oder von einem CSS mit höherer Priorität überschrieben. In Einzelfällen in iPhone 4 iOS7 wurde es nicht benötigt.
Idra
Ich brauchte auch nicht! Wichtig. Funktioniert auch hervorragend unter iOS 8. Prost
Sam Potts
Ich muss nur bei Bedarf scrollen = nein, sonst scrollen = ja. Was soll ich also erkennen? Ist das ein iOS-Problem? oder ein Webkit-Problem? oder...?
Gerbz
@ggwarpig Dies ist ein iOS-Problem, bei dem die iOS-Safari das nahtlose Attribut automatisch aktiviert und Sie es nicht überschreiben können. Wenn Sie die Kontrolle über den Inhalt haben, müssen Sie den Inhalt ändern, damit dies scrolling="yes"nicht korrigiert werden kann. Damit das Update auf IFRAME funktioniert, müssen Sie nur scrolling="no"auf dem IFRAME
Idra
24

Das Problem scheint zu sein, dass Mobile Safari sich weigert, die Breite Ihres iFrame einzuhalten, wenn das darin enthaltene Dokument breiter ist als von Ihnen angegeben. Beispiel:

http://jsbin.com/hapituto/1

In einem Desktop-Browser sehen Sie einen iFrame und einen Div, die beide auf 300px eingestellt sind. Der Inhalt ist breiter, sodass Sie im iFrame scrollen können.

Auf einer mobilen Safari werden Sie jedoch feststellen, dass der iFrame automatisch auf die Breite des Inhalts erweitert wird.

Ich vermute, dass dies eine Problemumgehung für langjährige Probleme beim Scrollen von Inhalten innerhalb einer Seite ist. Wenn Sie in der Vergangenheit einen großen Bildlauf-Iframe auf einem Touch-Gerät hatten, blieben Sie im Iframe stecken, da dieser anstelle der Seite selbst gescrollt würde. Es scheint, dass Apple entschieden hat, dass das Standardverhalten eines iFrames "kein Bildlauf" ist, und erweitert, um dies zu verhindern.

Eine Option kann diese Problemumgehung sein. Anstatt davon auszugehen, dass der iFrame einen Bildlauf durchführt, platzieren Sie den Iframe in einem DIV, über den Sie die Kontrolle haben, und lassen Sie diesen Bildlauf durchführen.

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

Beispiel-Markup:

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

Auf der mobilen Safari können Sie jetzt den Inhalt des jetzt vollständig erweiterten iFrame über das darin enthaltene div scrollen.

Der Haken: Das sieht in einem Desktop-Browser wirklich hässlich aus, da Sie jetzt doppelte Bildlaufleisten haben. Daher müssen Sie möglicherweise eine Browsererkennung mit JS durchführen, um dies zu umgehen.

DA.
quelle
1
Ich würde immer noch behaupten, dass dies nicht wirklich im Rahmen der Frage liegt, da die hier gezeigte Lösung die Standardmethode zum Fälschen des Iframe- Bildlaufs in iOS Safari ist, aber die Berücksichtigung dieses iOS-Problems ist ein Problem beim IFrame-Bildlauf (Inhalt oder anders) dann ist es schön, es hier zu haben.
Idra
1
Ich glaube, ich verstehe Ihre Frage nicht ganz. Soweit ich weiß, besteht das Problem darin, dass Mobile Safari unter iOS versucht, zu verhindern, dass ein iFrame überhaupt gescrollt wird, und ihm eine Breite aufzwingt. Verstehe ich Ihr Problem falsch?
DA.
Im Wesentlichen ist das das Problem, es ist nur die erforderliche Lösung anders. Bei dem anfänglichen Problem reagierte der IFrame-Inhalt, während der Inhalt horizontal gescrollt wurde. Die Frage war also nicht, wie der Iframe- Bildlauf emuliert werden soll , sondern wie die Iframe-Breite auf 100% eingestellt werden soll, dh ansprechend, während Sie den Inhalt horizontal mit in scrollen dieser Iframe. Aus diesem Grund funktioniert der oben beschriebene Ansatz in diesem Fall nicht, da die entworfene Reaktionsfähigkeit unterbrochen wurde und Sie einen Bildlauf durchführen müssen, um den vollständigen Inhalt anzuzeigen, selbst an Stellen, an denen dies normalerweise nicht erforderlich wäre.
Idra
1
Ich entschuldige mich, mir wurde klar, dass ich Sie bei einem der Kommentare in die Irre geführt habe. Der Iframe scrollt nicht. Das war der Punkt, der Iframe sollte nicht nur Teile seines Inhalts scrollen, dh das div#ScrolledArea(in Grün) in meinem Beispiel. Ich habe es gerade falsch verstanden. Aber der Iframe sollte nicht scrollen, sondern nur die Größe selbst basierend auf dem Containerelement ändern, dh habenwidth: 100%;
Idra
18

Ich brauchte eine browserübergreifende Lösung. Anforderungen waren:

  • musste sowohl auf iOS als auch anderswo funktionieren
  • Sie haben keinen Zugriff auf den Inhalt im iFrame
  • brauche es zum scrollen!

Aufbauend auf dem, was ich von @Idra in Bezug auf Scrollen = "Nein" unter iOS gelernt habe, und diesem Beitrag über das Anpassen von iFrame-Inhalten an den Bildschirm in iOS habe ich Folgendes erreicht. Hoffe es hilft jemandem =)

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
quelle
1
upvoted, aber ... warum die IE6-Regel in der "ios" -Klasse? :-)
J. Bruni
12

Das Problem bei all diesen Lösungen ist, dass sich die Höhe des iframenie wirklich ändert.

Dies bedeutet, dass Sie iframemit Javascript keine Elemente in der Mitte zentrieren position:fixed;können oder dass position:absolute;die Elemente iframeselbst niemals gescrollt werden.

Meine Lösung detailliert hier ist alles , den Inhalt des iframe in einem wickelt divmit diesem CSS:

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

Auf diese Weise glaubt Safari, dass der Inhalt keine Höhe hat, und lässt Sie die Höhe des Inhalts iframerichtig zuweisen . Auf diese Weise können Sie Elemente auch beliebig positionieren.

Sie können hier eine schnelle und schmutzige Demo sehen.

Seebrücke
quelle
1
Dies ist die einzige Lösung, die für mich funktioniert hat. Natürlich kann es nur verwendet werden, wenn Sie den Inhalt des steuern iframe, aber in meinem Fall tue ich das. Prost!
Vince
Hmm. Ihr Beispiel scheint unter iOS nicht zu reagieren?
BrandonReid
Es war vor 2 Jahren, als ich das schrieb. Können Sie ein Problem im Repo einreichen?
Pier
Nachdem Sie mit Ionic / Cordova unter iOS stundenlang an diesem Problem gearbeitet haben, ist dies das einzige, was funktioniert hat. Vielen Dank!
Andrew
1
Das ist großartig, das einzige, was funktioniert hat. Ich habe 1 Tag damit verbracht, nach einer Lösung wie dieser @Pier 100pts für Sie zu suchen
Carlos E
5

Dieses Problem tritt auch bei iOS Chrome auf.

Ich habe alle oben genannten Lösungen durchgesehen, die meisten sind sehr hackig.

Wenn Sie keine Unterstützung für ältere Browser benötigen, setzen Sie einfach die iframe-Breite auf 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 */
}

Hinweis: Überprüfen Sie die Unterstützung für Ansichtsfenstereinheiten https://caniuse.com/#feat=viewport-units

Prathamesh Gharat
quelle
1
Chrome für iOS ist nur Safari darunter. Es verwendet WKWebView. In iOS ist keine andere Web-Rendering-Engine zulässig.
Pier
3

Ich arbeite mit ionic2 und die Systemkonfiguration ist wie folgt:


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

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



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

Für mich wurde dieses Problem mit diesem Code behoben -
für 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>

Siehe CSS des gleichen As-


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

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

Positionseigenschaft spielt hier in meinem Fall eine entscheidende Rolle.
Position: relativ;

Es kann dir auch helfen !!!

S. Yadav
quelle
0

Nur CSS-Lösung

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

Eine weitere Demo hier mit HTML-Seite in Iframe

4dgaurav
quelle
Vielleicht implementiere ich Ihre Lösung falsch, aber als ich sie mit meinem isolierten Testfall ausprobiert habe, hat sie in iOS Safari 7.1 iPhone 4 überhaupt nicht funktioniert. Können Sie näher erläutern, wie dies funktionieren soll?
Idra
OK, es scheint, als hätten Sie das Problem missverstanden. Überprüfen Sie diesen Link , um festzustellen, ob Ihr neuer Demo-Iframe-Inhalt integriert ist, ohne dass zusätzliches CSS auf den Iframe angewendet wird. Wenn Sie es in iOS Safari überprüfen, reagiert es immer noch. Dies liegt daran, dass diese Seite keinen horizontalen Bildlauf aufweist, der dazu führen würde, dass die Iframe-Breite breiter als das Ansichtsfenster ist. Wie in der Frage beschrieben, müssen Sie auf einer Site wie dieser nichts tun, damit der Iframe reagiert.
Idra
Also, was genau soll es sich verhalten, geben Sie ein Beispiel für Ihren angegebenen Link?
4dgaurav
0

Ich hatte ein Problem mit der Breite im Inhaltsbereich, bei dem eine horizontale Bildlaufleiste für den Iframe erstellt wurde. Es stellte sich heraus, dass ein Bild die Breite breiter als erwartet hielt. Ich konnte es lösen, indem ich die maximale CSS-Breite aller Bilder auf ein Prozent festlegte.

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

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

Tatsächlich habe ich gerade in iOS gearbeitet, um die Schriftrolle zu deaktivieren

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

und Behandeln des Betriebssystems per Skript.

Luiz Rossi
quelle
0

Bei mir haben CSS-Lösungen nicht funktioniert. Das programmgesteuerte Einstellen der Breite erledigt den Job jedoch. Stellen Sie beim Laden des Iframes die Breite programmgesteuert ein:

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