astro-notion-blogのYouTube埋め込みの縦横比を16:9にする

Featured image of the post

目次

まえがき

📄Arrow icon of a page linkastro-notion-blogでコードブロックからHTML要素を挿入する

前回の記事⬆でHTMLを記事に埋め込むことができるようにしたので、試しにYouTubeの埋め込み機能を試してみました。色々調べるとレスポンシブ対応にする方法が書いてあって、なるほど~となったのですが、astro-notion-blogには標準でYouTubeの埋め込み機能があります。

astro-notion-blogでは、NotionにYouTubeを埋め込むと記事にもそのまま埋め込まれます。そういえばこれまでの記事で使ったことが無いなと思い、試してみました。

Icon in a callout block
実際のページのスクリーンショットを使用しているため、画像とYoutubeの埋め込みとの見分けがつかないレベルでややこしいです。このページをダークモードに切り替えるのをおすすめします。
Image in a image block
横に長い

16:9よりも細長いです。サムネイルは上下が見切れています。再生すると左右に黒枠が出てきます。

これを2列に配置するとこうなります。

Image in a image block

今度は上下に黒枠が出現しています。

標準の埋め込みと16:9の縦横比かつレスポンシブ対応のHTMLを並べてみます。

Image in a image block
左が標準 右がHTML
<div style="position: relative; padding-bottom: 56.25%;">
  <iframe 
    style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;" 
    src="https://www.youtube.com/embed/[YouTubeの動画ID]" 
    frameborder="0" 
    allow="autoplay; encrypted-media" 
    allowfullscreen>
  </iframe>
</div>
埋め込んだHTMLはこれです。

1行目の56.25%が肝で、16:9の高さを横幅に対する割合で決めるということになります。9÷16=0.5625ですね

ℹ️
2023/07/23追記
CSSのaspect-ratioというプロパティによって直接的に縦横比を指定できることを知ったので、これを使うように更新しました。

僕はドンピシャで16:9にしたいのでastro-notion-blogのコードを書き換えることにします。

コードの変更

YouTubeの埋め込みのための処理はsrc\components\notion-blocks\Video.astroにあります。

<div class="video">
  <div>
    {
      isYouTubeURL(url) && (
        <iframe
          src={`https://www.youtube.com/embed/${parseYouTubeVideoId(url)}`}
          title="YouTube video player"
          frameborder="0"
          allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
          allowfullscreen
        />
      )
    }
  </div>
  <Caption richTexts={block.Video.Caption} />
</div>

<style>
  .video div:first-child {
    width: 100%;
  }
  .video div:first-child iframe {
    width: 100%;
    height: 340px;
  }
  @media (max-width: 640px) {
    .video div:first-child iframe {
      height: 220px;
    }
  }
</style>
Video.astro 16行目から

このコードは上がHTML、下がCSSとなっています。

処理を読み込むと、iframeは大体同じ形で、変数としてYouTubeのURLを入れているようです。

styleは下に別記。
srcframeborderallowfullscreenは同じ。
allowの内容が少し多い。

ということで、styleを同じように変更すれば良さそうです。

旧バージョン

<style>
  .video div:first-child {
    width: 100%;
  }
  .video div:first-child iframe {
    width: 100%;
    height: 340px;
  }
  @media (max-width: 640px) {
    .video div:first-child iframe {
      height: 220px;
    }
  }
</style>
Video.astro 37行目から
<div style="position: relative; padding-bottom: 56.25%;">
  <iframe 
    style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;" 
    src="https://www.youtube.com/embed/[YouTubeの動画ID]" 
    frameborder="0" 
    allow="autoplay; encrypted-media" 
    allowfullscreen>
  </iframe>
</div>
16:9にするための埋め込みHTML

Video.astroのCSS部分では、.videoクラス内における3つの項目についてstyleを指定しています。具体的には、幅は全て100%(ビューポート幅)で、状況に応じて高さをpxで指定しています。

上から

  1. 最初の子div要素
  2. 最初の子div要素内のiframe要素
  3. ビューポートの幅が640px以下の場合の最初の子div要素内のiframe要素

です。

縦横比を保ったまま横幅に合わせて変形してほしいため、ビューポートの幅が640px以下になったとき(サイドバーがサイドから消えて記事のメインカラムだけが表示されるようになったとき)でも同じようにしたいです。16:9にするコードではビューポートの横幅に対して高さを50.25%という割合で指定することによって縦横比を維持しています。なので、2と3の処理は同じになり、ビューポートの幅によって処理を分岐させる必要もなくなります。

これで何がどうすればいいのか分かったので書き換えます。3. の項目はコメントアウトします。

<style>
  .video div:first-child {
    position: relative;
    padding-bottom: 56.25%;
  }
  .video div:first-child iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }
  /*@media (max-width: 640px) {
    .video div:first-child iframe {
      height: 220px;
    }
  }*/
</style>
Video.astro 37行目から

新バージョン

Video.astroのCSS部分では、.videoクラス内における3つの項目についてstyleを指定しています。具体的には、幅は全て100%(ビューポート幅)で、状況に応じて高さをpxで指定しています。

<style>
  .video div:first-child {
    width: 100%;
  }
  .video div:first-child iframe {
    width: 100%;
    height: 340px;
  }
  @media (max-width: 640px) {
    .video div:first-child iframe {
      height: 220px;
    }
  }
</style>
Video.astro CSS部分 37行目から

上から

  1. 最初の子div要素
  2. 最初の子div要素内のiframe要素
  3. ビューポートの幅が640px以下の場合の最初の子div要素内のiframe要素

です。外側から順に指定されています。

aspect-ratioの指定は、16:9であればaspect-ratio: 16 / 9;のようにします。

2.と3.では高さが固定値によって設定されていますが、今回はビューポート幅に関係なく縦横比を保ったままレスポンシブに対応させたいので、2.に統合します。

そして、1.の.video div:first-childに縦横比を指定、2.の.video div:first-child iframeは1.の幅と高さの100%とすることで、縦横比を保ったまま埋め込み動画のサイズがレスポンシブに対応します。

<style>
  .video div:first-child {
    width: 100%;
    aspect-ratio: 16 / 9;
  }
  .video div:first-child iframe {
    width: 100%;
    height: 100%;
  }
</style>
書き換え後

デモ

Image in a image block

この下のやつは実際に再生される埋め込みの動画です。上のGIFと同じ配置になっています。