如何让 IFrame 在 iOS Safari 中响应?

Posted

技术标签:

【中文标题】如何让 IFrame 在 iOS Safari 中响应?【英文标题】:How to get an IFrame to be responsive in iOS Safari? 【发布时间】:2014-05-29 19:01:04 【问题描述】:

问题在于,当您必须使用 IFrame 将内容插入网站时,在现代网络世界中,预计 IFrame 也会响应。理论上很简单,只需使用<iframe width="100%"></iframe> 或将CSS 宽度设置为iframe width: 100%; ,但实际上并不是那么简单,但可以。

如果iframe 内容完全响应并且可以在没有内部滚动条的情况下自行调整大小,那么ios Safari 将调整iframe 的大小而不会出现任何实际问题。

如果你考虑下面的代码:

<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   src="Content.html"></iframe>
    </div>
</body>
</html>

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>

然后这在 iOS 7.1 Safari 中没有问题。您可以毫无问题地在横向和纵向之间切换。

但是,只需通过添加以下内容来更改 Content.html CSS:

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

你明白了:

如您所见,即使 Content.html 内容是完全响应式的(div#ScrolledArea 设置了 overflow: scroll)并且 iframe 宽度是 100% iframe 仍然占据 div#ScrolledArea 的整个宽度,就好像溢出甚至不存在一样。 Demo

在这种情况下,iframecontent 上是否有滚动区域,问题就变成了,当 iframe 内容具有水平滚动区域时,如何让 iframe 响应?这里的问题不在于 Content.html 没有响应,而在于 iOS Safari 只是简单地调整 iframe 的大小以使 div#ScrolledArea 完全可见。

【问题讨论】:

你能和我们分享一个链接吗?你是说如果页面内的页面具有white-space: nowrap 样式的内容,iOS 会将 iFrame 扩展到页面的整个宽度? @DA 我在问题和解决方案中都添加了演示。不,white-space: nowrap 本身不是问题。我只是用它来获得div#ScrolledArea 的极端宽度。当 IFrame 内容中有水平滚动区域时,问题就出现了。如果是这种情况,iOS Safari 会简单地忽略您的宽度设置并显示孔内容并破坏网站的响应能力。 嗯...我想知道这是否是一个“功能”。拥有一个包含可滚动内容的可滚动区域 (iFrame) 会很尴尬。在触摸屏上进行交互是一件非常困难的事情。 @DA 当然,这是一个侄女案例,您所说的可能是真的(取决于实施,对我们有用)并且大多数网站没有水平滚动区域,但是当您这样做时。 ..你甚至无法想象我在这上面花了多少时间。但这可能是一个问题,即使您有隐藏的图像并使用按钮或类似的东西滚动。 看起来有相关的问题:***.com/questions/5267996/… 它似乎是移动 safari 的一个“功能”......它试图确保内容的大小符合用户仍然可以与之交互。我不确定如果您在滚动 iframe 中有滚动内容会发生什么……Safari 将如何解释嵌套滚动元素中的滑动? 【参考方案1】:

这个问题的解决方案其实很简单,有两种方法可以解决。如果您可以控制 Content.html,那么只需将 div#ScrolledArea 宽度 CSS 更改为:

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

基本上这里的想法很简单,您将width 设置为小于视口(在这种情况下为iframe 宽度),然后用min-width: 100% 覆盖它以允许iOS Safari 通过实际width: 100%默认覆盖。 *width: 100%; 在那里,因此代码将保持与 IE6 兼容,但如果您不关心 IE6,则可以省略它。 Demo

正如您现在所看到的,div#ScrolledArea 的宽度实际上是 100%,overflow: scroll; 可以做到这一点并隐藏溢出的内容。如果您可以访问 iframe 内容,则最好这样做。

但是,如果您无权访问 iframe 内容(无论出于何种原因),那么您实际上可以在 iframe 本身上使用相同的技术。只需在 iframe 上使用相同的 CSS:

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

但是,这样做有一个限制,您需要在 iframe 上使用 scrolling="no" 关闭滚动条才能使其工作:

<iframe   scrolling="no" src="Content.html"></iframe>

如果允许滚动条,那么这将不再适用于 iframe。也就是说,如果您修改 Content.html,则可以在 iframe 中保留滚动。 Demo

【讨论】:

就像@NickGottlieb 提到的那样,我必须将!important 添加到width 属性中才能在带有iOS 7 的iPhone 4 上准备好iframe responsive-web-design @ЮнгвиртТони 解决方法应该不需要它,有可能width 较早设置为!important 或更高优先级的CSS 覆盖它。在 iPhone 4 iOS7 的个别情况下,它是不需要的。 我也不需要 !important。也适用于 iOS 8。干杯 只有在必要时才需要滚动=否,否则滚动=是。那么我应该检测什么?这是iOS问题吗?还是 webkit 问题?还是...? @ggwarpig 这是一个 iOS 问题,iOS Safari 会自动打开无缝属性,您无法覆盖它。如果您可以控制内容,那么您需要修改内容才能拥有scrolling="yes",否则无法纠正此问题,只有在 IFRAME 上使用 scrolling="no" 才能修复此问题 【参考方案2】:

问题似乎在于,如果 Mobile Safari 包含的文档比您指定的宽,它将拒绝遵守您的 iFrame 的宽度。示例:

http://jsbin.com/hapituto/1

在桌面浏览器上,您会看到 iFrame 和 Div 都设置为 300 像素。内容更宽,因此您可以滚动 iFrame。

但是,在移动 Safari 上,您会注意到 iFrame 会自动扩展为内容的宽度。

我的猜测是,这是解决页面内滚动内容的长期问题的解决方法。过去,如果您在触摸设备上有一个大的滚动 iframe,您会“卡住”在 iframe 中,因为它会滚动而不是页面本身。 Apple 似乎已经决定 iFrame 的默认行为是“不滚动”并展开以防止它。

一个选项可能是这种解决方法。不要假设 iFrame 会滚动,而是将 iframe 放在您可以控制的 DIV 中并让其滚动。

示例:http://jsbin.com/zakedaja/1

示例标记:

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

在移动 Safari 上,您现在可以通过包含它的 div 滚动现已完全展开的 iFrame 的内容。

问题:这在桌面浏览器上看起来真的很难看,因为现在你有双滚动条。所以你可能需要用 JS 做一些浏览器检测来解决这个问题。

【讨论】:

我仍然认为这实际上不在问题的范围内,因为您在此处展示的解决方案是如何在 iOS 中伪造 iframe 滚动孔的标准方法Safari,但考虑到这个 iOS 问题是关于 IFrame 滚动(内容或其他)的问题,所以很高兴在这里拥有它。 我想我不完全理解你的问题。据我了解,您遇到的问题是,在 iOS 中,Mobile Safari 会首先尝试阻止 iFrame 滚动并在其上强制设置宽度。我误解你的问题了吗? 本质上就是问题所在,只是需要的解决方案不同。在最初的问题中,IFrame 内容是响应式的,同时具有水平滚动的内容,所以问题不是如何模拟 iframe 滚动,而是如何使 iframe 宽度达到 100% 即响应式,而您在该 iframe 中有水平滚动内容。这就是为什么上述方法在这种情况下不起作用的原因,因为设计的响应性已被破坏,您需要滚动查看完整内容,即使在您通常不需要的地方也是如此。 我很抱歉,我意识到我在其中一个 cmets 上误导了您。 iframe 不滚动。这就是重点,iframe 不应该只滚动它的部分内容,即我的示例中的div#ScrolledArea(绿色)。我之前只是看错了。但是 iframe 不应该只根据容器元素滚动调整自身的大小,即有 width: 100%;【参考方案3】:

我需要一个跨浏览器的解决方案。要求是:

需要同时在 iOS 和其他地方工作 无权访问 iFrame 中的内容 需要它来滚动!

基于我从 @Idra 学到的关于 iOS 上的 scrolling="no" 和 this post 关于在 iOS 中将 iFrame 内容适配到屏幕上的知识,这就是我最终得出的结论。希望它可以帮助某人=)

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


【讨论】:

赞成,但是......为什么“ios”类中的 IE6 规则? :-)【参考方案4】:

所有这些解决方案的问题在于iframe 的高度从未真正改变过。

这意味着您将无法使用 javascriptposition:fixed;position:absolute;iframe 中的元素居中,因为 iframe 本身永远不会滚动。

我的解决方案detailed here 是使用此 CSS 将 iframe 的所有内容包装在 div 中:

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

这样 Safari 认为内容没有高度,并允许您正确分配 iframe 的高度。这也允许您以任何您希望的方式定位元素。

You can see a quick and dirty demo here.

【讨论】:

这是唯一对我有用的解决方案。当然,它只能在您控制iframe 的内容的情况下使用,但在我的情况下,我可以。干杯! 嗯。您的示例在 iOS 上似乎没有响应? 我写这篇文章是两年前的事了。您可以在 repo 中提出问题吗? 在 iOS 上的 Ionic/Cordova 问题上浪费了数小时后,这是唯一有效的方法。谢谢! 这太棒了,唯一有效的,我花了 1 天时间寻找像这样的解决方案 @Pier 100pts 给你【参考方案5】:

iOS Chrome 上也存在此问题。

我浏览了上面所有的解决方案,大多数都非常hacky。

如果您不需要对旧浏览器的支持,只需将 iframe 宽度设置为 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 */

注意:检查对视口单位的支持 https://caniuse.com/#feat=viewport-units

【讨论】:

Chrome for iOS 只是下面的 Safari。它使用 WKWebView。 iOS 中不允许使用其他 Web 渲染引擎。【参考方案6】:

我正在使用ionic2,系统配置如下-


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

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



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

对我来说,此代码已解决此问题- 对于 html iframe 标签-

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

看css的一样——


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


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

Position 属性在我的例子中起着至关重要的作用。position:relative;

也许对你也有帮助!!!

【讨论】:

【参考方案7】:

我在为 iframe 创建水平滚动条的内容窗格上遇到了宽度问题。事实证明,图像的宽度比预期的要宽。我能够通过将所有图像 css max-width 设置为百分比来解决它。

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

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

【讨论】:

这实际上为我完成了这项工作而无需 css【参考方案8】:

仅 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

另一个demo here 在 iframe 中带有 HTML 页面

【讨论】:

也许我错误地实现了你的解决方案,但是当我用我隔离的测试用例尝试它时,它在 iOS Safari 7.1 iPhone 4 中根本不起作用。你能详细说明这应该如何工作? 好吧,好像你误解了这个问题,check this link out 这是你的新演示 iframe 内容集成,没有任何额外的 CSS 应用于 iframe。如果您在 iOS Safari 中查看它,那么它仍然是响应式的,这是因为该页面没有任何水平滚动会迫使 iframe 宽度比视口更宽。如问题中所述,在这样的网站上,您无需为 iframe 做出任何响应即可。 那么您到底希望它表现什么,为您给定的链接举个例子?【参考方案9】:

实际上对我来说只是在 ios 中禁用了滚动

&lt;iframe src="//www.youraddress.com/" scrolling="no"&gt;&lt;/iframe&gt;

并通过脚本处理操作系统。

【讨论】:

【参考方案10】:

对我来说,CSS 解决方案不起作用。但是以编程方式设置宽度可以完成这项工作。 在 iframe 加载时以编程方式设置宽度:

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

【讨论】:

以上是关于如何让 IFrame 在 iOS Safari 中响应?的主要内容,如果未能解决你的问题,请参考以下文章

safari,IOS下iframe宽高度被内容撑出设备高度

Phonegap / Cordova ios外部链接iframe无法在safari中打开

iOS 12 Safari iframe + 位置:固定 + translate3d 错误

带有 iframe 的嵌入式网站中的 iOS 滚动问题

如何在 div 或 iframe 等其他元素上模拟活动输入或 textarea 周围的 Chrome/Safari 边框?

如何让iframe中页面全屏显示