Html iPad 上的 IFRAME 和 Safari,用户如何滚动内容?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4599153/
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
IFRAMEs and the Safari on the iPad, how can the user scroll the content?
提问by Karlth
According to the Apple iOS mantra it should be possible to scroll the contents of an IFRAME by dragging it with two fingers. Unfortunately running the latest version of iOS on the iPad I have yet to find a single website with an IFRAME that scrolls using this method - no scrollbars appear either.
根据 Apple iOS 的口头禅,应该可以通过用两个手指拖动来滚动 IFRAME 的内容。不幸的是,在 iPad 上运行最新版本的 iOS 我还没有找到一个带有使用这种方法滚动的 IFRAME 的网站 - 也没有出现滚动条。
Does anyone know how a user is supposed to scroll the contents of an IFRAME with the mobile Safari?
有谁知道用户应该如何使用移动 Safari 滚动 IFRAME 的内容?
回答by Karlth
iOS 5 added the following style that can be added to the parent div so that scrolling works.
iOS 5 添加了以下可以添加到父 div 的样式,以便滚动工作。
-webkit-overflow-scrolling:touch
-webkit-overflow-scrolling:touch
回答by Dipin Krishnan
-webkit-overflow-scrolling:touch
as mentioned in the answer is infact the possible solution.
-webkit-overflow-scrolling:touch
正如答案中提到的,实际上是可能的解决方案。
<div style="overflow:scroll !important; -webkit-overflow-scrolling:touch !important;">
<iframe src="YOUR_PAGE_URL" width="600" height="400"></iframe>
</div>
But if you are unable to scroll up and down inside the iframe as shown in image below,
但是,如果您无法在 iframe 内上下滚动,如下图所示,
you could try scrolling with 2 fingers diagonally like this,
你可以尝试像这样用两根手指对角滚动,
This actually worked in my case, so just sharing it if you haven't still found a solution for this.
这实际上在我的情况下有效,所以如果您还没有找到解决方案,请分享它。
回答by deCastongrene
It doesn't appear that iframes display and scroll properly. You can use an object tag to replace an iframe and the contents will be scrollable with 2 fingers. Here's a simple example:
iframe 似乎没有正确显示和滚动。您可以使用对象标签来替换 iframe,内容将可以用 2 根手指滚动。这是一个简单的例子:
<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>
回答by Foreever
This is not my answer, but I just copied it from https://gist.github.com/anonymous/2388015just because the answer is awesome and fixes the problem completely. Credit completely goes to the anonymous author.
这不是我的答案,但我只是从https://gist.github.com/anonymous/2388015复制它只是因为答案很棒并且完全解决了问题。完全归功于匿名作者。
<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>
回答by Toothless Seer
As mentioned in other posts, the combination of css values of overflow: auto; & -webkit-overflow-scrolling: touch;
其他帖子里提到过,overflow: auto; css 值的组合。& -webkit-overflow-scrolling: 触摸;
works when applied to BOTH the iframe in question AND its parent div
适用于有问题的 iframe 及其父 div
With the unfortunate side-effect of double scrollbars on non-touch browsers.
由于双滚动条在非触摸浏览器上的不幸副作用。
The solution I used was to add these css values via javascript/jquery. Which allowed me to use a base css for all browsers
我使用的解决方案是通过 javascript/jquery 添加这些 css 值。这使我可以为所有浏览器使用基本 css
if (isSafariBrowser()){
$('#parentDivID').css('overflow', 'auto');
$('#parentDivID').css('-webkit-overflow-scrolling', 'touch');
$('#iframeID').css('overflow', 'auto');
$('#iframeID').css('-webkit-overflow-scrolling', 'touch');
}
where isSafariBrowser() is defined as foll...
其中 isSafariBrowser() 被定义为 foll...
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;
}
This allowed my application to work on an iPad Note 1) Not tested on other ios systems 2) Not tested this on Android browsers on tablets, may need additional changes
这允许我的应用程序在 iPad 上运行 注意 1) 未在其他 ios 系统上测试 2) 未在平板电脑上的 Android 浏览器上测试过,可能需要额外更改
(so this solution may not be complete)
(所以这个解决方案可能不完整)
回答by ccallendar
This is what I did to get iframe scrolling to work on iPad. Note that this solution only works if you control the html that is displayed inside the iframe.
这就是我为让 iframe 滚动以在 iPad 上工作所做的工作。请注意,此解决方案仅在您控制 iframe 内显示的 html 时才有效。
It actually turns off the default iframe scrolling, and instead causes the body tag inside the iframe to scroll.
它实际上关闭了默认的 iframe 滚动,而是导致 iframe 内的 body 标签滚动。
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:
测试.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>
The same could probably be accomplished using jQuery if you prefer:
如果您愿意,也可以使用 jQuery 完成相同的操作:
$("#iframe").contents().find("body").css({
"height": "100%",
"overflow": "auto",
"-webkit-overflow-scrolling": "touch"
});
I used this solution to get TinyMCE (wordpress editor) to scroll properly on the iPad.
我使用这个解决方案让 TinyMCE(wordpress 编辑器)在 iPad 上正确滚动。
回答by WhatsInAName
The code below works for me (thanks to Christopher Zimmermann for his blog post http://dev.magnolia-cms.com/blog/2012/05/strategies-for-the-iframe-on-the-ipad-problem/). The problems are:
下面的代码对我有用(感谢 Christopher Zimmermann 的博客文章http://dev.magnolia-cms.com/blog/2012/05/strategies-for-the-iframe-on-the-ipad-problem/) . 问题是:
- There are no scroll bars to let the user know that they can scroll
- Users have to use two-finger scrolling
The PDF files are not centered (still working on it)
<!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>
- 没有滚动条让用户知道他们可以滚动
- 用户必须使用两指滚动
PDF 文件未居中(仍在处理中)
<!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>
回答by periklis
Based on this article, I have put together the following snippet that provides some very basic functionality:
基于这篇文章,我整理了以下提供一些非常基本功能的片段:
<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>
Obviously it is far from perfect (given that it practically expands your page height to infinity), but it's the only viable workaround I've found so far.
显然它远非完美(考虑到它实际上将您的页面高度扩展到无穷大),但这是我迄今为止发现的唯一可行的解决方法。
回答by Philipp Lenssen
None of the solutions so far completely worked for me when I tried (sometimes, only buggy on secondary loads), but as a workaround, using an object element as described here, then wrapping in a scrollable div, then setting the object to a very high height (5000px) did the job for me. It's a big workaround and doesn't work incredibly well (for starters, pages over 5000px would cause issues -- 10000px completely broke it for me though) but it seems to get the job done in some of my test cases:
到目前为止,当我尝试时,没有一个解决方案对我完全有效(有时,只有在辅助负载上有问题),但作为一种解决方法,使用此处描述的对象元素,然后包装在可滚动的 div 中,然后将对象设置为非常高(5000 像素)为我完成了这项工作。这是一个很大的解决方法,并且效果不佳(对于初学者来说,超过 5000 像素的页面会导致问题——尽管 10000 像素对我来说完全破坏了它)但它似乎在我的一些测试用例中完成了工作:
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>';
}
Here's hoping Apple will fix the Safari iFrame issues.
希望 Apple 能够解决 Safari iFrame 问题。
回答by DoctorDestructo
The Problem
问题
I help maintain a big, complicated, messy old site in which everything(literally) is nested in multiple levels of iframes-- many of which are dynamically created and/or have a dynamic src. That creates the following challenges:
我帮助维护一个庞大、复杂、凌乱的旧站点,其中所有内容(字面意思)都嵌套在多个级别的 iframe 中——其中许多是动态创建的和/或具有动态 src。这带来了以下挑战:
- Any changes to the HTML structure risk breaking scripts and stylesheets that haven't been touched in years.
- Finding and fixing all of the iframes and src documents manually would take way too much time and effort.
- 对 HTML 结构的任何更改都有可能破坏多年未触及的脚本和样式表。
- 手动查找和修复所有 iframe 和 src 文档会花费太多时间和精力。
Of the solutions posted so far, thisis the only one I've seen that overcomes challenge 1. Unfortunately, it doesn't seem to work on some iframes, and when it does, the scrolling is very glitchy (which seems to cause other bugs on the page, such as unresponsive links and form controls).
到目前为止发布的解决方案中,这是我见过的唯一一个克服挑战 1的解决方案。不幸的是,它似乎不适用于某些 iframe,并且当它起作用时,滚动非常小(这似乎导致其他页面上的错误,例如无响应的链接和表单控件)。
The Solution
解决方案
If the above sounds anything like your situation, you may want to give the following script a try. It forgoes native scrolling and instead makes all iframes draggable within the bounds of their viewport. You only need to add it to the document that contains the top level iframes; it will apply the fix as needed to them and their descendants.
如果以上听起来与您的情况相似,您可能想尝试以下脚本。它放弃了本机滚动,而是使所有 iframe 都可以在其视口范围内拖动。您只需要将其添加到包含顶级 iframe 的文档中即可;它将根据需要将修复应用到它们及其后代。
Here's a working fiddle*, and here's the 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, '||').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, '||').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
};
}
})();
}
})();
* The jsfiddle has mouse support enabled for testing purposes. On a production site, you'd want to set mouse=false.
* jsfiddle 为测试目的启用了鼠标支持。在生产站点上,您需要设置 mouse=false。