当可见性发生变化时,IFrame滚动条会在Chrome上消失

时间:2016-07-24 23:47:26

标签: javascript html google-chrome iframe scrollbar

Windows上的Google Chrome浏览器是否存在渲染iframe滚动条的问题?

我写了一个非常简单的代码来显示正在发生的事情(至少我在chrome 52.0.2743.82 m上):

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

Plunker link to code

加载页面时,iframe作为滚动条可见。

隐藏并显示iframe单击按钮。滚动条消失。

这个问题显然只发生在chrome。

任何人都有这样的经历吗?任何修复/解决方法?

7 个答案:

答案 0 :(得分:4)

似乎更新Chrome 52.0.2743.82(http://googlechromereleases.blogspot.fr/2016/07/stable-channel-update.html

出现了错误

一种可能的解决方法是使用visibility与[{1}}而不是position: absolute的属性来显示或隐藏display

此商品存在chrome bug票证:https://bugs.chromium.org/p/chromium/issues/detail?id=641881

答案 1 :(得分:3)

我遇到了这个问题,使用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);
}

有一个&#34; flash&#34;但是,如果所讨论的iframe不需要滚动,则使用此解决方法的滚动条,因此在需要重新绘制的那个短暂时刻使用visibility解决方法可能是值得的,以避免闪现。 / p>

答案 2 :(得分:1)

这是我为我正在构建的应用程序开发的解决方法。它在Foundation选项卡控件中有多个<iframe>元素。

我使用MutationObserver来观察<iframe>的父元素(基金会div.tabs-content div.content元素)何时变为active,然后我切换{{1}文档的iframe属性。运行时效果是不可思议的。

我原本想直接overflow observe,但是当iframe本身更改了<iframe>属性时,没有引发任何DOM突变事件,我想因为技术上讲display 1}}值不是DOM结构的一部分。

这是我的代码(Vanilla.js,没有jQuery)。如果您在应用程序中使用,则需要将可见性检测代码替换为适用于您的文档的内容:

element.style

答案 3 :(得分:1)

对于给定的例子,你可以这样做:
$("iframe").toggle(1)

在我的情况下,它通过设置高度来工作:
$("iframe").css("height", "100%")

答案 4 :(得分:0)

我在Chrome上遇到类似问题,iframe嵌入到jQuery UI标签中。首次显示包含iframe的选项卡时,将显示滚动条。但是当我切换到另一个选项卡并返回到带有iframe的选项卡时,滚动条就会消失。这里提出的所有解决方案对我来说都不起作用。 以下是我为解决此问题所做的工作: 首先,我创建标签:

$("#mytabs").tabs();

然后我将一个函数绑定到事件&#34; tabsactivate&#34;我检查目标选项卡是否包含iframe。如果是这种情况,我会调用稍后描述的函数fixChromeScrollBar():

$("#mytabs").on("tabsactivate", function(event, ui) {
    if ($(event.originalEvent.target).attr("href") == "#mytab-with-iframe") {
        fixChromeScrollBar();
    }
});

最后这里是函数fixChromeScrollBar(),它将iframe体的溢出样式属性(如上所述)设置为&#34; scroll&#34;或&#34; auto&#34;。我注意到,当我只定义&#34; auto&#34;或&#34;滚动&#34;然后,如果我切换到另一个选项卡并返回到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的选项卡时才会调用此方法,因此如果您在此选项卡上多次单击而不切换到另一个选项卡,则此代码将仅在第一次执行时执行。

答案 5 :(得分:0)

显然设置src刷新chrome中的iframe,对于给定的示例代码将是:

<script type="text/javascript">
    $("button").on("click", function() {
        $('iframe').toggle().attr('src', function(i, val) { return val; });
    });
</script>

答案 6 :(得分:0)

我将戴的例子改编为我自己的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;
}