先日、引用先ページが同一ドメインの場合の<iframe>の高さ(height)を、引用先ページの高さに揃える方法について紹介しました。
ただしこの方法は、引用先ページが別ドメインの場合は「クロスオリジン制約」によってブロックされ、利用することができません。ただ、postMessageを使った通信を行うことでクロスオリジン制約を回避できる場合があります。(引用先ページにスクリプトを記述する必要があります。)
本記事では、引用先ページが別ドメインの場合に高さを揃える方法を紹介します。
目次
実装例とコード
以下は<iframe>で引用しているページです。(引用先ページは本ページとは異なるドメイン nov-tarvel.jp で、筆者の趣味ブログです。)
高さは引用先ページの高さに揃うよう、JavaScriptで実装しています。
HTML / JavaScritpt コード
- 引用先ページに記述するスクリプト
-
function sendHeight() { const height = document.documentElement.scrollHeight; const targetOrigin = '親ページのオリジン'; window.parent.postMessage(height, targetOrigin); } window.addEventListener('load', sendHeight); - 親ページ(<iframe>タグを埋め込むページ)に記述する HTML & スクリプト
-
<iframe id="myIframe" src="引用先ページのURL" style="width: 100%;"></iframe>window.addEventListener('message', function(event) { const allowedOrigin = '引用先ページのオリジン'; if (event.origin === allowedOrigin && typeof event.data === 'number') { const iframe = document.getElementById('myIframe'); iframe.style.height = event.data + 'px'; } });
実装のポイント
まず引用先ページに以下のJavaScriptを記述します。
function sendHeight() {
const height = document.documentElement.scrollHeight;
const targetOrigin = '親ページのオリジン';
window.parent.postMessage(height, targetOrigin);
}
window.addEventListener('load', sendHeight);sendHeight関数を定義し、document.documentElement.scrollHeightでページ高さを取得して、postMessageで親ページに送信します。targetOriginには親ページのオリジンを設定します。これにより、特定のURLにのみ高さの情報を送信できます。- URLではなくオリジンを設定する点に注意してください。オリジンとはパスを含まないURLのことです。
(本ページ https://noveblo.com/js-iframe-postmessage/ であれば https://noveblo.com です。)
- URLではなくオリジンを設定する点に注意してください。オリジンとはパスを含まないURLのことです。
window.addEventListener('load', sendHeight);でページが読み込まれたときにsendHeight関数が呼び出され、ページ高さが親ページに送信されます。
次に親ページを作成します。
まず<iframe>タグを配置し、id属性を付与してJavaScriptで操作できるようにします。
<iframe id="myIframe" src="引用先ページのURL" style="width: 100%;"></iframe>JavaScriptは以下の通り記述します。
window.addEventListener('message', function(event) {
const allowedOrigin = '引用先ページのオリジン';
if (event.origin === allowedOrigin && typeof event.data === 'number') {
const iframe = document.getElementById('myIframe');
iframe.style.height = event.data + 'px';
}
});window.addEventListener('message', function(event) {...})でmessageイベントリスナーを追加し、postMessageで送られたメッセージを受信したときに関数を実行します。const allowedOrigin = '引用先ページのオリジン';で、許可されたオリジン(引用先ページのオリジン)を変数に格納します。- URLではなくオリジンを設定する点に注意してください。オリジンとはパスを含まないURLのことです。
(本ページ https://noveblo.com/js-iframe-postmessage/ であれば https://noveblo.com です。)
- URLではなくオリジンを設定する点に注意してください。オリジンとはパスを含まないURLのことです。
if (event.origin === allowedOrigin && typeof event.data === 'number') {...}で、メッセージの送信元が許可されたオリジンと同一であり、メッセージのデータが数値であることを確認します。event.origin: メッセージの送信元のオリジンevent.data: メッセージのデータ
const iframe = document.getElementById('myIframe');で<iframe>要素を取得し、iframe.style.height = event.data + 'px';で受信した高さデータを<iframe>の高さに適用します
実装できない場合の考察
引用先ページにスクリプトを記述できる場合でも、以下のようなケースではpostMessageを使用してクロスオリジン制約を回避できない場合があります。
- 引用先ページや親ページがCSP(Content Security Policy)を設定している場合、
postMessageを使用するスクリプトの実行が制限されることがあります。(特に、外部スクリプトの読み込みや実行が制限されている場合) - 古いブラウザや特定のブラウザバージョンにおいては、
postMessageの挙動が期待通りに動作しない場合があります。 - 親ページがメッセージを受信するために設定した条件(例えば、特定のオリジンからのメッセージのみを受け付けるなど)が引用先ページの設定と一致しない場合、メッセージが正しく受信されません。
エラーの一例ですが、ご参考まで。
