簡體   English   中英

在iframe中調用element.focus()將父頁面滾動到Safari iOS10中的隨機位置

[英]Calling element.focus() in iframe scrolls parent page to random position in Safari iOS10

在將焦點設置在iframe內的元素上時,iOS 10.1.1上的Safari似乎有一個錯誤。

當我們在iframe內的元素上調用element.focus()時,Safari將立即向下滾動父頁面並將焦點元素移出屏幕(而不是將焦點元素滾動到視圖中)。

但是,只有當元素位於比設備屏幕高度更高的iframe時才會發生(更短的iframe可以)。

因此,如果有兩個元素,一個在iframe的頂部,另一個在頁面的下方,第一個將精確聚焦,但第二個將在我們設置焦點時跳出屏幕。

對我來說,Safari似乎試圖將元素滾動到視圖中,但數學是錯誤的,它們最終滾動到頁面下方的隨機位置。 在iOS9中一切正常,所以我認為這是iOS10中的一個新bug。

有一些方法可以阻止父頁面滾動或其他一些方法來避免這個錯誤?

我已經整理了一個單頁的要點,在iOS 10設備或模擬器上復制了這個問題。

這是您可以在手機上實際使用的URL: goo.gl/QYi7OE

這是一個plunker,所以你可以檢查桌面行為: https ://embed.plnkr.co/d61KtGlzbVtVYdZ4AMqb/

以及那個plunker的主要版本: https ://gist.github.com/Coridyn/86b0c335a3e5bf72e88589953566b358

這是一個可以運行的gist版本(這里的縮短的URL點): https//rawgit.com/Coridyn/86b0c335a3e5bf72e88589953566b358/raw/62a792bfec69b2c8fb02b3e99ff712abda8efecf/ios-iframe-bug.html

的index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="apple-mobile-web-app-capable" content="yes" />

    <script>
    document.addEventListener('DOMContentLoaded', function(){
        document.querySelector('#frame').srcdoc = document.querySelector('#frameContent').innerHTML;
    });
    </script>
</head>
<body>
    <iframe id="frame" frameborder="1"
        style="width: 100%; height: 1200px;"
        width="100%" height="1200">
    </iframe>

    <!--
    To keep this a one-page example, the content below will be inserted into the iframe using the `srcdoc` attribute.

    The problem occurs in iOS10 regardless of using `srcdoc` or `src` (and regardless of same-domain or cross-domain content).
    -->
    <script id="frameContent" type="text/template">
<div>
    <style>
        .spacer {
            padding-top: 400px;
            padding-bottom: 400px;
        }
        .green-block {
            width: 20px;
            height: 20px;
            background-color: green;
        }
        .red-block {
            width: 20px;
            height: 20px;
            background-color: red;
        }
    </style>

    <div class="green-block" tabindex="0"></div>

    <p>Scroll down and press the 'Focus Green' or 'Focus Red' button.</p>

    <h2>'Focus Green'</h2>
    <p><b>Expected:</b> should set focus on '.green-block' and scroll to the top of the page.</p>
    <p><b>Actual:</b> sets focus but does not scroll page.</p>

    <h2>'Focus Red'</h2>
    <p><b>Expected:</b> should set focus on '.red-block' and not scroll page (because element is already on-screen).</p>
    <p><b>Actual:</b> sets focus and scrolls down to the bottom of the host page.</p>

    <hr/>

    <p class="spacer">1 Filler content to force some visible scrolling 1</p>

    <div class="red-block" tabindex="0"></div>

    <div>
        <button type="button" onclick="document.querySelector('.green-block').focus();">Focus Green</button>
        <p>'Focus Green' should go to top of page, but on iOS10 the view doesn't move.</p>
    </div>
    <div>
        <button type="button" onclick="document.querySelector('.red-block').focus();">Focus Red</button>
        <p>'Focus Red' should stay here, but on iOS10 the view scrolls to the bottom of the page</p>
    </div>

    <p class="spacer">20 Filler content to force some visible scrolling 20</p>
    <p>Bottom of iframe</p>

</div>
    </script>

</body>
</html>

我們發現的事情:

  • 這個問題發生在Safari和Chrome的iOS 10+上
  • Safari iOS 9.3.2上不會出現此問題(行為與桌面瀏覽器匹配,如預期的那樣)
  • 問題只發生在關注非輸入HTML元素時,例如DIV,SPAN,錨標簽等; 設置焦點在INPUT元素上正常工作
  • Desktop Safari工作正常
  • 它是滾動的父頁面,而不是iframe(iframe的大小為其內容的100%,以避免在框架內滾動)
  • 我們嘗試在父頁面上調用preventDefault: window.onscroll = (event) => event.preventDefault(); 但這不起作用,因為scroll事件不可取消
  • 在父頁面上引發的scroll事件似乎來自Safari / Webkit本身,因為callstack中沒有其他函數(當使用DevTools和Error.stack進行檢查時)

我在iOS上滾動跳轉時遇到了類似的問題。 它出現在所有iOS版本上,對我來說,8,9和10。

在真正的iOS 10設備中測試你的plunker並沒有給我帶來麻煩。 我不確定我是否正確測試過。

你能在iOS上試試這個版本的plunker嗎? https://embed.plnkr.co/NuTgqW/

我的問題的解決方法是確保iframe內容中的body和html標記具有定義的100%高度和寬度,以及溢出滾動。 這能夠強制iframe的維度。 它阻止了滾動跳躍。

如果有幫助,請告訴我。

在我的情況下,一個頁面包含一個帶輸入的iframe。 在頁面加載時,輸入得到了焦點。 這導致父頁面滾動到輸入的位置。 它發生在所有瀏覽器中。

解決方案:當頁面開始滾動時,將滾動位置設置回頂部。

因為問題只發生過一次,所以一旦阻止了不需要的滾動,我就使用命名空間事件來刪除監聽器。

$(function() {
    if ($('#iframe').length) {
        var namespace = 'myNamespace';
        $(window).on('scroll.' + namespace, function() {
            $(window).scrollTop(0).off('scroll.' + namespace);
        });
    }
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM