IFRAMEs und die Safari auf dem iPad, wie kann der Benutzer den Inhalt scrollen?

72

Gemäß dem Apple iOS-Mantra sollte es möglich sein, den Inhalt eines IFRAME durch Ziehen mit zwei Fingern zu scrollen. Leider habe ich mit der neuesten Version von iOS auf dem iPad noch keine einzige Website mit einem IFRAME gefunden, der mit dieser Methode einen Bildlauf durchführt. Es werden auch keine Bildlaufleisten angezeigt.

Weiß jemand, wie ein Benutzer mit der mobilen Safari durch den Inhalt eines IFRAME scrollen soll?

Karlth
quelle
1
Ich hatte kein Problem mit 2 Fingern. Es werden keine Bildlaufleisten angezeigt, aber der Inhalt wird gescrollt.
ughoavgfhw
Bitte migrieren Sie die Frage zum Superuser und veröffentlichen Sie eine Beispielseite, die nicht funktioniert. Das Scrollen mit zwei Fingern funktioniert auf jeder Site, die ich mit meinem iPad ausprobiert habe.
Dour High Arch
1
Es funktioniert sicherlich nicht mit der neuesten Version von iOS (4.2.1). Probieren Sie das Beispiel der w3-Site aus: w3schools.com/tags/tryit.asp?filename=tryhtml_iframe Vergleichen Sie, wie die Seite auf dem iPad und einem Desktop-Browser aussieht. Völlig anders und kein Scrollen möglich. Dies ist eine Programmierfrage, da es sich um eine Frage handelt, welche Stilbits auf dem IFRAME oder einem umgebenden DIV gesetzt werden müssen, damit das Scrollen funktioniert.
Karlth

Antworten:

89

iOS 5 hat den folgenden Stil hinzugefügt, der dem übergeordneten Div hinzugefügt werden kann, damit das Scrollen funktioniert.

-webkit-overflow-scrolling:touch

Karlth
quelle
13
Ich habe festgestellt, dass ich dies als Stil für das übergeordnete div hinzufügen muss. Wenn ich es mit einstelle, jQuery("#div").css("-webkit-overflow-scrolling","touch")funktioniert es nicht wirklich. Außerdem müssen Sie es jetzt kombinieren, overflow:autowas bedeutet, dass Sie bei einigen Nicht-Touch-Browsern möglicherweise doppelte Bildlaufleisten erhalten ...
Frumbert
8
Der folgende jQuery-Zucker funktioniert für mich: gist.github.com/2388015 (dies ist sehr einfach und implementiert kein Kopieren von Grenzen)
N Rohler
Funktioniert es mit ChromeApp auf dem iPad? Es funktioniert bei Safari Mobile
Piotr Czyż
Funktioniert hier in iOS 7. Hat es zuvor unter IOS 6 funktioniert?
Karlth
24

-webkit-overflow-scrolling:touch Wie in der Antwort erwähnt, ist tatsächlich die mögliche Lösung.

<div style="overflow:scroll !important; -webkit-overflow-scrolling:touch !important;">
     <iframe src="YOUR_PAGE_URL" width="600" height="400"></iframe>
</div>

Wenn Sie jedoch nicht in der Lage sind, innerhalb des Iframes nach oben und unten zu scrollen, wie in der Abbildung unten gezeigt, Geben Sie hier die Bildbeschreibung ein

Sie könnten versuchen, mit 2 Fingern diagonal so zu scrollen,

Geben Sie hier die Bildbeschreibung ein

In meinem Fall hat dies tatsächlich funktioniert. Teilen Sie es also einfach mit, wenn Sie noch keine Lösung dafür gefunden haben.

Dipin Krishnan
quelle
9

Es scheint nicht, dass Iframes richtig angezeigt und gescrollt werden. Sie können ein Objekt-Tag verwenden, um einen Iframe zu ersetzen, und der Inhalt kann mit 2 Fingern gescrollt werden. Hier ist ein einfaches Beispiel:

<html>
    <head>
        <meta name="viewport" content="minimum-scale=1.0; maximum-scale=1.0; user-scalable=false; initial-scale=1.0;"/>
    </head>
    <body>
        <div>HEADER - use 2 fingers to scroll contents:</div>
        <div id="scrollee" style="height:75%;" >
            <object id="object" height="90%" width="100%" type="text/html" data="http://en.wikipedia.org/"></object>
        </div>
        <div>FOOTER</div>
    </body>
</html>
deCastongrene
quelle
4
Leider funktioniert das auch nicht. Es scheint, dass in 4.2.1 zwei Finger-Iframe- und Objekt-Scrolling unterbrochen wurden (obwohl dies für Textfelder funktioniert). Hoffentlich wird Apple diesen nervigen Fehler in der nächsten Version beheben.
Karlth
Hat jemand eine gültige Quelle für diesen Fehler? Wie von Apple?
TwDuke
7

Dies ist nicht meine Antwort, aber ich habe sie einfach von https://gist.github.com/anonymous/2388015 kopiert, nur weil die Antwort fantastisch ist und das Problem vollständig behebt. Die Gutschrift geht vollständig an den anonymen Autor.

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
    $(function(){
        if (/iPhone|iPod|iPad/.test(navigator.userAgent))
            $('iframe').wrap(function(){
                var $this = $(this);
                return $('<div />').css({
                    width: $this.attr('width'),
                    height: $this.attr('height'),
                    overflow: 'auto',
                    '-webkit-overflow-scrolling': 'touch'
                });
            });
    })
</script>
Für immer
quelle
4

Wie in anderen Beiträgen erwähnt, ist die Kombination der CSS-Werte des Überlaufs: auto; & -webkit-overflow-scrolling: touch;

funktioniert, wenn es auf BEIDEN fraglichen Iframe UND dessen übergeordnetes div angewendet wird

Mit dem unglücklichen Nebeneffekt von doppelten Bildlaufleisten bei Nicht-Touch-Browsern.

Die Lösung, die ich verwendete, bestand darin, diese CSS-Werte über Javascript / JQuery hinzuzufügen. Dadurch konnte ich ein Basis-CSS für alle Browser verwenden

if (isSafariBrowser()){
    $('#parentDivID').css('overflow', 'auto');
    $('#parentDivID').css('-webkit-overflow-scrolling', 'touch');
    $('#iframeID').css('overflow', 'auto');
    $('#iframeID').css('-webkit-overflow-scrolling', 'touch');
}

Dabei ist isSafariBrowser () wie folgt definiert ...

var is_chrome = navigator.userAgent.indexOf('Chrome') > -1;
var is_safari = navigator.userAgent.indexOf("Safari") > -1;

function isSafariBrowser(){
    if (is_safari){
        if (is_chrome)  // Chrome seems to have both Chrome and Safari userAgents
            return false;
        else
            return true;
    }
    return false;
}

Dadurch konnte meine Anwendung auf einem iPad ausgeführt werden. Hinweis 1) Nicht auf anderen iOS-Systemen getestet. 2) Auf Android-Browsern auf Tablets nicht getestet. Möglicherweise sind zusätzliche Änderungen erforderlich

(Daher ist diese Lösung möglicherweise nicht vollständig.)

Zahnloser Seher
quelle
2
function isSafariBrowser() { return is_safari && !is_chrome; }Außerdem brauchen Sie dafür keine Funktion.
Pavlo
2

Der folgende Code funktioniert für mich (danke an Christopher Zimmermann für seinen Blog-Beitrag http://dev.magnolia-cms.com/blog/2012/05/strategies-for-the-iframe-on-the-ipad-problem/ ) . Die Probleme sind:

  1. Es gibt keine Bildlaufleisten, die den Benutzer darüber informieren, dass er scrollen kann
  2. Benutzer müssen mit zwei Fingern scrollen
  3. Die PDF-Dateien sind nicht zentriert (arbeiten noch daran)

    <!DOCTYPE HTML>
    <html>
    <head>
      <title>Testing iFrames on iPad</title>
      <style>
      div {
        border: solid 1px green;
        height:100px;
      }
    
    .scroller{
        border:solid 1px #66AA66;
        height: 400px;
        width: 400px;
        overflow: auto;
        text-align:center;
    
    }
    </style>
    

    <table>
      <tr>
        <td><div class="scroller">
        <iframe width="400" height="400" src="http://www.supremecourt.gov/opinions/11pdf/11-393c3a2.pdf" ></iframe>
    </div>
        </td>
        <td><div class="scroller">
        <iframe width="400" height="400" src="http://www.supremecourt.gov/opinions/11pdf/11-393c3a2.pdf" ></iframe>
    </div>
        </td>
      </tr>
      <tr>
      <td><div class="scroller">
        <iframe width="400" height="400" src="http://www.supremecourt.gov/opinions/11pdf/11-393c3a2.pdf" ></iframe>
    </div>
        </td>
        <td><div class="scroller">
        <iframe width="400" height="400" src="http://www.supremecourt.gov/opinions/11pdf/11-393c3a2.pdf" ></iframe>
    </div>
        </td>
      </tr>
    </table>
    <div> Here are some additional contents.</div>
    

Was ist in einem Namen
quelle
2

Dies ist, was ich getan habe, damit der Iframe-Bildlauf auf dem iPad funktioniert. Beachten Sie, dass diese Lösung nur funktioniert, wenn Sie den HTML-Code steuern, der im Iframe angezeigt wird.

Das Standard-Iframe-Scrollen wird deaktiviert, und stattdessen wird das Body-Tag im Iframe gescrollt.

main.html :

<!DOCTYPE html>
<html>
<head>
<style type="text/css">
#container {
    position: absolute;
    top: 50px;
    left: 50px;
    width: 400px;
    height: 300px;
    overflow: hidden;
}
#iframe {
    width: 400px;
    height: 300px;
}
</style>
</head>
<body>

    <div id="container">
        <iframe src="test.html" id="iframe" scrolling="no"></iframe>
    </div>

</body>
</html>

test.html :

<!DOCTYPE html>
<html>
<head>
<style type="text/css">
html { 
    overflow: auto; 
    -webkit-overflow-scrolling: touch; 
}
body {
    height: 100%;
    overflow: auto; 
    -webkit-overflow-scrolling: touch;
    margin: 0;
    padding: 8px;
}
</style>
</head>
<body></body>
</html>

Dasselbe könnte wahrscheinlich mit jQuery erreicht werden, wenn Sie Folgendes bevorzugen:

$("#iframe").contents().find("body").css({
    "height": "100%",
    "overflow": "auto", 
    "-webkit-overflow-scrolling": "touch"
});

Ich habe diese Lösung verwendet, um TinyMCE (WordPress-Editor) dazu zu bringen, auf dem iPad richtig zu scrollen.

Kalender
quelle
Sie sollten Kommas anstelle von Semikolons haben. Ansonsten scheint das gut zu sein. Vielen Dank!
Fmstrat
0

Basierend auf diesem Artikel habe ich das folgende Snippet zusammengestellt, das einige sehr grundlegende Funktionen bietet:

<div id = "container"></div>
<script>
function setPDFHeight(){ 
        $("#pdfObject")[0].height = $("#pdfObject")[0].offsetHeight;   
}   
$('#container').append('<div align="center" style="width: 100%; height:100%; overflow: auto !important; -webkit-overflow-scrolling: touch !important;">\
      <object id="pdfObject" width="100%" height="1000000000000" align="center" data="content/lessons/12/t.pdf" type="application/pdf" onload="setPDFHeight()">You have no plugin installed</object></div>');  
</script>

Natürlich ist es alles andere als perfekt (da es Ihre Seitenhöhe praktisch auf unendlich erweitert), aber es ist die einzige praktikable Problemumgehung, die ich bisher gefunden habe.

Periklis
quelle
0

Keine der Lösungen funktionierte bisher vollständig für mich, als ich es versuchte (manchmal nur fehlerhaft bei sekundären Lasten), aber als Problemumgehung, indem ich ein Objektelement wie hier beschrieben verwendete, dann in ein scrollbares Div einwickelte und das Objekt dann auf ein sehr setzte hohe Höhe (5000px) hat den Job für mich erledigt. Es ist eine große Problemumgehung und funktioniert nicht besonders gut (für den Anfang würden Seiten über 5000 Pixel Probleme verursachen - 10000 Pixel haben es für mich jedoch völlig kaputt gemacht), aber es scheint in einigen meiner Testfälle die Arbeit zu erledigen:

var style = 'left: ...px; top: ...px; ' +
        'width: ...px; height: ...px; border: ...';

if (isIOs) {
    style += '; overflow: scroll !important; -webkit-overflow-scrolling: touch !important;';
    html = '<div style="' + style + '">' +
           '<object type="text/html" data="http://example.com" ' +
           'style="width: 100%; height: 5000px;"></object>' +
           '</div>';
}
else {
    style += '; overflow: auto;';
    html = '<iframe src="http://example.com" ' +
           'style="' + style + '"></iframe>';
}

Wir hoffen, dass Apple die Probleme mit Safari iFrame beheben wird.

Philipp Lenssen
quelle
0

Das Problem

Ich helfe bei der Pflege einer großen, komplizierten, chaotischen alten Site, auf der alles (im wahrsten Sinne des Wortes) in mehreren Ebenen von Iframes verschachtelt ist - von denen viele dynamisch erstellt werden und / oder einen dynamischen Quellcode haben. Das schafft folgende Herausforderungen:

  1. Bei Änderungen an der HTML-Struktur können Skripte und Stylesheets beschädigt werden, die seit Jahren nicht mehr berührt wurden.
  2. Das manuelle Suchen und Reparieren aller iframes- und src-Dokumente würde viel zu viel Zeit und Mühe kosten.

Von den bisher veröffentlichten Lösungen ist dies die einzige, die ich gesehen habe, die Herausforderung 1 überwindet. Leider scheint es bei einigen Iframes nicht zu funktionieren, und wenn dies der Fall ist, ist das Scrollen sehr fehlerhaft (was andere zu verursachen scheint) Fehler auf der Seite, z. B. nicht reagierende Links und Formularsteuerelemente).

Die Lösung

Wenn das oben Gesagte Ihrer Situation entspricht, können Sie das folgende Skript ausprobieren. Es verzichtet auf natives Scrollen und macht stattdessen alle Iframes innerhalb der Grenzen ihres Ansichtsfensters ziehbar. Sie müssen es nur dem Dokument hinzufügen, das die Iframes der obersten Ebene enthält. Das Update wird nach Bedarf auf sie und ihre Nachkommen angewendet.

Hier ist eine funktionierende Geige * und hier ist der Code:

(function() {
  var mouse = false //Set mouse=true to enable mouse support
    , iOS = /iPad|iPhone|iPod/.test(navigator.platform);
  if(mouse || iOS) {
    (function() {
      var currentFrame
        , startEvent, moveEvent, endEvent
        , screenY, translateY, minY, maxY
        , matrixPrefix, matrixSuffix
        , matrixRegex = /(.*([\.\d-]+, ?){5,13})([\.\d-]+)(.*)/
        , min = Math.min, max = Math.max
        , topWin = window;
      if(!iOS) {
        startEvent = 'mousedown';
        moveEvent = 'mousemove';
        endEvent = 'mouseup';
      }
      else {
        startEvent = 'touchstart';
        moveEvent = 'touchmove';
        endEvent = 'touchend';
      }
      setInterval(scrollFix, 500);
      function scrollFix() {fixSubframes(topWin.frames);}
      function fixSubframes(wins) {for(var i = wins.length; i; addListeners(wins[--i]));}
      function addListeners(win) {
        try {
          var doc = win.document;
          if(!doc.draggableframe) {
            win.addEventListener('unload', resetFrame);
            doc.draggableframe = true;
            doc.addEventListener(startEvent, touchStart);
            doc.addEventListener(moveEvent, touchMove);
            doc.addEventListener(endEvent, touchEnd);
          }
          fixSubframes(win.frames);
        }
        catch(e) {}
      }
      function resetFrame(e) {
        var doc = e.target
          , win = doc.defaultView
          , iframe = win.frameElement
          , style = getComputedStyle(iframe).transform;
        if(iframe===currentFrame) currentFrame = null;
        win.removeEventListener('unload', resetFrame);
        doc.removeEventListener(startEvent, touchStart);
        doc.removeEventListener(moveEvent, touchMove);
        doc.removeEventListener(endEvent, touchEnd);
        if(style !== 'none') {
          style = style.replace(matrixRegex, '$1|$3|$4').split('|');
          iframe.style.transform = style[0] + 0 + style[2];
        }
        else iframe.style.transform = null;
        iframe.style.WebkitClipPath = null;
        iframe.style.clipPath = null;
        delete doc.draggableiframe;
      }
      function touchStart(e) {
        var iframe, style, offset, coords
          , touch = e.touches ? e.touches[0] : e
          , elem = touch.target
          , tag = elem.tagName;
        currentFrame = null;
        if(tag==='TEXTAREA' || tag==='SELECT' || tag==='HTML') return;
        for(;elem.parentElement; elem = elem.parentElement) {
          if(elem.scrollHeight > elem.clientHeight) {
            style = getComputedStyle(elem).overflowY;
            if(style==='auto' || style==='scroll') return;
          }
        }
        elem = elem.ownerDocument.body;
        iframe = elem.ownerDocument.defaultView.frameElement;
        coords = getComputedViewportY(elem.clientHeight < iframe.clientHeight ? elem : iframe);
        if(coords.elemTop >= coords.top && coords.elemBottom <= coords.bottom) return;
        style = getComputedStyle(iframe).transform;
        if(style !== 'none') {
          style = style.replace(matrixRegex, '$1|$3|$4').split('|');
          matrixPrefix = style[0];
          matrixSuffix = style[2];
          offset = parseFloat(style[1]);
        }
        else {
          matrixPrefix = 'matrix(1, 0, 0, 1, 0, ';
          matrixSuffix = ')';
          offset = 0;
        }
        translateY = offset;
        minY = min(0, offset - (coords.elemBottom - coords.bottom));
        maxY = max(0, offset + (coords.top - coords.elemTop));
        screenY = touch.screenY;
        currentFrame = iframe;
      }
      function touchMove(e) {
        var touch, style;
        if(currentFrame) {
          touch = e.touches ? e.touches[0] : e;
          style = min(maxY, max(minY, translateY + (touch.screenY - screenY)));
          if(style===translateY) return;
          e.preventDefault();
          currentFrame.contentWindow.getSelection().removeAllRanges();
          translateY = style;
          currentFrame.style.transform = matrixPrefix + style + matrixSuffix;
          style = 'inset(' + (-style) + 'px 0px ' + style + 'px 0px)';
          currentFrame.style.WebkitClipPath = style;
          currentFrame.style.clipPath = style;
          screenY = touch.screenY;
        }
      }
      function touchEnd() {currentFrame = null;}
      function getComputedViewportY(elem) {
        var style, offset
          , doc = elem.ownerDocument
          , bod = doc.body
          , elemTop = elem.getBoundingClientRect().top + elem.clientTop
          , elemBottom = elem.clientHeight
          , viewportTop = elemTop
          , viewportBottom = elemBottom + elemTop
          , position = getComputedStyle(elem).position;
        try {
          while(true) {
            if(elem === bod || position === 'fixed') {
              if(doc.defaultView.frameElement) {
                elem = doc.defaultView.frameElement;
                position = getComputedStyle(elem).position;
                offset = elem.getBoundingClientRect().top + elem.clientTop;
                viewportTop += offset;
                viewportBottom = min(viewportBottom + offset, elem.clientHeight + offset);
                elemTop += offset;
                doc = elem.ownerDocument;
                bod = doc.body;
                continue;
              }
              else break;
            }
            else {
              if(position === 'absolute') {
                elem = elem.offsetParent;
                style = getComputedStyle(elem);
                position = style.position;
                if(position === 'static') continue;
              }
              else {
                elem = elem.parentElement;
                style = getComputedStyle(elem);
                position = style.position;
              }
              if(style.overflowY !== 'visible') {
                offset = elem.getBoundingClientRect().top + elem.clientTop;
                viewportTop = max(viewportTop, offset);
                viewportBottom = min(viewportBottom, elem.clientHeight + offset);
              }
            }
          }
        }
        catch(e) {}
        return {
          top: max(viewportTop, 0)
          ,bottom: min(viewportBottom, doc.defaultView.innerHeight)
          ,elemTop: elemTop
          ,elemBottom: elemBottom + elemTop
        };
      }
    })();
  }
})();

* Für die jsfiddle ist die Mausunterstützung zu Testzwecken aktiviert. Auf einer Produktionsstätte möchten Sie mouse = false setzen.

DoctorDestructo
quelle
-1

Nach langem Hin und Her entdeckte ich, wie man auf meinem iPad in Iframes blättert. Das Geheimnis bestand darin, auf der linken Seite des Iframe-Bereichs (und möglicherweise etwas außerhalb des Randes) einen vertikalen Fingerwisch auszuführen (ein Finger war in Ordnung). Auf einem Laptop oder PC befindet sich die Bildlaufleiste rechts, daher habe ich natürlich viel Zeit auf meinem iPad verbracht, um mit Fingerbewegungen auf der rechten Seite zu experimentieren. Nur wenn ich es auf der linken Seite versuchte, rollte der Iframe.

ccs
quelle
-1

Fügen Sie overflow: auto;dem Stil hinzu und die Zwei-Finger-Schriftrolle sollte funktionieren.

ske57
quelle
1
Das tut es leider nicht. Die richtige Antwort ist oben markiert.
Karl
Sie müssen beide verwenden, um ältere und neuere iPads oder Personen
anzusprechen, die