iframeについて

目次
  1. HTML埋め込みコンテンツ
  2. iframe
  3. セキュリティについて

HTML埋め込みコンテンツ

iframe現在のHTMLへ別のHTMLを埋め込む
embed外部のマルチメディアを埋め込む(プラグインが必要)
object外部リソース全般を埋め込む
*src属性ではなくdata属性に埋め込みたいページのURLを記述
*param要素はobject要素の子要素
video動画を埋め込む
audio音声を埋め込む
sourcepicture・video・audio要素に対して複数のメディアリソースを指定します
canvasグラフィックの描画
img画像を埋め込む
mapイメージマップ(一部にハイパーリンクが設定された画像)の定義
areaイメージマップ領域を指定

*かつてJavaアプレットやFlashのようなプラグイン技術が普及した時代に「objectやembed」が使用されていましたが、今は外側にコンテン・動画などのシェアに「iframe」が使用されています

iframe

srcで埋め込むWebページのURLを指定

<iframe
  src="埋め込むHTMLのURL"
></iframe>

iframeで表示できるのは、自分と同じ転送プロトコルを使用するサイトのコンテンツのみです
*HTTPSを使用しているサイトの場合、同じHTTPSを使用しているサイトのコンテンツのみを埋め込むことができます

TwitterやYouTubeなどの人気のあるウェブサイトでは、手動のiFrame埋め込みが無効になっていて埋め込みコードを取得する必要があります
*例えばYouTubeビデオプレーヤーの下に「共有」ボタンから取得します

*サイトごとに埋め込みコードを取得する方法が異なるり、埋め込みコードに対応していないサイトも多いので「Iframely」という埋め込みコードを生成してくれるWebサービスを利用したりもできます

備考:自サイトをIframely用に最適化する場合
https://iframely.com/docs/webmasters

srcdocで直接HTMLタグを書く
*Internet Explorerはsrcdoc属性非対応

<iframe
  srcdoc="HTMLコード"
></iframe>

属性について

  • title属性:埋め込みコンテンツの説明
  • widthとheight属性:フレームの幅と高さでデフォルトは「幅300px高さ150px」
  • scrolling属性
    • “auto”:デフォルト、ホバーでスクロールバー表示
    • “yes”:常にスクロールバーを表示
    • “no”:スクロールを禁止
  • loading属性
    • “eager”:デフォルト、iframe を直ちにロードします
    • “lazy”:ブiframe の読み込みを延期します
  • referrerpolicy属性でリファラー送信ポリシーを指定
    • no-referrer-when-downgrade:デフォルト、httpsからhttpへは送信しない
    • no-referrer:送信しない。
    • same-origin:同一オリジン間のみ送信する
    • origin:オリジン情報のみを送信する
    • strict-origin:オリジン情報のみを送信するが、httpsからhttpへは送信しない
    • origin-when-cross-origin:オリジンをまたがる場合は、オリジン情報のみを送信する
    • strict-origin-when-cross-origin:オリジンをまたがる場合は、オリジン情報のみを送信するが、httpsからhttpへは送信しない
    • unsafe-url:常に送信する
  • name属性:フレーム名を付けることができ、リンクにtarget属性を指定する場合やform送信でtarget属性を指定する場合などに使用されます

レスポンシブ表示

/* 親要素の幅以下に */
iframe {
  max-width: 100%; /* width属性を指定していた場合 */
}

/* 縦横比も維持する場合 */
.iframe-wrapper{ /*親要素 */
  position: relative;
  padding-top: 60%;
  height:0;
}
iframe{
 position: absolute;
 top: 0;
 left: 0;
 width: 100%;
 height: 100%;
}

セキュリティについて

フロント側の実装では
外部のWebページを埋め込むことはセキュリティ面でのリスクがあります
大前提として自分のサイトもしくは信頼できるサイトを埋め込むようにします
*具体的なリスク
iframe内に埋め込まれたウェブページが、現在のウェブページのコンテキスト内で実行されるため、クロスサイトスクリプティング(XSS)攻撃やクリックジャッキング攻撃、CookieやLocalStorageなどのストレージにアクセスされるリスクがあります

サーバー側の実装では
外部サイトへの埋め込みを許可すると、セキュリティ上のリスクが生じるので
レスポンスヘッダーにx-frame-options: DENYを設定することで埋め込みを禁止できます

oEmbedについて

oEmbedとは、Webサイトやアプリケーションの中で外部のコンテンツを埋め込むためのAPIですoEmbed APIを提供するWebサイトに、特定のURLを送信することでそのURLに関連する情報を取得することができます
*埋め込みに必要なHTMLを問い合せるためのプロトコル
TwitterやYouTubeやInstagramやWordPressなどの有名なWebサービスはoEmbed APIを提供しています
*備考:WordPressのブロックエディターではURLをコピーしブロック内にペーストするだけで、埋め込みブロック対象サイトを自動探知するように実装されています


サンドボックス」は保護された領域です
*埋め込まれたコンテンツ内で問題があっても、元のページには影響を及ぼさないようにします

iframeに「sandbox属性」を指定することで、iframe内のウェブページが現在のウェブページのストレージにアクセスできなくなります
「sandbox属性」を指定することで、iframe内のウェブページが使用できる機能が制限されます

iframeはsandbox属性でサンドボックス化できます
サンドボックス化されていないコンテンツはJavaScriptの実行・フォームの送信・ポップアップウィンドウなどができてしまいます

「すべてを制限」したり「必要な権限」だけを与えたりできます

<!-- すべてを制限 -->
<iframe src="..." sandbox></iframe>

<!--必要な権限を1つずつ追加することができます-->
<iframe src="..." sandbox="1つずつ追加"></iframe>
  • allow-forms :フォーム送信を許可
  • allow-popups :ポップアップの表示を許可
  • allow-scripts :JavaScript(ポップアップを除く)の実行を許可
  • allow-top-navigation :フレーム内の文書から別のウィンドウに移動を許可
  • allow-same-origin :sandbox 属性を持っている場合は強制的に “異なるオリジン” の状態に置かれますがallow-same-originを指定することで同一オリジンとして扱う
  • fullscreen:デフォルトでは埋め込みコンテンツからの操作で全画面表示モードにすることはできませんがこの制限を解除できます

重要 sandbox属性に allow-scripts と allow-same-origin の両方を追加しない


サブドメインのサイトをiframeで読み込む(ちなみにサブドメインのサイトもクロスオリジンです)
*JavaScriptでアニメーションしているのでsandbox="allow-scripts"を設定
*srcはJavaScriptで設定します

<style>
.iframe-wrap{
  position: relative;
  padding-top: 60%;
  height:0;
}
iframe{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border:1px solid #ccc;
}
</style>

<button id="btn">表示する</button>
<div class="iframe-wrap">
 <iframe id="iframe" sandbox="allow-scripts"></iframe>
</div>

<script>
const btn = document.getElementById('btn')
btn.addEventListener('click', ()=>{
document.getElementById("iframe").src = "https://birthday.koro-koro.com/2023/";
}) 
</script>

クロスオリジンの制約について
クロスオリジンとは異なるオリジン間でのデータ共有や通信を制限するセキュリティ上の仕組みのことです

iframe内で表示される外部のドキュメントは、同じオリジンのものであれば親ウェブページとの間データのやり取りができますが異なるオリジンの場合は操作が制限されます(JavaScriptで取得できません)

*ただし、CORS(Cross-Origin Resource Sharing)やpostMessage APIなどの技術を使用することで異なるオリジン間でのデータ共有や通信を実現できます

クロスドキュメントメッセージング
*クロスドキュメントメッセージングはJavaScriptのpostMessage APIを使用して実現されます

iframe要素やJavaScriptのwindow.openメソッドなど異なるオリジン間でメッセージをやりとりする仕組みで、専用のメソッドとイベントが定義されています

送信は、相手先のwindowオブジェクトのpostMessage(message, targetOrigin)メソッド呼び出しますmessageには送信するデータを指定します
targetOriginには相手先のオリジンを文字列で指定

iframe.contentWindow.postMessage('メッセージ','https://hoge.com');

messageイベントのハンドラのevent引数はMessageEventオブジェクトでEventオブジェクトを持っています
data:送られて来たデータ
origin:送信元のオリジン
source :送信元のwindowオブジェクト
ports :送信元から送られてきたMessagePortオブジェクトの配列
受信側では、これらの属性を参照してメッセージを受け取ります
*セキュリティ上、送信元のオリジンを確認することが推奨

window.onmessage = function(event){
   // 送信元のオリジンを確認
   if(event.origin == 'https://hoge.com'){
        // 送信されたデータの取出し
        console.log(event.data);
        // 送信されたデータをそのまま返信する
        event.source.postMessage(event.data, event.origin);
   }
}