8192.jp

CSSのみでアスペクト比を固定する「aspect-ratio」の使い方

Web制作 2022/06/23 2022/06/23

最近ようやくIEが死滅したので、今まで「IEも対応させなきゃいけないからなぁ…」という理由で使えなかった(もしくはIEでも動作する代替コードも併用しなきゃいけなかった)テクニックが心置きなく使えるようになりましたね。

特にCSSはかなり顕著で、今回紹介する「aspect-ratio」以外にも色々なプロパティが使えるようになりましたが…それはまた別の記事で紹介します。

目次

    aspect-ratio(アスペクト比)とは

    これはほとんどの人が知っていると思いますが、アスペクト比とは縦横の比率です。Web的に言うと縦横のピクセルの比率ですね。

    ちなみに縦横とは言いましたが、だいたい「横:縦」で表記されます。

    よく見る比率

    • 16:9(YouTubeやテレビなどの映像)
    • 21:9(最近増えてきたウルトラワイドモニター)
    • 8:5(たまーに見かけるWXGA・WUXGAモニター)
    • 4:3(アナログテレビやデジタルカメラ)
    • 3:2(一眼レフ)
    • 2.35:1(映画)
    • 1.618…:1(黄金比)
    • 1:1(正方形)

    実際のサイズ感はこんな感じ。

    See the Pen Untitled by Leo_8192 (@Leo_8192) on CodePen.

    aspect-ratioの記述方法

    aspect-ratioの使い方は超簡単で、aspect-ratio: 16/9;のように横と縦の数値をスラッシュで区切って記述します(小数もOK)。

    .content{
      width: 1920px;
      aspect-ratio: 16/9;
    }

    このようにアスペクト比を指定すると、width(横幅)に対しての高さが自動的に計算されてheight1080pxになります。

    もちろん逆も然りで…

    .content{
      height: 1080px;
      aspect-ratio: 16/9;
    }

    こうするとwidth1920pxになります。

    また、スラッシュとその後に続く数値は省略可能で、省略した場合は縦の比率は「1」として扱われます。

    .content{
      width: 400px;
      aspect-ratio: 4;
    }

    このように記述すると「4:1」として扱われるので、height100pxになります。パッと見で分かりにくいのでわざわざ省略する必要は無さそうですが…

    活用例

    具体的に、どのような場面でこのプロパティが活きるのかをいくつか紹介します。

    レスポンシブデザインに対応したGoogleマップの埋め込み

    Webサイトに埋め込んだGoogleマップの大きさを、画面幅に応じて変化させることが出来ます。

    See the Pen Untitled by Leo_8192 (@Leo_8192) on CodePen.

    まぁ結構前からGoogleマップをレスポンシブサイトに埋め込む方法はあったんですが、そのコードがこちら(HTMLは共通)。

    .gmap{
    	position: relative;
    	padding-top: 56.25%;
    }
     
    .gmap iframe{
    	position: absolute;
    	top: 0;
    	left: 0;
    	width: 100%;
    	height: 100%;
    }

    padding-top56.25%にすることによって、無理矢理16:9の比率にするという手法です。例えば横幅が1920pxだった場合、高さは1920*0.5625=1080pxとなります。

    これでも良いっちゃ良いんですが、直感的じゃない上にコード量も多いので、これからは実務でもaspect-ratioを使う手法に切り替えていくつもりです。

    CLSの改善(小難しい話だからスルーでOK)

    CLSっていうのはコアウェブバイタルの指標の1つである「Cumulative Layout Shift」の略ですね。これを改善するっていうのは、ザックリ言うと「ユーザーの意図しないレイアウトのズレを減らす」ってことです。広告消すために✕押そうとしたらいきなり画像がバーンって出てきて誤クリックしちゃうようなクソサイトは死んでほしい。

    まぁクソ広告の話は置いといて、CLSの改善で最も意識しなきゃいけないのが画像の読み込みです。てかほぼこれ。

    例えば横600px・縦400pxの画像を表示させたいとき、画像パス以外何も指定せずに書いた場合は読み込みを完了するまでその場所には何も表示されません。んで、読み込みが完了した瞬間に画像がドーンと表示されて後続のコンテンツが400px下に移動します。これがレイアウトシフトです。

    <img src="600x400.jpg"> <!-- レイアウトシフトが発生するパターン -->

    これの対策として一般的なのがimg要素width="〇〇"height="〇〇"をしっかり記述するというもの。これでブラウザは画像を読み込む前から高さを把握できるので、レイアウトシフトは起こらなくなります。

    <img src="600x400.jpg" width="600" height="400"> <!-- レイアウトシフトが発生しないパターン -->

    ただ一つ弱点があって、この方法だけだとレスポンシブに対応出来ません。

    スマホ用サイト等で画像サイズを縮小しなくてはいけない場合、大抵CSSでこういう制御をしますよね。

    img{
      width: 100%;
      height: auto; /*初期値*/
    }

    これで画面幅に応じて画像が縮小されるようになりますが、高さはautoなので可変、つまり画像の読み込みが終わって画像を横幅何pxで表示するかをブラウザが把握するまで、高さが計算されません。

    ここで登場するのがaspect-ratioで、600x400の画像をレスポンシブ対応させつつCLSも改善することが出来るのが以下のCSSです。

    img{
      width: 100%;
      height: auto;
      aspect-ratio: 3/2;
    }

    画像のアスペクト比をブラウザに伝えてあげることで、ブラウザは即座に高さを計算することが出来るようになります。これでレスポンシブ対応とCLS改善を両立させることが出来るようになります。

    注意点

    実は先程の方法にも欠点があって、様々なアスペクト比の画像が混在するページだと画像ごとにaspect-ratioを指定しなくてはいけないんですよね…一応こういう書き方をすることも出来る!という記事があるんですが…↓

    img{
      width: 100%;
      height: auto;
      aspect-ratio: attr(width) / attr(height);
    }

    attr(width)attr(height)もあまり見ない記述ですが、これはimg要素に指定された属性から数値を取得し、CSS側で呼び出すというものです。これが動けば全部の問題が解決するんですが、Chromeだとエラー吐くんですよね…Firefoxだとしっかり動作してくれるので、ブラウザの対応待ちって感じです。

    以上。