WordPressのembed関係のコードを見ていて、ちょっと以外なことを知った。WordPress記事の埋め込みページ(/embed)は埋め込まれた先のWordPressブログと通信していて、読み込み時やリサイズ時などに埋め込みページの高さ(height)を伝えることによって、レスポンシブな埋め込みを実現している。だからWordPressブログに埋め込まれている限り、ブラウザのウィンドウをリサイズしても埋め込みページiframeの高さが勝手に伸び縮みしてくれるわけだ。

© Grant Hutchinson – “Embedded” – Creative Commons: Attribution, Noncommercial, No Derivative Works

うーん、埋め込まれた先のページを操作できるというのは、なんだか面白そうだ。

ちょっとお遊びとして、このようなページを用意した。ボタンをクリックすると、高さがアニメーションする文章が表示される。

button:before {
    content: 'close';
}
button.more:before {
    content: 'more'
}
p {
    margin-bottom: 0;
    padding-bottom: 0;
    max-height: 100vh;
    overflow: hidden;
    transition: max-height 2s;
}
p.hide {
    max-height: 0;
}
var btn = document.querySelector("button");
var p = document.querySelector("p");
var status = false;
var cb = () => {
  if (status) {
    return;
  } else {
    status = true;
  }

  var timer = setInterval(() => window.dispatchEvent(new Event('resize')), 20);
  p.classList.toggle("hide");
  btn.classList.toggle("more");
  setTimeout(() => {
    clearInterval(timer);
    status = false;
  }, 2000);
}

btn.addEventListener("click", cb, false);

ボタンをクリックすると2秒間のアニメーションの間、20ミリ秒ごとにリサイズイベントを発生させている。あと、当然だが、WordPressブログと通信するためのスクリプトも読み込んでいる。それから、今気がついたが、うっかりarrow functionを使ったのでIEだとエラーがでるだろうけど知ったこっちゃない。

さて、このブログは(少なくとも今は)WordPressで動いているので、moreと書かれたボタンを押すと、ビローンと文章が現れiframeの高さが(ぎこちなく)変更していくはず。楽しい。面倒なことはWordPressの埋め込み用JavaScriptがやってくれるので、埋め込みページでは良きタイミングでリサイズイベントを呼ぶだけというのも手軽。

子ウィンドウから高さを変更できるのが確認できたところで、ちょっとしたイタズラもできないかと調べてみたが、流石に無理だった。例えば、埋め込まれたページにある他の埋め込みページの高さを変更することはできない。それぞれの埋め込みiframeはランダムな秘密の文字列が与えられ、その文字列と一致するiframeだけ変更されるからだ。

また、極端な値を高さとして設定することはできない。埋め込みページの高さは200以上1000以下に限定され、この範囲外の値は最大値(最小値)に設定される。上のデモ埋め込みページの下部分に謎のスペースがあるのもこのせいだ。

さらに、アニメーションもぎこちない。細かくリサイズイベントを発生させても、実際にiframeの高さが変更されるのは最後の100ミリ秒のようだ。すなわち上のように20ミリ秒ごとにリサイズイベントを発生させるスクリプトはまったく意味がなかった😢 ただこれは、送信(埋め込みページ)側の制限なので、自分でWordPressブログとの通信を実装した場合は自由だけど。

最後に注意点として、WordPressブログが埋め込みページと通信するのは、iframeがwp-embedded-contentというクラスを持つ場合だけだ。WordPress記事の埋め込み用HTMLコードやoembed機能では標準でiframeにこのクラスが付与されている。逆に、iframeがこのクラスさえ持っていればいいので、他のCMSや埋め込み機能のあるサービスでも、埋め込みコードにwp-embeded-contentクラスを付与して通信用jsを作っておくだけで(WordPressに貼り付けられた時だけ)レスポンシブな埋め込みが提供できる。レスポンシブな埋め込みは便利なので、別のスタンダードができればいいのだけれどね。