基本設定
iframe
要素には、コンテンツのURLを指定するsrc
属性と、コンテンツの概要を示すtitle
属性が必要です。title
属性は、アクセシビリティの観点から必須とされます。
<iframe
src="https://example.com"
width="800"
height="600"
title="外部コンテンツの概要"
loading="lazy"
sandbox="allow-scripts"
allow="geolocation 'none'">
</iframe>
レスポンシブ対応
iframe
のサイズをビューポートに応じて変更するには、CSSを使用します。アスペクト比を維持する場合、以下の手法が用いられます。
.iframe-container {
position: relative;
width: 100%;
height: 0;
padding-bottom: 56.25%; /* アスペクト比 16:9 */
}
.iframe-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
同一オリジンポリシー
同一オリジンポリシーは、ブラウザのセキュリティモデルの基本原則です。オリジン(プロトコル、ホスト、ポートの組み合わせ)が異なるリソース間のアクセスは、原則として制限されます。
同一オリジン間のアクセス
親ページとiframe
が同一オリジンの場合、親ページのスクリプトはiframe
内のDOMにアクセスできます。
const iframe = document.getElementById('myIframe');
const iframeDoc = iframe.contentDocument;
const heading = iframeDoc?.querySelector('h1');
if (heading) {
heading.textContent = '親ページからの変更';
}
異なるオリジン間の通信
オリジンが異なる場合、DOMへの直接アクセスはできません。通信にはpostMessage
APIを使用します。
// 親から子への送信
const iframe = document.getElementById('myIframe');
iframe.contentWindow?.postMessage('データ', 'https://trusted-domain.com');
// 子での受信
window.addEventListener('message', (event) => {
if (event.origin !== 'https://trusted-domain.com') {
return;
}
console.log(event.data);
});
sandbox属性
sandbox
属性は、iframe
内のコンテンツが使用できる機能を制限します。属性値を空にすると、スクリプト実行、フォーム送信、ポップアップ表示などの機能がブロックされます。
オプション | 説明 |
---|---|
allow-scripts |
JavaScriptの実行を許可する |
allow-forms |
フォームの送信を許可する |
allow-popups |
ポップアップの作成を許可する |
allow-same-origin |
コンテンツを同一オリジンとして扱う |
allow-scripts
とallow-same-origin
を同時に指定すると、埋め込みコンテンツはsandbox
の制約を回避できるため、この組み合わせは使用しないでください。
セキュリティヘッダー
HTTPヘッダーによってもiframe
の挙動は制御されます。
- X-Frame-Options:
DENY
またはSAMEORIGIN
を指定し、ページがiframe
内に表示されることを制御します。 - Content-Security-Policy (CSP):
frame-src
ディレクティブでiframe
として読み込めるソースを、frame-ancestors
ディレクティブでページを埋め込める親ページを指定します。
遅延読み込み
loading="lazy"
属性を指定すると、iframe
がビューポートに近づくまで読み込みが遅延されます。
<iframe src="..." loading="lazy"></iframe>
Intersection Observer
APIを使えば、遅延読み込みを細かく制御できます。
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const iframe = entry.target;
iframe.src = iframe.dataset.src;
observer.unobserve(iframe);
}
});
});
document.querySelectorAll('iframe[data-src]').forEach(iframe => {
observer.observe(iframe);
});
推奨設定
以下は、セキュリティを考慮したiframe
の推奨設定例です。
<iframe
src="適当なsrc"
title="適当なタイトル"
sandbox="allow-scripts allow-forms"
allow="geolocation 'none'; microphone 'none'; camera 'none'"
loading="lazy"
referrerpolicy="strict-origin-when-cross-origin">
</iframe>