埋め込みコンテンツの最適化:postMessage APIを活用したレスポンシブ対応
Published on May 28, 2025
Category: メモ
実現したいこと
- 埋め込みコンテンツを他サイトに埋め込む際、コンテンツの比率(16:9、4:3、9:16など)に応じて自動でサイズ調整したい
- 埋め込み先での実装負荷を最小化し、一行のスクリプトタグだけで完結させたい
課題
従来のiframe埋め込みでは、以下の問題がありました。
固定サイズの問題
- 単純なiframeでは動画の実際の表示に関係なく固定サイズになる
- 様々なアスペクト比の動画に対応できない
- 横型動画(16:9): 一般的なYouTube形式
- 正方形動画(1:1): Instagram投稿用
- 縦型動画(9:16): TikTok、YouTube Shortsなど
実装の複雑さ
- 埋め込み先で毎回CSSやJavaScriptを書く必要がある
- 動画プレイヤーの仕様変更に追従できない
従来の埋め込み方法の限界
何も制御しない場合
<iframe
src="<https://video-player.example.com/embed/abc123>"
width="640"
height="360">
</iframe>
この方法では16:9の動画なら問題ないですが、縦型動画では表示が崩れてしまいます。
デモサイト:
解決策:postMessage APIによる動的サイズ調整
アーキテクチャ

埋め込み先の実装
<!DOCTYPE html>
<html>
<head>
<title>動画埋め込みデモ</title>
<style>
.video-container {
max-width: 100%;
margin: 20px 0;
}
.video-iframe {
border: none;
transition: all 0.3s ease;
}
</style>
</head>
<body>
<h1>レスポンシブ動画プレイヤー</h1>
<!-- 横型動画 -->
<div class="video-container">
<iframe
id="video1"
class="video-iframe"
src="<https://video-player.example.com/embed/horizontal-video-123>"
scrolling="no">
</iframe>
</div>
<!-- 縦型動画 -->
<div class="video-container">
<iframe
id="video2"
class="video-iframe"
src="<https://video-player.example.com/embed/vertical-video-456>"
scrolling="no">
</iframe>
</div>
<script>
window.addEventListener("message", function(event) {
// セキュリティチェック:信頼できるoriginからのメッセージのみ処理
if (event.origin !== "<https://video-player.example.com>") {
return;
}
if (event.data && event.data.type === "VIDEO_RESIZE") {
const iframes = document.querySelectorAll(".video-iframe");
iframes.forEach(function(iframe) {
if (event.source === iframe.contentWindow) {
// サイズを動的に調整
iframe.style.width = event.data.width + "px";
iframe.style.height = event.data.height + "px";
// デバッグ用ログ
console.log(`動画 ${iframe.id} のサイズを更新:`, {
width: event.data.width,
height: event.data.height,
aspectRatio: event.data.aspectRatio
});
// 調整完了を動画プレイヤーに通知
iframe.contentWindow.postMessage({
type: "RESIZE_COMPLETE"
}, event.origin);
}
});
}
// その他のイベント処理
if (event.data && event.data.type === "VIDEO_FULLSCREEN") {
console.log("フルスクリーンモード:", event.data.isFullscreen);
}
});
</script>
</body>
</html>
動画プレイヤー側の実装
// 動画プレイヤー内(iframe内)のコード例
class ResponsiveVideoPlayer {
constructor() {
this.parentOrigin = document.referrer ? new URL(document.referrer).origin : "*";
this.init();
}
init() {
// 動画メタデータの読み込み完了を待つ
this.video = document.querySelector('video');
this.video.addEventListener('loadedmetadata', () => {
this.calculateOptimalSize();
});
// リサイズイベントの監視
window.addEventListener('resize', () => {
this.calculateOptimalSize();
});
}
calculateOptimalSize() {
const videoWidth = this.video.videoWidth;
const videoHeight = this.video.videoHeight;
const aspectRatio = videoWidth / videoHeight;
// 埋め込み先の表示領域に応じて最適なサイズを計算
const maxWidth = Math.min(800, window.parent.innerWidth * 0.9);
let optimalWidth, optimalHeight;
if (aspectRatio > 1) {
// 横型動画
optimalWidth = maxWidth;
optimalHeight = maxWidth / aspectRatio;
} else {
// 縦型・正方形動画
optimalHeight = Math.min(600, maxWidth * aspectRatio);
optimalWidth = optimalHeight * aspectRatio;
}
// 親ウィンドウにサイズ調整を要求
this.requestResize(optimalWidth, optimalHeight, aspectRatio);
}
requestResize(width, height, aspectRatio) {
const message = {
type: "VIDEO_RESIZE",
width: Math.round(width),
height: Math.round(height),
aspectRatio: aspectRatio.toFixed(2)
};
window.parent.postMessage(message, this.parentOrigin);
}
notifyFullscreen(isFullscreen) {
window.parent.postMessage({
type: "VIDEO_FULLSCREEN",
isFullscreen: isFullscreen
}, this.parentOrigin);
}
}
// プレイヤー初期化
new ResponsiveVideoPlayer();
実装結果と効果
Before(従来の固定iframe)
- 16:9の固定値場合、縦型動画が横に引き伸ばされて表示される
- レスポンシブ対応が困難
- 各埋め込み先で個別のCSS調整が必要
After(postMessage API活用)
- 動画の解像度に自動で適応
- モバイル・デスクトップ両対応
- 埋め込み先での実装負荷最小化
更なる改善:埋め込みスクリプトの管理について
現状でも十分実用的ですが、さらに使いやすくするために以下の改善を検討中です。
下記のように埋め込みのスクリプトをリソースとして管理することで、仕様変更が発生した場合でもリソースで管理しているため、埋め込み先全てに反映することができます。
何らかの埋め込みコンテンツをサービスとして提供している場合、埋め込み実装だけでなく、今後仕様変更や拡張に備えた設計を考える必要があります。
理想的な埋め込み方法
<!-- これだけで完結 -->
<script
src="https://video-player.example.com/embed.js"
data-video-id="abc123"
data-autoplay="false">
</script>
中央管理型埋め込みアーキテクチャ
このアプローチにより、以下のメリットが実現できます
1. 一元的な仕様管理
- バージョン管理: セマンティックバージョニングによる段階的アップデート
- A/Bテスト: 新機能のカナリアリリースが可能
- 互換性保証: 旧バージョンとの後方互換性を維持
2. 運用面でのメリット
- 緊急修正: 重大なバグが発見された場合、即座に全埋め込み先に適用
- 機能追加: 新しいプレイヤー機能を既存の埋め込み先に自動展開
- パフォーマンス最適化: CDN活用やコード圧縮を一箇所で管理
スクリプトの内部実装
// embed.js の概要
(function() {
const script = document.currentScript;
const videoId = script.getAttribute('data-video-id');
const autoplay = script.getAttribute('data-autoplay') === 'true';
// iframe を動的生成
const iframe = document.createElement('iframe');
iframe.src = `https://video-player.example.com/embed/${videoId}?autoplay=${autoplay}`;
iframe.style.border = 'none';
iframe.scrolling = 'no';
// postMessage リスナーを自動設定
window.addEventListener('message', handleVideoMessage);
// スクリプトタグの直後に iframe を挿入
script.parentNode.insertBefore(iframe, script.nextSibling);
})();
まとめ
postMessage APIを活用することで
- レスポンシブ対応: 動画の解像度に自動適応
- 実装簡素化: 埋め込み先での作業を大幅削減
- 保守性向上: プレイヤー側の仕様変更に自動追従
- セキュリティ: origin検証による安全な通信
この手法は動画プレイヤー以外にも、チャートやスライドなど様々な埋め込みコンテンツに応用可能です。
技術的な注意点
- セキュリティ: 必ず
event.origin
をチェックする - パフォーマンス: メッセージの頻度を適切に制限する
- フォールバック: postMessage未対応環境での代替処理
- CORS対応: 異なるドメイン間での通信設定