web-dev-qa-db-ja.com

iOS 11 WebKit iframeのバグの回避策

iOS WebKit iframeのバグの説明

iOS WebKitは、iframeをコンテンツのフルサイズにサイズ変更します(下の写真を参照)。これは2016年以来知られているバグであり、iOS 11ではまだ解決されていません: https://bugs.webkit.org/show_bug.cgi?id=155198

iOS 11

私の現在の調査結果

1。固定iframeコンテンツ(ビデオなど)の場合

以下にCSSを適用するだけで十分ですが、iframeコンテンツのスクロールを防ぎます。

.fixed iframe {
    width: 0;
    height: 0;

    min-width: 100%;
    min-height: 100%;    
}

2。スクロール可能なiframeコンテンツ(ページなど)の場合

  1. 2つのiframeコンテナが必要です。1つは境界(固定サイズ)として、もう1つはスクロール領域として。
  2. Iframeコンテンツに合わせるには、そのdivコンテナにピクセル単位で定義されたw/hが必要です。相対メジャー(%、vw/vhなど)は機能しません。
  3. 一部のRWDページ(「不完全なRWD」の場合)でiframeオーバーフローが発生しています(iframeはiframeコンテナに収まりません)。残念ながら、外部のiframeからそれを修正することはできません。この問題を解決するには、iframe内のドキュメントには少なくとも以下が必要です。

    body {
        max-width: 100vw !important;
    }
    

    オプションとして、最後の手段としてiframeコンテンツをスケーリングできます。

  4. 2のため、コンテナの割合を維持するには、少なくともCSSメディアクエリまたはJSを使用して高さを調整する必要があります。

一部の不完全なソリューション

私の回避策は答えに掲載されています。

7

これは私がこれまで来たものです。どんな貢献も大歓迎です。 Github Gist の最新バージョン。

/* 1. Beautifiers (optional) */

iframe {
    border: none;
    width: 100%;
    height: 100%;
}

.simple-container {
    width: 50vw;
    height: 50vh;
    padding: 1em;
}

/* 2. Resolving iOS iframe rendering issue */

/* 2.1. Sizing reorganization (obligatory) */

.popover {
    /* To control popover size by .popover-body instead of .popover */
    max-width: 100% !important;
}

.popover-body {
    box-sizing: border-box;
    max-width: 100%;
    max-height: 100%;
}

.iframe-container,
.iframe-container iframe {
    width: 100%;
    height: 100%;
    
    margin: 0 !important;
    padding: 0 !important;
    box-sizing: border-box;
}

.fixed iframe {
    /* This only fits iframe inside iframe-container but prevents scrolling */
    width: 0;
    height: 0;
    
    min-width: 100%;
    min-height: 100%;
}

.popover-body {
    width: 640px; height: 360px;
}

/* 2.2. RWD Resizings (optional) */

@media only screen and (max-width: 568px)
{
    .rwd .popover-body {
        width: 320px; height: 180px;
    }    
}

@media only screen and (min-width: 569px) and (max-width: 965px)
{
    .rwd .popover-body {
        width: 480px; height: 270px;
    }    
}

@media only screen and (min-width: 968px) and (max-width: 1023px)
{
    .rwd .popover-body {
        width: 640px; height: 360px;
    }    
}

/* 2.3. Resolving iOS iframe scrolling issue (obligatory) */

/*
    Due to iOS WebKit bug an iframe content cannot be scrolled, because WebKit renders entire iframe content:
    https://bugs.webkit.org/show_bug.cgi?id=155198
    (still not resolved on iOS11)
    The workaround is to scroll an div container content with full iframe rendered inside.
*/

.scroll {
    overflow: scroll !important;
    -webkit-overflow-scrolling: touch !important;
}

/* 2.4. Resolving iframe and container double scrollbars on desktop browsers (rather obligatory) */

.no-scrollbar {
    position: relative;
}

.no-scrollbar iframe {
    position: absolute;
    top: 0;
    left: 0;
}

.no-scrollbar {
    /* Hide scrollbars in IE Edge */
    /* Autohiding is needed inside iframe document */
    /*-ms-overflow-style: -ms-autohiding-scrollbar;*/
    /* In the parent iframe container we don't want any scrollbars */
    -ms-overflow-style: none;
}

/* 3. Scale non-RWD iframe content (optional) */

/* Warning! iOS 11 Safari crashes on two-fingers zoom of a page with scaled iframe */

.scale {   
    -ms-transform-Origin: 0 0;
    -moz-transform-Origin: 0 0;
    -o-transform-Origin: 0 0;
    -webkit-transform-Origin: 0 0;
    transform-Origin: 0 0;    
}

.scale.x2 {
    width: 200% !important;
    height: 200% !important;
    
    -ms-transform: scale(0.5);
    -moz-transform: scale(0.5);
    -o-transform: scale(0.5);
    -webkit-transform: scale(0.5);
    transform: scale(0.5);
}

.scale.x4 {
    width: 400% !important;
    height: 400% !important;
    
    -ms-transform: scale(0.25);
    -moz-transform: scale(0.25);
    -o-transform: scale(0.25);
    -webkit-transform: scale(0.25);
    transform: scale(0.25);
}

/* DEBUG */

/* To receive click events on iOS */
/*
* {
    cursor: pointer;    
}
*/
.popover-body {
    border: 1px green dotted;
}

.simple-container,
.iframe-container {
    border: 1px blue dotted;
}

iframe {
    border: 1px red dotted;
}
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>iOS iframes</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta http-equiv="cache-control" content="no-cache" />

        <!-- Solution -->
        <link rel="stylesheet" href="iframe.css" />
        
        <!-- Bootstrap with Popover -->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" />
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.bundle.min.js"></script>    
        <script>
            jQuery(function ($) {
                $('a.popover-me').on('click', function(e) {
                    e.preventDefault();
                    if (!$(this).data('bs.popover')) $(this).popover({
                        container: 'body',
                        boundary: 'window',
                        placement: 'auto',
                        trigger: 'manual',
                        html: true,
                        title: $(this).text(),
                        content: '<div class="iframe-container scroll no-scrollbar"><iframe src="' + this.href + '"></iframe></div>'
                    });
                    $(this).popover('toggle');
                });
            });
        </script>
    </head>
    <body class="rwd" style="padding: 2em;">
        <h2>Embracing iOS WebKit weirdness with iframes</h2>
        <div class="alert alert-primary" role="alert">
            Ready for Bootstrap v4.0.0 <a class="popover-me" href="https://en.wikipedia.org/wiki/WebKit">Popover</a>.
        </div>
        <div class="alert alert-danger" role="alert">
            Display this page on iOS device.
        </div>        
        <h3>1. Workaround for scrollable iframe</h3>
        
        <p>
            <div class="popover-body">
                <div class="iframe-container scroll no-scrollbar">
                    <iframe src="https://en.wikipedia.org/wiki/WebKit"></iframe>
                </div>
            </div>
        </p>
        
        <div class="alert alert-warning" role="alert">
            <strong>Hint: </strong>
            <em>
                Some RWD pages (let's say with "incomplete RWD") are experiencing iframe overflow (iframe does not fit into the iframe-container).
                Unfortunately, we can't fix that from the iframe outside and to solve this issue, document inside iframe requires at least:
            </em>
            <br /><br />
<pre>
body {
    /* Resolves iOS overflow rendering bug */
    max-width: 100vw !important;
}
</pre>
            <em>
                Optionally, you can scale iframe document as below.
            </em>
        </div>
        
        <h3>2. Workaround for non-RWD scrollable iframe</h3>
        
        <em>
            Page inside iframe is zoomed out to 50%.
        </em>
        
        <p>
            <div class="popover-body">
                <div class="iframe-container scroll no-scrollbar scale x2">
                    <iframe src="https://en.wikipedia.org/wiki/WebKit"></iframe>
                </div>
            </div>
        </p>
        
        <h3>3. Workaround for fixed iframe</h3>
        
        <em>
            iframe fits in iframe-container.
        </em>
        
        <p>
            <div class="popover-body">
                <div class="iframe-container fixed scroll no-scrollbar">
                    <iframe src="https://en.wikipedia.org/wiki/WebKit"></iframe>
                </div>
            </div>
        </p>
        
        <h3>4. [BUG] Plain iframe inside simple container</h3>
        
        <em>
            iframe should fit into simple container.
        </em>

        <p>
            <div class="simple-container">
                <iframe src="https://en.wikipedia.org/wiki/WebKit"></iframe>
            </div>
        </p>
    </body>
</html>
14