CSS 如何在移动 Safari 中正确显示 iFrame

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5267996/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 23:54:25  来源:igfitidea点击:

how to properly display an iFrame in mobile safari

cssiframemobile-safari

提问by Matt Diamond

I'm trying to display an iframe in my mobile web application, but I'm having trouble restricting the size of the iframe to the dimensions of the iPhone screen. The height and width attributes on the iframe element seem to have no effect, strangely. Surrounding it with a div manages to constrain it, but then I'm unable to scroll within the iframe.

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

Has anyone tackled iframes in mobile safari before? Any ideas where to start?

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

回答by Case

Yeah, you can't constrain the iframe itself with height and width. You should put a div around it. If you control the content in the iframe, you can put some JS within the iframe content that will tell the parent to scroll the div when the touch event is received.

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

like this:

像这样:

The JS:

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

The HTML:

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>

If you don't control the iframe content, you can use an overlay over the iframe in a similar manner, but then you can't interact with the iframe contents other than to scroll it - so you can't, for example, click links in the iframe.

如果您不控制 iframe 内容,则可以以类似的方式在 iframe 上使用叠加层,但是除了滚动之外,您无法与 iframe 内容进行交互 - 因此您不能,例如,单击iframe 中的链接。

It used to be that you could use two fingers to scroll within an iframe, but that doesn't work anymore.

过去,您可以使用两根手指在 iframe 内滚动,但现在已不再适用。

Update: iOS 6 broke this solution for us.I've been attempting to get a new fix for it, but nothing has worked yet. In addition, it is no longer possible to debug javascript on the device since they introduced Remote Web Inspector, which requires a Mac to use.

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

回答by Tmac

If the iFrame content is not yours then the solution below will not work.

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

With Android all you need to do is to surround the iframe with a DIV and set the height on the div to document.documentElement.clientHeight. IOS, however, is a different animal. Although I have not yet tried Sharon's solution it does seem like a good solution. I did find a simpler solution but it only works with IOS 5.+.

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

Surround your iframe element with a DIV (lets call it scroller), set the height of the DIV and make sure that the new DIV has the following styling:

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

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

This alone will work but you will notice that in most implementations the content in the iframe goes blank when scrolling and is basically rendered useless. My understanding is that this behavior has been reported as a bug to Apple as early as iOS 5.0. To get around that problem, find the body element in the iframe and add -webkit-transform', 'translate3d(0, 0, 0) like so:

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

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

If your app or iframe is heavy on memory usage you might get a hitchy scroll for which you might need to use Sharon's solution.

如果您的应用程序或 iframe 占用大量内存,您可能会遇到一个不顺畅的滚动,您可能需要使用 Sharon 的解决方案。

回答by Kernel James

This only works if you control both the outside page and the iframe page.

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

On the outside page, make the iframeunscrollable.

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

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

On the iframe page, add this.

在 iframe 页面上,添加此内容。

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

This works because modern browsers uses htmlto determine the height, so we just give that a fixed height and turn the bodyinto a scrollable node.

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

回答by Eric Pohl

I have put @Sharon's code together into the following, which works for me on the iPad with two-finger scrolling. The only thing you should have to change to get it working is the src attribute on the iframe (I used a PDF document).

我已将@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>

回答by Krossyomind

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

I'm building my first site and this helped me get this working for all sites that I use iframe embededding for.

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

Thanks!

谢谢!

回答by Phil Green

Sharon's method worked for me, however when a link in the iframe is followed and then the browser back button is pressed, the cached version of the page is loaded and the iframe is no longer scrollable. To overcome this I used some code to refresh the page as follows:

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

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

回答by spaceRace

Don't scroll the IFrame page or its content, scroll the parent page. If you control the IFrame content, you can use the iframe-resizerlibrary to turn the iframe element itself into a proper block level element, with a natural/correct/native height. Also, don't attempt to position (fixed, absolute) your iframe in the parent page, or present an iframe in a modal window, especially if it has form elements.

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

I also suspect that iOS Safari has a non-standards behavior that expands your iframe's height to its natural height, much like the iframe-resizer library will do for desktop browsers, which seem to render responsive iframe content at height 0px or 150px or some other not useful default. If you need to contrain width, try a max-width style inside the iframe.

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

回答by MSchimpf

I implemented the following and it works well. Basically, I set the body dimensions according to the size of the iFrame content. It does mean that our non-iFrame menu can be scrolled off the screen, but otherwise, this makes our sites functional with iPad and iPhone. "workbox" is the ID of our iFrame.

我实现了以下内容并且效果很好。基本上,我根据 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';
     });
}

回答by dgig

Purely using MSchimpf and Ahmad's code, I made adjustments so I could have the iframe within a div, therefore keeping a header and footer for back button and branding on my page. Updated code:

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

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

and the html

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

回答by wes

The solution is to use Scrolling="no"on the iframe.

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

That's it.

就是这样。