【问题标题】:how to properly display an iFrame in mobile safari如何在移动 Safari 中正确显示 iFrame
【发布时间】:2011-07-13 04:26:27
【问题描述】:

我正在尝试在我的移动网络应用程序中显示 iframe,但我无法将 iframe 的大小限制为 iPhone 屏幕的尺寸。奇怪的是,iframe 元素的 height 和 width 属性似乎没有效果。用 div 包围它可以限制它,但是我无法在 iframe 内滚动。

以前有人在移动 Safari 中处理过 iframe 吗?任何想法从哪里开始?

【问题讨论】:

  • 在不知道他在做什么的情况下,开始争论这样做是否正确是毫无意义的。有些用例需要 iframe。
  • 如果您可以访问 iframed 页面,您可以这样做:stackoverflow.com/questions/19667785/…
  • 这是我发现有趣的 Chris Coyier 最近的一篇文章:blog.codepen.io/2017/12/01/stupid-iframes-stupid-ios
  • 看看这里:stackoverflow.com/a/32993873/1480587 这有一个很好的解决方案,对我有用。

标签: css iframe mobile-safari


【解决方案1】:

是的,你不能用高度和宽度来限制 iframe 本身。你应该在它周围放一个div。如果控制 iframe 中的内容,可以在 iframe 内容中放置一些 JS,告诉父级在收到触摸事件时滚动 div。

像这样:

JS:

setTimeout(function () {
var startY = 0;
var startX = 0;
var b = document.body;
b.addEventListener('touchstart', function (event) {
    parent.window.scrollTo(0, 1);
    startY = event.targetTouches[0].pageY;
    startX = event.targetTouches[0].pageX;
});
b.addEventListener('touchmove', function (event) {
    event.preventDefault();
    var posy = event.targetTouches[0].pageY;
    var h = parent.document.getElementById("scroller");
    var sty = h.scrollTop;

    var posx = event.targetTouches[0].pageX;
    var stx = h.scrollLeft;
    h.scrollTop = sty - (posy - startY);
    h.scrollLeft = stx - (posx - startX);
    startY = posy;
    startX = posx;
});
}, 1000);

HTML:

<div id="scroller" style="height: 400px; width: 100%; overflow: auto;">
<iframe height="100%" id="iframe" scrolling="no" width="100%" id="iframe" src="url" />
</div>

如果您不控制 iframe 内容,则可以以类似的方式在 iframe 上使用叠加层,但是您不能与 iframe 内容进行交互,只能滚动它 - 所以您不能,因为例如,点击 iframe 中的链接。

以前你可以用两根手指在 iframe 中滚动,但现在不行了。

更新:iOS 6 为我们打破了这个解决方案。我一直在尝试对其进行新的修复,但还没有任何效果。此外,由于他们引入了需要 Mac 才能使用的 Remote Web Inspector,因此无法在设备上调试 javascript。

【讨论】:

  • 仅供内部使用。你有什么问题?
  • 好吧..我有一个子 iframe 在主页上调用..这个子 iframe 不在主页内滚动..你可以查看ipad.atwebpages.com/table/try2.html
  • 那个链接失效了。您是否将 JS 放入 iframe 中?然后在主文档中的 iframe 周围放置“滚动”div?
  • 不知道为什么这个链接对你不起作用..但是是的,你是对的,在主页面上,我有一个包含 iframe 元素的滚动 div 并将 JS 代码放在 iframe 页面中。 ..但 iframe 仍然不滚动...您是否有在线工作示例,以便我可以用作参考...再次感谢您的帮助...
  • 您上面的示例对我有用,但是滚动抖动得像疯了一样,因为您使用的是 event.pageX 和 pageY,其中包括滚动信息(然后您正在更改这些信息,这会导致抖动)。切换到使用 event.screenX 和 screenY 会为我带来流畅的滚动。
【解决方案2】:

如果 iFrame 内容不是您的,那么下面的解决方案将不起作用。

在 Android 中,您需要做的就是用 DIV 包围 iframe,并将 div 的高度设置为 document.documentElement.clientHeight。然而,IOS 是另一种动物。虽然我还没有尝试过 Sharon 的解决方案,但它看起来确实是一个不错的解决方案。我确实找到了一个更简单的解决方案,但它只适用于 IOS 5.+。

用 DIV 包围你的 iframe 元素(我们称之为滚动条),设置 DIV 的高度并确保新 DIV 具有以下样式:

$('#scroller').css({'overflow' : 'auto', '-webkit-overflow-scrolling' : 'touch'});

仅此一项即可,但您会注意到,在大多数实现中,iframe 中的内容在滚动时变为空白,并且基本上呈现无用。我的理解是,这种行为早在 iOS 5.0 就已作为错误报告给 Apple。要解决这个问题,请在 iframe 中找到 body 元素并添加 -webkit-transform', 'translate3d(0, 0, 0),如下所示:

$('#contentIframe').contents().find('body').css('-webkit-transform', 'translate3d(0, 0, 0)');

如果您的应用或 iframe 占用大量内存,您可能会遇到麻烦的滚动,您可能需要使用 Sharon 的解决方案。

【讨论】:

    【解决方案3】:

    这仅在您同时控制外部页面和 iframe 页面时才有效。

    在外部页面上,使iframe 不可滚动。

    <iframe src="" height=200 scrolling=no></iframe>
    

    在 iframe 页面上,添加这个。

    <!doctype html>
    ...
    <style>
    html, body {height:100%; overflow:hidden}
    body {overflow:auto; -webkit-overflow-scrolling:touch}
    </style>
    

    这是可行的,因为现代浏览器使用html 来确定高度,所以我们只需给它一个固定高度并将body 变成一个可滚动的节点。

    【讨论】:

    • 我爱你,你愿意嫁给我吗?
    【解决方案4】:

    我已将@Sharon 的代码放在下面,它适用于 iPad 上的两指滚动。您唯一需要更改的就是 iframe 上的 src 属性(我使用的是 PDF 文档)。

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Pdf Scrolling in mobile Safari</title>
    </head>
    <body>
    <div id="scroller" style="height: 400px; width: 100%; overflow: auto;">
    <iframe height="100%" id="iframe" scrolling="no" width="100%" id="iframe" src="data/testdocument.pdf" />
    </div>
    <script type="text/javascript">
        setTimeout(function () {
            var startY = 0;
            var startX = 0;
            var b = document.body;
            b.addEventListener('touchstart', function (event) {
                parent.window.scrollTo(0, 1);
                startY = event.targetTouches[0].pageY;
                startX = event.targetTouches[0].pageX;
            });
            b.addEventListener('touchmove', function (event) {
                event.preventDefault();
                var posy = event.targetTouches[0].pageY;
                var h = parent.document.getElementById("scroller");
                var sty = h.scrollTop;
    
                var posx = event.targetTouches[0].pageX;
                var stx = h.scrollLeft;
                h.scrollTop = sty - (posy - startY);
                h.scrollLeft = stx - (posx - startX);
                startY = posy;
                startX = posx;
            });
        }, 1000);
        </script>
    </body>
    </html>
    

    【讨论】:

    • 你好,我在某处看到 2 指滚动在一些更新前被删除了,这个解决方案仍然对你有用吗?
    • 是的,我可以确认它可以工作,我将它与 jQuery colorbox 插件一起使用。尽管没有滚动条,但它可以用一根手指滚动。
    【解决方案5】:
    <div id="scroller" style="height: 400px; width: 100%; overflow: auto;">
    <iframe height="100%" id="iframe" scrolling="no" width="100%" src="url" />
    </div>
    

    我正在构建我的第一个网站,这帮助我使其适用于我使用 iframe 嵌入的所有网站。

    谢谢!

    【讨论】:

      【解决方案6】:

      Sharon 的方法对我有用,但是当点击 iframe 中的链接然后按下浏览器后退按钮时,会加载页面的缓存版本并且 iframe 不再可滚动。为了克服这个问题,我使用了一些代码来刷新页面,如下所示:

      if ('ontouchstart' in document.documentElement)
           {
              document.getElementById('Scrolling').src = document.getElementById('SCrolling').src;
          }
      

      【讨论】:

        【解决方案7】:

        我实现了以下内容并且效果很好。基本上,我根据 iFrame 内容的大小设置正文尺寸。这确实意味着我们的非 iFrame 菜单可以滚动到屏幕之外,但除此之外,这使得我们的网站可以在 iPad 和 iPhone 上运行。 “workbox”是我们 iFrame 的 ID。

        // Configure for scrolling peculiarities of iPad and iPhone
        
        if (navigator.userAgent.indexOf('iPhone') != -1 || navigator.userAgent.indexOf('iPad') != -1)
        {
            document.body.style.width = "100%";
            document.body.style.height = "100%";
            $("#workbox").load(function (){ // Wait until iFrame content is loaded before checking dimensions of the content
                iframeWidth = $("#workbox").contents().width();
                if (iframeWidth > 400)
                   document.body.style.width = (iframeWidth + 182) + 'px';
        
                iframeHeight = $("#workbox").contents().height();
                if (iframeHeight>200)
                    document.body.style.height = iframeHeight + 'px';
             });
        }
        

        【讨论】:

          【解决方案8】:

          纯粹使用 MSchimpf 和 A​​hmad 的代码,我进行了调整,以便我可以将 iframe 放在 div 中,因此在我的页面上保留用于后退按钮和品牌的页眉和页脚。更新代码:

          <script type="text/javascript">
              $("#webview").bind('pagebeforeshow', function(event){
                  $("#iframe").attr('src',cwebview);
              });
          
              if (navigator.userAgent.indexOf('iPhone') != -1 || navigator.userAgent.indexOf('iPad') != -1)
              {
                  $("#webview-content").css("width","100%");
                  $("#webview-content").css("height","100%");
                  $("#iframe").load(function (){ // Wait until iFrame content is loaded before checking dimensions of the content
                      iframeWidth = $("#iframe").contents().width();
                      if (iframeWidth > 400)
                         $("#webview-content").css("width",(iframeWidth + 182) + 'px');
          
                      iframeHeight = $("#iframe").contents().height();
                      if (iframeHeight>200)
                          $("#webview-content").css("height",iframeHeight + 'px');
                   });
              }       
          </script>  
          

          和html

          <div class="header" data-role="header" data-position="fixed">
          </div>
          
          <div id="webview-content" data-role="content" style="height:380px;">
              <iframe id="iframe"></iframe>   
          </div><!-- /content -->
          
          <div class="footer" data-role="footer" data-position="fixed">
          </div><!-- /footer -->   
          

          【讨论】:

            【解决方案9】:

            不要滚动 IFrame 页面或其内容,滚动父页面。如果控制IFRAME内容,则可以使用iframe-resizer库将iframe元素本身转换为适当的块级元素,具有自然/正确/本机高度。此外,不要尝试在父页面中定位(固定、绝对)您的 iframe,或在模式窗口中显示 iframe,尤其是当它具有表单元素时。

            我还怀疑 iOS Safari 有一种非标准行为,可以将 iframe 的高度扩展到其自然高度,就像 iframe-resizer 库为桌面浏览器所做的那样,它似乎在高度 0px 或 150px 处呈现响应式 iframe 内容或其他一些无用的默认值。如果您需要限制宽度,请尝试 iframe 内的 max-width 样式。

            【讨论】:

              【解决方案10】:

              解决方案是在 iframe 上使用Scrolling="no"

              就是这样。

              【讨论】:

              • 我不知道这是否在最新的 iOS 中被破坏,但对于我来说,我无法让它与动态创建的 iframe 一起使用
              • 更准确地说-使用 scrolling="no" 和 width:100% iframe 仍然会自行调整大小。只有当我将宽度设置为继承或特定像素值时,它才会停止调整大小。
              • 这对我没有任何影响
              猜你喜欢
              • 1970-01-01
              • 2021-02-02
              • 1970-01-01
              • 1970-01-01
              • 2017-10-21
              • 1970-01-01
              • 2018-05-11
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多