Facebookページの投稿をサイトに表示する「Page Plugin」を完全レスポンシブ対応する方法

Facebookページの投稿をサイトに表示する「Page Plugin」を完全レスポンシブ対応する方法

2015.12.29

Like Boxから切り替わり、全然「レスポンシブ」にできなくなったPage Plugin

以前、「FacebookのPage Pluginのレスポンシブはdata-widthに500pxを指定すればいい」と言っていたのですが、どうやらそれだけじゃ足りないみたいです。

実はPage PluginがiPhone(特にアプリ内ブラウザ)でページを読み込んだ時に右横に一瞬空白が現れる現象を引き起こしていることに気づきました。

※ここでの「iPhoneでページを読み込んだ時〜」は私の実体験(iPhoneしかモバイル端末を持っていない為)であり「iPhone固有の現象」を指すものではありません。

今回はそんな「Page Pluginが引き起こすページ読み込み時の問題」に対応するためにやったことのお話です。

FacebookのPage Pluginが引き起こすページのグラつき

以前から気になっていはいたものの、「一瞬だしいいか…」と後回しにしていたページ読み込み時に右に発生するちょっとした空白の対策をしてみました。

ページ読み込み時に空白が出現するという現象

「ページ読み込み時に右に発生するちょっとした空白」とは一体どういうことかというと、次の画像のような現象が起きていました。

ページ読み込み時に右側に一瞬だけ空白が出現する

上の画像はページ内のある要素の横幅を500pxに指定した時にページがどのように表示されるかテストしたものです。

ページ読み込み時に画像のような右側に空白が一瞬出てくるブログを見たことありませんか?

原因はいろいろあるのかもしれませんが、当ブログではどうやらFacebookのPage Pluginが悪さをしていたようでした。

Page Pluginは自動で幅を縮めてくれる

Like Boxが廃止され、代わりに登場したPage Pluginは親要素の横幅に合わせて幅を縮めてくれる機能を持っているのですが…

どうもその「親要素の幅に合わせてPage Pluginの幅を調整する」というタイミングがワンテンポ遅いようです…

幅の調整タイミングがワンテンポ遅れるおかげで、一瞬Page Pluginが横幅500pxで表示されてしまい、右側に空白部分を作り出しているようでした。

「一瞬」なので気にしなくてもいいことかもしれませんが、どうも気になってしまったので、次に紹介するjQueryコードで対策をしてみました。

FacebookのPage Pluginをレスポンシブ対応するjQueryコード

今回紹介するコードでPage Pluginのレスポンシブ対応できるのはFacebookの「Page Plugin – Social Plugins」で作成したコードをテーマ内に直接書き込んでいる方になります。

(WordPressのプラグインで出力している方は対応に工夫が必要になります。)

また、合わせてjQueryを読み込んでいる必要があります。

おそらく今では大体のサイトでjQueryを使っていると思うのでそれほど意識しなくてもなんとかなると思います。(急に適当になってスミマセン)

Page Plugin埋め込みの為に必要なコード

まずは、「Page Plugin – Social Plugins」で埋め込み用HTMLとjavascriptを作った時の初期コードです。

今回jQueryでカスタマイズを加えるのはjavascript側になります。

//最初のjavascriptソース
<script>(function(d, s, id) {
  var js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) return;
  js = d.createElement(s); js.id = id;
  js.src = "//connect.facebook.net/ja_JP/sdk.js#xfbml=1&version=v2.5&appId=123456789012345";
  fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>

上記のコードは</body>タグの直前に書き込んで下さい。(WordPressであればfooter.phpに書くことになると思います)

また、appIdの部分は適当な数字に書き換えてるので、上のコードをコピペしただけでは正常に動作しませんのでご注意下さい。(必ずご自身でコードを発行して下さい。)

ページ読み込み時に右側に空白を出さないようにカスタマイズしたコード

ページ読み込み時に無駄な空白が発生しないようにカスタマイズするコードは次のコードになります。


//読み込み時のレスポンシブ
<script>(function(d, s, id) {
  //▼▼▼ 読み込み時のスペース対策の為に追加したコード ▼▼▼
  var fbpw,fbp = $('.fb-page');
  for(i=0;i<fbp.length;i++) {
    fbpw = $(fbp[i]).parent().width();
    if(fbpw>500){fbpw=500}
    if(fbpw<180){fbpw=180}
    $(fbp[i]).attr('data-width',fbpw);
  }//end for
  //▲▲▲ 読み込み時のスペース対策の為に追加したコード ▲▲▲
  var js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) return;
  js = d.createElement(s); js.id = id;
  js.src = "//connect.facebook.net/ja_JP/sdk.js#xfbml=1&version=v2.5&appId=123456789012345";
  fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>

動作としては、Page Pluginのコードが書かれている要素の親要素の幅を取得して、data-widthを親要素の幅と同じ値にに書き換えるということをしています。

「▼」と「▲」で挟まれた間のコードが今回カスタマイズの為に追加したコードになります。

元のjavascriptコードのvar js, fjs = d.getElementsByTagName(s)[0];の行の手前にでも追加して頂ければと思います。

Page Pluginの描画直前にはdata-widthが親要素の幅になっている

Page Pluginの描画直前のHTMLは上のスクリーンショットのようになります。

もともとdata-widthには500pxを指定していましたが、親要素の幅に合わせてdata-widthが変更されるようになりました!

一応上記コードで僕は「Page Pluginのレスポンシブ対応完了!」と言ってます…

本来ならばページ幅の変化に合わせて表示を変えるところなんですけど…

ページ幅の変更に対応……そこまでしなくてもいいんじゃない?

ということで、ページ幅の変化に合わせてPage Pluginの幅を変えることはやっていません。

ページ幅を頻繁に変えながらWEB閲覧するシーンってそれほど多くないですよね…?

もしページ幅をゴリゴリ変えながら見てるとしてもPage Pluginくらい……気になるならページリロードすればいいんだし…

ページ幅の変化に合わせてPage Pluginの幅も変える為のコード

ここから先は未実装のコードですがページ幅の変更に合わせてPage Pluginの表示幅も変更するコードも紹介します。


<!-- Facebook PagePluginのHTMLをid付きの要素で囲む -->
<div id="fbpageouter">
  <!-- Facebook PagePluginのHTML -->
</div>

まずはPage Pluginの埋め込みHTMLをid指定したdiv要素等で囲みます。

複数箇所ある場合はそれぞれ囲う必要があるかと思います。

<script>(function(d, s, id) {
  //▼▼▼ リサイズ対応の為に追加したコード PagePluginのHTMLを「id="fbpageouter"」の要素で囲う必要あり ▼▼▼
  var timer = false;
  var fbhtml1=d.getElementById("fbpageouter").innerHTML;
  //複数箇所ある場合は変数を複数に分けるなどしてなんとかします
  $(window).resize(function() {
      if (timer !== false) {
          clearTimeout(timer);
      }
      timer = setTimeout(function() {
          d.getElementById("fbpageouter").innerHTML = fbhtml1;
          //複数箇所ある場合はそれぞれの要素にHTMLを戻します
          fbpagedatawidthrewite();
          window.FB.XFBML.parse();
      }, 200);
  });
  //▲▲▲ リサイズ対応の為に追加したコード PagePluginのHTMLを「id="fbpageouter"」の要素で囲う必要あり ▲▲▲
  //▼▼▼ 読み込み時のスペース対策の為に追加したコード(関数化した) ▼▼▼
  function fbpagedatawidthrewite() {
    var fbpw,fbp = $('.fb-page');
      for(i=0;i<fbp.length;i++) {
        fbpw = $(fbp[i]).parent().width();
        if(fbpw>500){fbpw=500}
        if(fbpw<180){fbpw=180}
        $(fbp[i]).attr('data-width',fbpw);
      }//end for
  }
  fbpagedatawidthrewite();
  //▲▲▲ 読み込み時のスペース対策の為に追加したコード(関数化した) ▲▲▲
  var js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) return;
  js = d.createElement(s); js.id = id;
  js.src = "//connect.facebook.net/ja_JP/sdk.js#xfbml=1&version=v2.5&appId=123456789012345";
  fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>

個人的にあまりおすすめしたくないので説明は簡単なものにさせていただきますが…

動作としてはページのリサイズ時にPage PluginのHTMLを再度書きなおして、window.FB.XFBML.parse()でPage Pluginを再描画しています。

単にresizeのイベントで動作させると、リサイズ中にもイベントが連発してブラウザが固まる恐れがあったので、リサイズ完了時に1回だけ処理されるようにしました。

一応軽くテストして期待通りの動作はしてくれているのでOKかなと思います。

ではまた。