Instagram のフィードを簡単にWebサイトに埋め込みむことができる無料サービス InstaWidget が、最近何度かダウンすることがあり、それを埋め込んでいるページ全体の読み込みに影響がありました。

SnapWidget や WordPress のプラグインである Instagram Feed は、利用するためには Instagram のアカウントで認証する必要があるため、クライアント案件ではハードルがあり、別のサービスを探していたところ、複眼feed という無料サービスがありました。

この複眼feed、Instagram に限らず、Facebook や Twitter、Youtube、Tumblr など、様々な SNS やブログ等のフィードから写真や動画を抽出して埋め込むことができ、さらに Instagram の写真は Instagram のサイトに飛んでくれるなど、とても良い感じなのですが、サムネイルのサイズが設定したサイズ(px)に固定されるため、レスポンシブでないところが難点です。複眼feed ではレスポンシブとうたってありますが、PC からのアクセスとスマホ等からのアクセスとでレイアウトを切り替えることができるというもので、PC レイアウトの可変幅には対応していません。

ただ、埋め込まれた状態の HTML を確認すると、table タグで直接埋め込まれており、よくある iframe 方式ではないので、CSS を使って上書きすることができます。

複眼feed で埋め込まれる HTML

埋め込まれた HTML は次のようなものです。(サムネイルのサイズを 230px × 230px、間隔を 2px × 2px、レイアウトを 3 列× 2 行、テンプレートを標準とした場合)

<div id="_fukugan_xxxxx">
  <table class="_fukugan_grid _fukugan_grid_xxxxx" style="background-color: #FFFFFF;overflow: hidden;width: 702px;height: 468px;border: none;margin: 0;padding: 0;">
    <tbody>
      <tr>
        <td class="_fukugan_cell " title="(キャプション)" style="position: relative;padding: 2px 2px;">
          <a href="https://fukugan.com/rule/" rel="nofollow" style="position: absolute;top: 5px;left: 5px;color: white;z-index: 1000;width: 14px;height: 14px;overflow: hidden;line-height: 14px;clear: both;text-align: left;" onmouseover="this.style.width='150px'; this.querySelector('svg').style.display = 'none'" onmouseout="this.style.width='20px';  this.querySelector('svg').style.display = 'block'">
            <svg width="14" height="14" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" style="float: left;fill: white;opacity: 0.5;"><path d=" M16 0 A16 16 0 0 1 16 32 A16 16 0 0 1 16 0 M19 15 L13 15 L13 26 L19 26 z M16 6 A3 3 0 0 0 16 12 A3 3 0 0 0 16 6 "></path></svg>
            <span style="display: inline-block;text-decoration: none;width: 124px;color: black;background-color: white;padding-left: 3px;font-size: 11px;">ブログパーツ 複眼feed</span>
          </a>
          <a href="https://www.instagram.com/p/xxxxx/" target="_blank" style="width: 230px;height: 230px;color: inherit;border: 0;display: block;text-decoration: none;position: relative;">
            <span class="_fukugan_mask" style="width: 230px;height: 230px;display: none;background-image: url('//fukugan.com/rssimg/thumb_cache/mask/r0_230x230.png');z-index: 2;text-align: center;position: absolute;cursor: pointer;border-radius: 0px;">
              <p style="line-height:1.2;text-align:center;word-break:break-all;color:white;padding:0;margin:12px;font-size:12px;text-decoration: underline;"><span style="display: block;">(キャプション)</span></p>
            </span>
            <img class="_fukugan_thumbnail" alt="(キャプション)" src="//fukugan.com/rssimg/thumb_cache/crop_fr0_230x230/http....jpg" style="width: 230px;height: 230px;object-fit: cover;border: none;border-radius: 0px;">
          </a>
          <a class="_fukugan_report_link" target="_blank" style="visibility: hidden; position: absolute; right: 4px; top: 4px;" href="//fukugan.com/rssimg/report.php?url=https....jpg" rel="nofollow">x</a>
        </td>
        <td class="_fukugan_cell " title="(キャプション)" style="position: relative;padding: 2px 2px;">
          <a href="https://www.instagram.com/p/xxxxx/" target="_blank" style="width: 230px;height: 230px;color: inherit;border: 0;display: block;text-decoration: none;position: relative;">
            <span class="_fukugan_mask" style="width: 230px;height: 230px;display: none;background-image: url('//fukugan.com/rssimg/thumb_cache/mask/r0_230x230.png');z-index: 2;text-align: center;position: absolute;cursor: pointer;border-radius: 0px;">
              <p style="line-height:1.2;text-align:center;word-break:break-all;color:white;padding:0;margin:12px;font-size:12px;text-decoration: underline;"><span style="display: block;">(キャプション)</span></p>
            </span>
            <img class="_fukugan_thumbnail" alt="(キャプション)" src="//fukugan.com/rssimg/thumb_cache/crop_fr0_230x230/http....jpg" style="width: 230px;height: 230px;object-fit: cover;border: none;border-radius: 0px;">
          </a>
          <a class="_fukugan_report_link" target="_blank" style="visibility: hidden; position: absolute; right: 4px; top: 4px;" href="//fukugan.com/rssimg/report.php?url=https....jpg" rel="nofollow">x</a>
        </td>
        <td class="_fukugan_cell " title="(キャプション)" style="position: relative;padding: 2px 2px;">
          <a href="https://www.instagram.com/p/xxxxx/" target="_blank" style="width: 230px;height: 230px;color: inherit;border: 0;display: block;text-decoration: none;position: relative;">
            <span class="_fukugan_mask" style="width: 230px;height: 230px;display: none;background-image: url('//fukugan.com/rssimg/thumb_cache/mask/r0_230x230.png');z-index: 2;text-align: center;position: absolute;cursor: pointer;border-radius: 0px;">
              <p style="line-height:1.2;text-align:center;word-break:break-all;color:white;padding:0;margin:12px;font-size:12px;text-decoration: underline;"><span style="display: block;">(キャプション)</span></p>
            </span>
            <img class="_fukugan_thumbnail" alt="(キャプション)" src="//fukugan.com/rssimg/thumb_cache/crop_fr0_230x230/http....jpg" style="width: 230px;height: 230px;object-fit: cover;border: none;border-radius: 0px;">
          </a>
          <a class="_fukugan_report_link" target="_blank" style="visibility: hidden; position: absolute; right: 4px; top: 4px;" href="//fukugan.com/rssimg/report.php?url=https....jpg" rel="nofollow">x</a>
        </td>
      </tr>
      <tr>
        <td class="_fukugan_cell " title="(キャプション)" style="position: relative;padding: 2px 2px;">
          :
        </td>
        <td class="_fukugan_cell " title="(キャプション)" style="position: relative;padding: 2px 2px;">
          :
        </td>
        <td class="_fukugan_cell " title="(キャプション)" style="position: relative;padding: 2px 2px;">
          :
        </td>
      </tr>
    </tbody>
  </table>
  <style type="text/css">
    ._fukugan_grid_xxxxx ._fukugan_cell { margin: 0;  padding: 0;  border: none; }
    ._fukugan_grid_xxxxx { border-collapse: collapse;  border-spacing:0;  display: block;  overflow: hidden; }
    ._fukugan_grid_xxxxx ._fukugan_icon_play { position: absolute;  color: #FFF;  top: 50%;  left: 50%;  width: 1em;  height: 1em;  font-size: 23px;  margin-top: -0.5em;  margin-left: -0.5em; }
    ._fukugan_grid_xxxxx ._fukugan_cell:hover ._fukugan_mask { display: block !important; }
  </style>
  <style>
    ._fukugan_grid_xxxxx ._fukugan_cell:hover ._fukugan_report_link { visibility: visible !important; }
    ._fukugan_grid_xxxxx ._fukugan_report_link { cursor: pointer;  height: 12px;  position: absolute;  visibility: hidden;  width: 12px;  z-index: 9000;  font-size: 10px !important;  color: #dadada !important;  text-align: center; }
    ._fukugan_grid_xxxxx ._fukugan_report_link:hover { color: #ffffff !important;  text-decoration: underline; }
  </style>
</div>

設定したレイアウト(列×行)でテーブルが組まれており、サムネイルの間隔が td 要素の padding として、サムネイルのサイズがサムネイルの a 要素と span 要素、img 要素に、それぞれインラインスタイルで設定されていることがわかります。さらに、サムネイルの幅と間隔の合計値が table 要素の width と height に設定されています。

なお、サムネイルの間隔が td 要素の padding となっていますので、サムネイルの間隔は実質2倍となり、2px とした場合は 4px に、全体の周囲にも 2px の余白ができます。

また、それぞれのセルの中には、サムネイル要素の後に、複眼RSSの品質向上のための問題報告のリンクがあり、1行目先頭のセルには「ブログパーツ 複眼feed」のラベルと規約へのリンクがあります。

可変幅のレスポンシブに対応させる

そこで、可変幅に対応させるための CSS は次のとおり。

table._fukugan_grid {
  width: 100% !important;
  height: auto !important;
}

table._fukugan_grid td {
  width: calc((100% - 12px) / 3);
  padding-top: calc((100% - 12px) / 3);
}

table._fukugan_grid td a[href^='https://www.instagram.com'],
table._fukugan_grid td a[href^='https://www.instagram.com'] > span,
table._fukugan_grid td a[href^='https://www.instagram.com'] > img {
  width: 100% !important;
  height: 100% !important;
  vertical-align: bottom;
}

table._fukugan_grid td a[href^='https://www.instagram.com'] > span {
  overflow-y: auto;
}

まず、テーブルの幅を 100%、高さを自動に設定します。

次にセルの幅をテーブル幅からサムネイルの間隔の合計を引いたものを列数で当分します。前述のとおり、サムネイルの間隔がセルの padding に設定されているので、上記の例の場合は 2px × 2(左右) × 3列で 12px となります。また、サムネイルの間隔を 0 とした場合は、width: calc(100% / 3); あるいは width: 33.33%; などとなります。

一方、セルの高さは親要素の高さが定まらないため height で設定することが難しいので、padding-top を使います。こうすることで、親要素の幅を基準に高さを設定することができます。サムネイルが正方形の場合は width と同じ値でよいですが、高さが異なる場合は padding-top: calc((100% - 12px) / 3 * .75); などのように幅との比率を掛けます。

そして、インラインで幅と高さが設定されている、サムネイルの a 要素と span 要素、img 要素の width と height を 100% に上書き指定します。

最後の span 要素への overflow 設定は、マウスオンで表示されるキャプションが長い場合にスクロールさせるためのものですが、この辺りはお好みで。


この複眼feed、画像や動画の埋め込みに特化しているので、Instagram や Facebook 専用のサービスのように他の情報を引っ張ってくることはできませんが、複数のアカウントを統合することも、複数の異なる SNS 等からサムネイルを読み込むこともできます。リンク先はそれぞれの SNS 等のサイトですし、広告表示も気にならない程度なので、いろいろと活用できそうです。