機能するクロスドメインのiframeの高さ自動サイズ変更機能はありますか?


110

いくつかの解決策を試しましたが、成功しませんでした。わかりやすいチュートリアルを使用して、できればそこに解決策があるかどうか疑問に思っています。


2
うまくいかなかった解決策はありますか?
Yzmir Ramirez、2011

1
私はこれを試しましたが、記事に記載されているようにwebkitブラウザーで異常動作します:css-tricks.com/cross-domain-iframe-resizing別のものがありましたが、URLを思い出せません。
J82 2011


これはあなたの質問に答えますか?コンテンツに合わせてiframeの幅と高さを調整します
abbr

回答:


68

次の3つの選択肢があります。

1. iFrame-resizerを使用する

これは、iFrameのコンテンツのサイズを維持するための単純なライブラリです。IE8-10のフォールバックを備えたPostMessageおよびMutationObserver APIを使用します。また、コンテンツページが含まれているiFrameが特定のサイズであることを要求するオプションがあり、iFrameを使い終わったら閉じることもできます。

https://github.com/davidjbradshaw/iframe-resizer

2. Easy XDM(PostMessage + Flashコンボ)を使用する

Easy XDMは、いくつかのブラウザーで異なるウィンドウ間のクロスドメイン通信を可能にするための一連のトリックを使用しており、iframeのサイズ変更に使用する例があります。

http://easyxdm.net/wp/2010/03/17/resize-iframe-based-on-content/

http://kinsey.no/blog/index.php/2010/02/19/resizing-iframes-using-easyxdm/

Easy XDMは、最新のブラウザーではPostMessageを使用し、古いブラウザーのフォールバックとしてFlashベースのソリューションを使用することで機能します。

Stackoverflowのこのスレッドも参照してください(他にもありますが、これはよくある質問です)。また、Facebookも同様のアプローチを使用しているようです。

3.サーバーを介して通信する

別のオプションは、iframeの高さをサーバーに送信し、そのサーバーからJSONPを使用して親Webページからポーリングすることです(または、可能であればロングポーリングを使用します)。


1
PostMessageの場合、jQueryを既に使用している場合は、Ben Almanの素晴らしいpostMessageプラグインを確認することもできます:benalman.com/projects/jquery-postmessage-plugin
rinogo

8
iFrame-resizerは、iframeコンテンツをホストするサーバーにアクセスする必要があります。そのため、自分が管理するドメインでのみ使用できます。
Hokascha

良いキャッチ、@ Hokascha。プロジェクトはクロスドメインiframeのサポートを主張していますが、ドキュメントを読むと、埋め込みドメインへのサーバーアクセスが依然として必要であることがわかります。
StockB

1
これらの「代替手段」はどれもこの問題の実際の解決策ではありません。質問者は、自分が制御できないWebサイトからクロスドメインiFrameのiFrameの高さを設定したいと考えています。1.サーバーアクセスが必要です。2.貧しいと思うソフトウェアが必要です。Easy XDMは10年前のように作成されました。2019年以降の最新バージョンでは、flashが必要です。ありがたいことに、フラッシュは死んでおり、誰もそれに頼るべきではありません。3.サーバーアクセスが必要です。
redanimalwar

26

そのコンテンツに基づいて動的にiframeの高さを設定するための解決策を得ました。これは、クロスドメインコンテンツに対して機能します。これを達成するために従うべきいくつかのステップがあります。

  1. 「abc.com/page」のWebページにiframeを追加したとします。

    <div> <iframe id="IframeId" src="http://xyz.pqr/contactpage" style="width:100%;" onload="setIframeHeight(this)"></iframe> </div>

  2. 次に、Webページ "abc.com/page"の下でウィンドウ "message"イベントをバインドする必要があります

window.addEventListener('message', function (event) {
//Here We have to check content of the message event  for safety purpose
//event data contains message sent from page added in iframe as shown in step 3
if (event.data.hasOwnProperty("FrameHeight")) {
        //Set height of the Iframe
        $("#IframeId").css("height", event.data.FrameHeight);        
    }
});

iframeのロード時に、「FrameHeight」メッセージを含むiframeウィンドウコンテンツにメッセージを送信する必要があります。

function setIframeHeight(ifrm) {
   var height = ifrm.contentWindow.postMessage("FrameHeight", "*");   
}
  1. ここのiframeの下に追加されたメインページ "xyz.pqr / contactpage"では、すべてのメッセージが "abc.com/page"の親ウィンドウから受信されるウィンドウ "message"イベントをバインドする必要があります
window.addEventListener('message', function (event) {

    // Need to check for safety as we are going to process only our messages
    // So Check whether event with data(which contains any object) contains our message here its "FrameHeight"
   if (event.data == "FrameHeight") {

        //event.source contains parent page window object 
        //which we are going to use to send message back to main page here "abc.com/page"

        //parentSourceWindow = event.source;

        //Calculate the maximum height of the page
        var body = document.body, html = document.documentElement;
        var height = Math.max(body.scrollHeight, body.offsetHeight,
            html.clientHeight, html.scrollHeight, html.offsetHeight);

       // Send height back to parent page "abc.com/page"
        event.source.postMessage({ "FrameHeight": height }, "*");       
    }
});

3
スムーズに動作します。どうもありがとう!
Alex Leonov 2017年

単にこれが私が見つけることができる最も技術的な方法です。素晴らしい仕事@sudhir、ありがとう:)
java acm

14

私がやったことは、iFrameの高さを段階的に設定しながら、iframeのscrollWidthをサイズが変わるまで比較したことです。そしてそれは私にとってはうまくいきました。増分は必要に応じて調整できます。

   <script type="text/javascript">
    function AdjustIFrame(id) {
        var frame = document.getElementById(id);
        var maxW = frame.scrollWidth;
        var minW = maxW;
        var FrameH = 100; //IFrame starting height
        frame.style.height = FrameH + "px"

        while (minW == maxW) {
            FrameH = FrameH + 100; //Increment
            frame.style.height = FrameH + "px";
            minW = frame.scrollWidth;
        }
    }

   </script>


<iframe id="RefFrame" onload="AdjustIFrame('RefFrame');" class="RefFrame"
    src="http://www.YourUrl.com"></iframe>

4
おそらく、ループの数に上限を追加する必要があります。そうしないと、「while」が無限ループに退化する可能性があります。
Kevin Seifert

1
これは私のページをクラッシュさせています。
DDDD '19年

良いシンプルなソリューション。しかし、私のcaesでは、サイズの増分は画面サイズによって制限されます。
ゼータ

1

私は、そのコンテンツとともにiframeにドロップするスクリプトを持っています。また、iFrameResizerが存在することを確認し(スクリプトとして挿入)、サイズ変更を行います。

以下の簡単な例を紹介します。

// /js/embed-iframe-content.js

(function(){
    // Note the id, we need to set this correctly on the script tag responsible for
    // requesting this file.
    var me = document.getElementById('my-iframe-content-loader-script-tag');

    function loadIFrame() {
        var ifrm = document.createElement('iframe');
        ifrm.id = 'my-iframe-identifier';
        ifrm.setAttribute('src', 'http://www.google.com');
        ifrm.style.width = '100%';
        ifrm.style.border = 0;
        // we initially hide the iframe to avoid seeing the iframe resizing
        ifrm.style.opacity = 0;
        ifrm.onload = function () {
            // this will resize our iframe
            iFrameResize({ log: true }, '#my-iframe-identifier');
            // make our iframe visible
            ifrm.style.opacity = 1;
        };

        me.insertAdjacentElement('afterend', ifrm);
    }

    if (!window.iFrameResize) {
        // We first need to ensure we inject the js required to resize our iframe.

        var resizerScriptTag = document.createElement('script');
        resizerScriptTag.type = 'text/javascript';

        // IMPORTANT: insert the script tag before attaching the onload and setting the src.
        me.insertAdjacentElement('afterend', ifrm);

        // IMPORTANT: attach the onload before setting the src.
        resizerScriptTag.onload = loadIFrame;

        // This a CDN resource to get the iFrameResizer code.
        // NOTE: You must have the below "coupled" script hosted by the content that
        // is loaded within the iframe:
        // https://unpkg.com/iframe-resizer@3.5.14/js/iframeResizer.contentWindow.min.js
        resizerScriptTag.src = 'https://unpkg.com/iframe-resizer@3.5.14/js/iframeResizer.min.js';
    } else {
        // Cool, the iFrameResizer exists so we can just load our iframe.
        loadIFrame();
    }    
}())

次に、次のようなスクリプトを使用して、iframeコンテンツを別のページ/サイト内のどこにでも挿入できます。

<script
  id="my-iframe-content-loader-script-tag"
  type="text/javascript"
  src="/js/embed-iframe-content.js"
></script>

iframeコンテンツは、scriptタグを配置する場所の下に挿入されます。

これが誰かに役立つことを願っています。👍


いいですね<script ... data-src="http://google.com">、iframe src を追加して埋めました。
バナナ酸

執筆時点での現在のバージョンはiframe-resizer@4.2.10
BananaAcid

1
...完全に使用可能なサンプルcodesandbox.io/s/remote-embed-ifrm-qdb74に拡張
BananaAcid

@BananaAcid-コードサンドボックスリンクが機能しなくなった
ctrlplusb

言及してくれてありがとう、リンクは次のようになりました:codesandbox.io/s/remote-embed-ifrm-yz0xl。(注:codesandboxは複数のページを使用して「偽物」になり、ハングする可能性があります。再
読み込み

1

これがこのページの私の簡単な解決策です。http://lab.ohshiftlabs.com/iframesize/

以下がその仕組みです。

ここに画像の説明を入力してください

基本的に、他のドメインでページを編集できる場合は、サーバーに属する別のiframeページを配置して、Cookieの高さを節約できます。間隔が更新されたときにCookieを読み取ると、iframeの高さが更新されます。以上です。

ダウンロード; http://lab.ohshiftlabs.com/iframesize/iframesizepost.zip

編集:2019年12月

上記のソリューションは基本的に、iframe内の別のiframeを使用します。3番目のiframeはトップページドメインに属しています。このページは、サイズ値をCookieに保存するクエリ文字列でこのページを呼び出します。外部ページは、このクエリを一定の間隔でチェックします。しかし、これは良い解決策ではないので、次の方法に従う必要があります。

トップページ:

window.addEventListener("message", (m)=>{iframeResizingFunction(m)});

ここm.originでは、どこから来たのかを確認できます。

フレームページ:

window.parent.postMessage({ width: 640, height:480 }, "*")

ただし、これはそれほど安全な方法ではないことを忘れないでください。安全に更新するには、必要な値で更新値(targetOrigin)を指定します。ドキュメントに従ってください:https : //developer.mozilla.org/en-US/docs/Web/API/Window/postMessage


1
これらのリンクは現在無効になっており(404)、コンテンツは回答に要約されていません。:(
StockB

1
リンクはまだ死んでいます。404
Arslan Ameer

0

PHPを使用してiframeのサイズを取得するWeb開発用の別のサーバー側ソリューションを見つけました。

まず、サーバースクリプトPHPを使用して、内部関数を介して外部呼び出しを行います:(file_get_contentswith with curl and dom)。

function curl_get_file_contents($url,$proxyActivation=false) {
    global $proxy;
    $c = curl_init();
    curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($c, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.8.1.7) Gecko/20070914 Firefox/2.0.0.7");
    curl_setopt($c, CURLOPT_REFERER, $url);
    curl_setopt($c, CURLOPT_URL, $url);
    curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
    if($proxyActivation) {
        curl_setopt($c, CURLOPT_PROXY, $proxy);
    }
    $contents = curl_exec($c);
    curl_close($c);
    $dom = new DOMDocument();
    $dom->preserveWhiteSpace = false;
    @$dom->loadHTML($contents);
    $form = $dom->getElementsByTagName("body")->item(0);
    if ($contents) //si on a du contenu
        return $dom->saveHTML();
    else
        return FALSE;
}
$url = "http://www.google.com"; //Exernal url test to iframe
<html>
    <head>
    <script type="text/javascript">

    </script>
    <style type="text/css">
    #iframe_reserve {
        width: 560px;
        height: 228px
    }
    </style>
    </head>

    <body>
        <div id="iframe_reserve"><?php echo curl_get_file_contents($url); ?></div>

        <iframe id="myiframe" src="http://www.google.com" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"  style="overflow:none; width:100%; display:none"></iframe>

        <script type="text/javascript">
            window.onload = function(){
            document.getElementById("iframe_reserve").style.display = "block";
            var divHeight = document.getElementById("iframe_reserve").clientHeight;
            document.getElementById("iframe_reserve").style.display = "none";
            document.getElementById("myiframe").style.display = "block";
            document.getElementById("myiframe").style.height = divHeight;
            alert(divHeight);
            };
        </script>
    </body>
</html>

div(iframe_reserve)の下に、関数呼び出しによって生成されたHTMLを、シンプルecho curl_get_file_contents("location url iframe","activation proxy")

これを行った後、javascriptを使用したbodyイベント関数onloadは、コンテンツdiv(iframe_reserve)の単純な制御だけでページiframeの高さを取得します

そのdivHeight = document.getElementById("iframe_reserve").clientHeight;ため、divコンテナー(iframe_reserve)をマスクした後に呼び出す外部ページの高さを取得するのが常でした。この後、iframeを適切な高さでロードします。


0

職場で(Reactを使用して)作業中にこの問題に遭遇しました。基本的に、外部のHTMLコンテンツがいくつかあり、データベースのドキュメントテーブルに保存し、特定の状況下でドキュメントデータセットにいるときにページに挿入します。

したがって、n最大でn外部htmlを含む可能性があるインラインがある場合、コンテンツが完全に読み込まれると、各インラインのiframeのサイズを自動的に変更するシステムを考案する必要がありました。私のホイールを少し回転させた後、これが私がそれをやった方法です:

  1. 設定しmessage、私たちのインデックスにイベントリスナーは、AA、特定のキーのチェックが、我々は、送信者はiframeから設定することをアプリに反応します。
  2. iframeを実際にレンダリングするコンポーネントで、外部htmlをそれに挿入した後<script>、iframeの起動を待機するタグを追加しますwindow.onload。これが発生したらpostMessage、iframe ID、計算された高さなどの情報を含むメッセージを親ウィンドウに送信するために使用します。
  3. 原点が一致し、キーがインデックスリスナーで満たされている場合idは、MessageEventオブジェクトで渡すiframe のDOM を取得します
  4. iframe取得したら、iframeから渡された値から高さを設定するだけpostMessageです。
// index
if (window.postMessage) {
    window.addEventListener("message", (messageEvent) => {
        if (
            messageEvent.data.origin &&
            messageEvent.data.origin === "company-name-iframe"
        ) {
            const iframe = document.getElementById(messageEvent.data.id)
            // this is the only way to ensure that the height of the iframe container matches its body height
            iframe.style.height = `${messageEvent.data.height}px`
            // by default, the iframe will not expand to fill the width of its parent
            iframe.style.width = "100%"
            // the iframe should take precedence over all pointer events of its immediate parent
            // (you can still click around the iframe to segue, for example, but all content of the iframe
            // will act like it has been directly inserted into the DOM)
            iframe.style.pointerEvents = "all"
            // by default, iframes have an ugly web-1.0 border
            iframe.style.border = "none"
        }
    })
}
// in component that renders n iframes
<iframe
    id={`${props.id}-iframe`}
    src={(() => {
        const html = [`data:text/html,${encodeURIComponent(props.thirdLineData)}`]
        if (window.parent.postMessage) {
            html.push(
                `
                <script>
                window.onload = function(event) {
                    window.parent.postMessage(
                        {
                            height: document.body.scrollHeight,
                            id: "${props.id}-iframe",
                            origin: "company-name-iframe",
                        },
                        "${window.location.origin}"
                    );
                };
                </script>
                `
            )
        }

        return html.join("\n")
    })()}
    onLoad={(event) => {
        // if the browser does not enforce a cross-origin policy,
        // then just access the height directly instead
        try {
            const { target } = event
            const contentDocument = (
                target.contentDocument ||
                // Earlier versions of IE or IE8+ where !DOCTYPE is not specified
                target.contentWindow.document
            )
            if (contentDocument) {
                target.style.height = `${contentDocument.body.scrollHeight}px`
            }
        } catch (error) {
            const expectedError = (
                `Blocked a frame with origin "${window.location.origin}" ` +
                `from accessing a cross-origin frame.`
            )
            if (error.message !== expectedError) {
                /* eslint-disable no-console */
                console.err(
                    `An error (${error.message}) ocurred while trying to check to see ` +
                    "if the inner iframe is accessible or not depending " +
                    "on the browser cross-origin policy"
                )
            }
        }
    }}
/>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.