iframe要素の高さを自動調整でレスポンシブ化する最も簡単な方法

YouTubeなどの動画をウェブページに埋め込む際、よく利用されるiframe要素ですが、img要素のように縦横の比率を維持したまま、様々な画面サイズに対応させる (レスポンシブ化する) ためには、padding-topプロパティとpadding-bottomプロパティの%値が親要素の横幅の相対値であることを利用した、CSSハックに近いコードが広く利用されています。

今回は、iframe要素の、最新で、最も簡単な、レスポンシブ化の方法をご紹介します。

従来のpaddingプロパティを使用したレスポンシブ化

…
<style>
[class*="__iframe__"] {
  position: relative;
}
[class*="__iframe__"]:before {
  content: "";
  display: block;
  padding: 100% 0 0; /* 1 : 1 */
}
[class*="__iframe__"] > iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
.__iframe__ratio-2-1:before {
  padding-top: calc(100% * (1 / 2)); /* 2 : 1 */
}
.__iframe__ratio-3-2:before {
  padding-top: calc(100% * (2 / 3)); /* 3 : 2 */
}
.__iframe__ratio-4-3:before {
  padding-top: calc(100% * (3 / 4)); /* 4 : 3 */
}
.__iframe__ratio-16-9:before {
  padding-top: calc(100% * (9 / 16)); /* 16 : 9 */
}
</style>
…
<figure class="__iframe__ratio-2-1"><iframe width="960" height="480" …></iframe></figure>
<figure class="__iframe__ratio-3-2"><iframe width="960" height="640" …></iframe></figure>
<figure class="__iframe__ratio-4-3"><iframe width="960" height="720" …></iframe></figure>
<figure class="__iframe__ratio-16-9"><iframe width="960" height="540" …></iframe></figure>
…

ご覧のとおり、複雑ですね。

そして、問題なのは、縦横の比率を設定したい要素の親要素に比率を設定している点です。これだと、比率の数だけclass値を用意し、iframe要素毎に適切なclass値を設定する必要がでてきます。

ちなみに、figure要素ではなく、before擬似要素にpadding-topプロパティを設定している理由は、figure要素の左右にマージンやボーダーを設定しても、比率が変化しないためです。

最新のaspect-ratioプロパティを使用したレスポンシブ化

…
<style>
iframe[style*="aspect-ratio:"] {
  max-width: 100%;
  height: auto;
}
</style>
…
<figure><iframe width="960" height="480" … style="aspect-ratio: 2 / 1;"></iframe></figure>
<figure><iframe width="960" height="640" … style="aspect-ratio: 3 / 2;"></iframe></figure>
<figure><iframe width="960" height="720" … style="aspect-ratio: 4 / 3;"></iframe></figure>
<figure><iframe width="960" height="540" … style="aspect-ratio: 16 / 9;"></iframe></figure>
…

iframe要素にaspect-ratioプロパティを設定して、img要素と同様に、max-widthプロパティとheightプロパティを設定するだけです。

このコードであれば、iframe要素に比率を設定したくない場合、aspect-ratioプロパティを設定しないだけで済みます。

このaspect-ratioプロパティは、最近になって、IEを除く主要なブラウザで使用できるようになった、比較的新しいプロパティです。

style属性でaspect-ratioプロパティを設定する理由

HTML側にwidth属性とheight属性があるのに、比率だけCSS側に記述するというのはナンセンスです。

…
<style>
iframe[class*="__ratio__"] {
  max-width: 100%;
  height: auto;
}
.__ratio__2-1 {
  aspect-ratio: 2 / 1;
}
.__ratio__3-2 {
  aspect-ratio: 3 / 2;
}
.__ratio__4-3 {
  aspect-ratio: 4 / 3;
}
.__ratio__16-9 {
  aspect-ratio: 16 / 9;
}
</style>
…
<figure><iframe width="960" height="480" … class="__ratio__2-1"></iframe></figure>
<figure><iframe width="960" height="640" … class="__ratio__3-2"></iframe></figure>
<figure><iframe width="960" height="720" … class="__ratio__4-3"></iframe></figure>
<figure><iframe width="960" height="540" … class="__ratio__16-9"></iframe></figure>
…

このように、コード量が増えるだけでメリットが全くありません。

また、width属性値とheight属性値から比率を導きだすのが面倒ならば、style属性であれば、次のように書くこともできます。

<figure><iframe width="960" height="480" … style="aspect-ratio: 960 / 480;"></iframe></figure>
<figure><iframe width="960" height="640" … style="aspect-ratio: 960 / 640;"></iframe></figure>
<figure><iframe width="960" height="720" … style="aspect-ratio: 960 / 720;"></iframe></figure>
<figure><iframe width="960" height="540" … style="aspect-ratio: 960 / 540;"></iframe></figure>

ただ、やっぱりstyle属性は気持ち悪いですよね。

将来的には、次のようにattr関数値を使用して、style属性すら必要なくなるかもしれませんが、2021年7月現在、attr関数値をプロパティの値として利用できるブラウザはありません。

…
<style>
iframe[width][height] {
  aspect-ratio: attr(width) / attr(height);
  max-width: 100%;
  height: auto;
}
</style>
…
<figure><iframe width="960" height="540" … ></iframe></figure>
…

iframe要素にaspect-ratioプロパティを追加するJSコード

aspect-ratioプロパティで簡単にレスポンシブ化できましたが、ウェブサイト内で大量のiframe要素を使用していて、改修が面倒な場合もあるかと思います。

そんな時には、JavaScriptでaspect-ratioプロパティを追加すると楽です。

document.querySelectorAll( 'iframe[width][height]' ).forEach( ( iframe ) => {
  iframe.style.aspectRatio = iframe.width + '/' + iframe.height;
} );

上記のような短いコードで実装できます。

aspect-ratioプロパティはすごく便利ですね。ブラウザのアップデートと共に、知識もアップデートしないと、どんどん取り残されていってしまいますね。

関連記事