当可见性发生变化时,IFrame滚动条会在Chrome上消失
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当可见性发生变化时,IFrame滚动条会在Chrome上消失相关的知识,希望对你有一定的参考价值。
Windows上的Google Chrome浏览器是否存在渲染iframe滚动条的问题?
我写了一个非常简单的代码来显示正在发生的事情(至少我在chrome 52.0.2743.82米上):
<button>Toggle visibility</button>
<br />
<iframe scrolling="yes" seamless src="https://en.wikipedia.org/wiki/Lorem_ipsum" frameborder="0" style="width: 700px; height: 300px"></iframe>
<script type="text/javascript">
$("button").on("click", function() {
$("iframe").toggle();
});
</script>
加载页面时,可以看到iframe作为滚动条。
隐藏并显示iframe单击按钮。滚动条消失。
这个问题显然只发生在chrome中。
有人也在经历这个吗?任何修复/解决方法?
似乎更新Chrome 52.0.2743.82(http://googlechromereleases.blogspot.fr/2016/07/stable-channel-update.html)中出现了错误
一种可能的解决方法是使用visibility
属性与position: absolute
而不是display
来显示或隐藏iframe
。
此项目存在chrome bug票证:https://bugs.chromium.org/p/chromium/issues/detail?id=641881
我有这个问题,使用visibility
而不是display: none
不是一个选择。
我的解决方法是每当我将iframe设置为再次可见时,在iframe中显示的文档的overflow: scroll
上设置<body>
。这似乎迫使滚动条再次出现在iframe上。然后,您可以将overflow
重置为旧值,滚动条将保留在iframe上。在重置overflow
之前,你需要等待重新绘制,所以我把它放在延迟为0的超时。
function showIframe(iframe) {
var iframeBody = iframe.contentDocument.body;
$(iframe).show();
var oldOverflow = iframeBody.css("overflow");
iframeBody.css("overflow", "scroll");
window.setTimeout(function () {
iframeBody.css("overflow", oldOverflow);
}, 0);
}
如果有问题的iframe不需要滚动,那么滚动条会有一个“闪烁”,所以在需要重新绘制的那个短暂时刻使用visibility
解决方法可能是值得的,以避免闪光。
这是我为我正在构建的应用程序开发的一种解决方法。它在Foundation选项卡控件中有多个<iframe>
元素。
我使用MutationObserver
来观察当<iframe>
的父元素(一个基础div.tabs-content div.content
元素)变成active
时,然后我切换iframe
的文档的overflow
属性。运行时效果是不可思议的。
我最初想直接observe
<iframe>
,但是当iframe本身改变了display
属性时没有引发DOM突变事件,我想因为从技术上来说element.style
值不是DOM结构的一部分。
这是我的代码(Vanilla.js,没有jQuery)。如果您在应用程序中使用,则需要将可见性检测代码替换为适用于您的文档的内容:
window.addEventListener('DOMContentLoaded', function(e) {
var observer = new MutationObserver( onContentMutated );
var options = { attributes: true, childList: false, characterData: false, subtree: false, attributeFilter: ['class'] };
var iframeContainers = document.querySelectorAll('.tabs-content .content');
for(var i = 0; i < iframeContainers.length; i++) {
observer.observe( iframeContainers[i], options );
}
});
function onContentMutated(mutations) {
for(var i = 0; i < mutations.length; i++) {
var m = mutations[i];
var thisIsNowAnActiveTab = m.target.classList.contains('active');
if( thisIsNowAnActiveTab ) {
// get the corresponding iframe and fiddle with its DOM
var iframes = m.target.getElementsByTagName("iframe");
if( iframes.length == 0 ) continue;
var iframe = iframes[0];
iframe.contentWindow.document.documentElement.style.overflow = 'hidden';
// the timeout is to trigger Chrome to recompute the necessity of the scrollbars, which makes them visible again. Because the timeout period is 0 there should be no visible change to users.
setTimeout( function(s) {
s.overflow = 'auto';
}, 0, iframe.contentWindow.document.documentElement.style );
}
console.log( m.type );
}
}
对于给定的示例,您可以:
$("iframe").toggle(1)
在我的情况下,它通过设置高度来工作:
$("iframe").css("height", "100%")
我在Chrome上遇到了类似的问题,iframe嵌入到jQuery UI标签中。首次显示包含iframe的选项卡时,将显示滚动条。但是当我切换到另一个选项卡并返回到带有iframe的选项卡时,滚动条就会消失。这里提出的所有解决方案对我都不起作用。以下是我为解决此问题所做的工作:首先,我创建了标签:
$("#mytabs").tabs();
然后我将一个函数绑定到事件“tabsactivate”,然后检查目标选项卡是否包含iframe。如果是这种情况,我会调用后面描述的函数fixChromeScrollBar():
$("#mytabs").on("tabsactivate", function(event, ui) {
if ($(event.originalEvent.target).attr("href") == "#mytab-with-iframe") {
fixChromeScrollBar();
}
});
最后这里是函数fixChromeScrollBar(),它将iframe体的溢出样式属性(如前所述)设置为“scroll”或“auto”。我注意到,当我只定义“自动”或“滚动”值时,如果我切换到另一个选项卡并返回到iframe,我会丢失滚动条。维护它们的唯一方法是每次出现iframe时在两个值之间交替。这很奇怪,但它有效:
function fixChromeScrollBar() {
var iFrameBody = $("#myiframe").contents().find("body");
var originalOverflow = $(iFrameBody).css("overflow");
if (originalOverflow == "visible" || originalOverflow == "auto") {
$(iFrameBody).css("overflow", "scroll");
} else {
$(iFrameBody).css("overflow", "auto");
}
}
您可以注意到,只有在切换到包含iframe的选项卡时才会调用此方法,因此如果您在此选项卡上多次单击而不切换到另一个选项卡,则此代码将仅在第一次执行时执行。
显然设置src
刷新chrome中的iframe,对于给定的示例代码将是:
<script type="text/javascript">
$("button").on("click", function() {
$('iframe').toggle().attr('src', function(i, val) { return val; });
});
</script>
我将Dai的例子改编为我自己的React IFrame组件。我在选项卡面板中有一个iframe,它本身位于可折叠面板中。当其中任何一个被切换时,我强制iframe重新绘制。它运作得很好。
private iframe: htmlIFrameElement;
private displayObserver: MutationObserver;
componentDidMount() {
// Detect style attribute changes for the containing collapsible components
// If the display goes from 'none' to something else, then we need to redraw the iframe
// so we get the scrollbar back as it should be.
if (isChrome()) {
this.displayObserver = new MutationObserver(this.onContentMutated);
const options = { attributes: true, childList: false, characterData: false, subtree: false, attributeFilter: ['style'] };
const tabPanelAncestor = this.findAncestor(this.iframe, '.tab-panel-content');
if (tabPanelAncestor) {
this.displayObserver.observe(tabPanelAncestor, options);
}
const collapsibleAncestor = this.findAncestor(this.iframe, '.collapsible');
if (collapsibleAncestor) {
this.displayObserver.observe(collapsibleAncestor, options);
}
}
}
private readonly onContentMutated = (mutations: Array<MutationRecord>) => {
R.forEach( (mutation) => {
const targetElement = mutation.target as Element;
const style = targetElement.getAttribute('style');
if (style && !style.match(/display: none/)) {
this.iframe.contentWindow.location.reload(true);
}
}, mutations);
}
private readonly findAncestor = (element: HTMLElement, sel: string): Node | null => {
if (typeof element.closest === 'function') {
return element.closest(sel) || null;
}
let ancestor: HTMLElement | null = element;
while (ancestor) {
if (ancestor.matches(sel)) {
return ancestor;
}
ancestor = ancestor.parentElement;
}
return null;
}
以上是关于当可见性发生变化时,IFrame滚动条会在Chrome上消失的主要内容,如果未能解决你的问题,请参考以下文章
当 iframe 内容的高度发生变化时自动调整 iframe 高度(同域)
当 UIRefreshControl 处于活动状态时,字母滚动条会向下移动?