😸

microCMSで出力されるiframeをレスポンシブ対応させてみた話

2020/09/19に公開

こんにちは、ebii(de)と申します。

先日、Nuxt.js + microCMS + Netlifyでブログを作成しました。
(大したこと書いてないけど、こちら

そのときにmicroCMSで埋め込んだiframeがスマホの画面をはみ出てしまう問題に遭遇したので、どう解決したのかをまとめます。

問題点

microCMSでは、リッチエディタにてiframe埋め込みをすると、以下のフォーマットで出力されます。

例:YouTube

<iframe width=\"480\" height=\"270\" src=\"https://www.youtube.com/embed/41Ia291KIvI?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>

参考記事

たぶん、widthheightを直接指定してるのが悪さしてるんだと思います。
さて、どうしたものか。

解決編

以下の記事が参考になりました。

この記事では、microCMSから取得したHTMLをcheerioで弄っております。
これと同じことをiframeに適用すればいいと思いつきました。(多少強引ではありますが……。)

そして、asyncDataを以下のように修正しました。

async asyncData ({ params, $config, error }) {
    try {
      const { data } = await axios.get(
        $config.apiBaseUrl + `/api/v1/blog/${params.slug}`,
        {
          headers: { 'X-API-KEY': $config.apiKey }
        }
      )
      const $ = cheerio.load(data.body)
      $('pre code').each((_, elm) => {
        const result = hljs.highlightAuto($(elm).text())
        $(elm).html(result.value)
        $(elm).addClass('hljs')
      })
      $('iframe').each((_, elm) => {
        const wrapDiv =
          $('<div style="left: 0; width: 100%; height: 0; position: relative; padding-bottom: 56.25%;"></div>')
        $(elm).wrap(wrapDiv)
        $(elm).attr('width', null)
          .attr('height', null)
          .attr('style', 'border: 0; top: 0; left: 0; width: 100%; height: 100%; position: absolute;')
      })
      return {
        ...data,
        body: $.html()
      }
    } catch (err) {
      error({
        statusCode: err.response.status
      })
    }
  }

みてほしいのは$('iframe').each((_, elm) => {...})の部分です。
やっていることは以下の通り。

  1. iframeタグの部分を取得
  2. iframeをdivタグで囲む
  3. iframタグに定義されているwidthheightを削除
  4. iframeタグにstyle追加

これでうまくいきました。

div、iframeタグに追加しているstyleはおまじないみたいなもので、私もしっかり理解はしておりません……。

ただ、divタグのstyleに書いてあるpadding-bottomの数値は結構重要です。
YouTubeの画面比率を16:9に固定するための値なので、ここは必ずこの数値にしておきましょう。
(つまり、他の比率に変更したい場合はここをいじればよいはず。)

これで、無事にYouTubeがレスポンシブ表示されました!

参考になれば幸いです。

Discussion