CSS の aspect-ratio プロパティ

レスポンシブ レイアウトでスペースの維持に役立つ CSS プロパティ。

対応ブラウザ

  • Chrome: 88。
  • Edge: 88.
  • Firefox: 89。
  • Safari: 15。

ソース

アスペクト比は、ほとんどの場合、2 つの整数とコロン(width:height または x:y)で表されます。写真で最も一般的なアスペクト比は 4:3 と 3:2 ですが、動画や最近の一般向けカメラでは 16:9 のアスペクト比が一般的です。

アスペクト比が同じ 2 つの画像。1 つは 634 × 951 ピクセル、もう 1 つは 200 × 300 ピクセル。アスペクト比はどちらも 2:3 です。
同じアスペクト比の 2 つの画像。1 つは 634 x 951 ピクセルで、もう 1 つは 200 x 300 ピクセルです。どちらもアスペクト比は 2:3 です。

レスポンシブ デザインの登場により、アスペクト比の維持はウェブ デベロッパーにとってますます重要になっています。特に、画像のサイズが異なり、使用可能なスペースに応じて要素のサイズが変化する場合は重要です。

アスペクト比の維持が重要となる例を以下に示します。

  • レスポンシブ iframe を作成する。iframe は親の幅の 100% で、高さは特定のビューポート比率にする必要があります。
  • 画像、動画、埋め込みの固有のプレースホルダ コンテナを作成し、アイテムが読み込まれてスペースを占有するときに再レイアウトしないようにする
  • インタラクティブなデータの可視化や SVG アニメーション用の均一でレスポンシブなスペースを作成する
  • カードやカレンダーの日付などの複数要素のコンポーネント用に、均一でレスポンシブなスペースを作成する
  • さまざまなサイズの複数の画像に均一でレスポンシブなスペースを作成する(object-fit とともに使用可能)

object-fit

アスペクト比を定義すると、レスポンシブ コンテキストでメディアのサイズを調整できます。このバケットのもう 1 つのツールは object-fit プロパティです。これにより、ブロック内のオブジェクト(画像など)がブロックをどのように埋めるかを指定できます。

オブジェクト フィット デモの可視化
さまざまな object-fit 値を示しています。Codepen のデモをご覧ください。

initialfill の値は、スペースを埋めるように画像を再調整します。この例では、ピクセルが再調整されるため、画像が押しつぶされてぼやけます。理想的ではありません。object-fit: cover は、画像の最小サイズを使用してスペースを埋め、このサイズに基づいて画像を切り抜いてスペースに収まるようにします。最小境界で「ズームイン」します。object-fit: contain を使用すると、画像全体が常に表示されるため、cover とは逆に、最大境界のサイズ(上記の例では幅)を取得し、スペースに収まるように画像のサイズを変更して固有のアスペクト比を維持します。object-fit: none の場合、画像の中心(デフォルトのオブジェクト位置)が自然なサイズで切り抜かれます。

object-fit: cover は、さまざまなサイズの画像を扱う際に、ほとんどの状況で均一なインターフェースを実現できますが、この方法では情報が失われます(画像は最も長い辺で切り抜かれます)。

こうした詳細が重要である場合(美容製品のフラットレイを使用する場合など)は、重要なコンテンツを切り抜くことはできません。そのため、理想的なシナリオは、切り抜かずに UI スペースに収まるさまざまなサイズのレスポンシブ画像です。

古いハック: padding-top でアスペクト比を維持する

padding-top を使用して、カルーセル内の投稿プレビュー画像のアスペクト比を 1:1 に設定する。
padding-top を使用して、カルーセル内のポストプレビュー画像のアスペクト比を 1:1 に設定する。

レスポンシブにするには、アスペクト比を使用できます。これにより、特定のアスペクト比のサイズを設定し、残りのメディアを個々の軸(高さまたは幅)に基づいて設定できます。

画像の幅に基づいてアスペクト比を維持する、現在広く受け入れられているクロスブラウザ ソリューションは、「Padding-Top ハック」と呼ばれます。このソリューションには、親コンテナと絶対配置された子コンテナが必要です。次に、アスペクト比をパーセンテージとして計算し、padding-top として設定します。例:

  • アスペクト比 1:1 = 1 / 1 = 1 = padding-top: 100%
  • アスペクト比 4:3 = 3 / 4 = 0.75 = padding-top: 75%
  • アスペクト比 3:2 = 2 / 3 = 0.66666 = padding-top: 66.67%
  • アスペクト比 16:9 = 9 ÷ 16 = 0.5625 = padding-top: 56.25%

アスペクト比の値がわかったので、それを親コンテナに適用できます。たとえば次のようになります。

<div class="container">
  <img class="media" src="..." alt="...">
</div>

次に、以下の CSS を作成します。

.container {
  position: relative;
  width: 100%;
  padding-top: 56.25%; /* 16:9 Aspect Ratio */
}

.media {
  position: absolute;
  top: 0;
}

aspect-ratio でアスペクト比を維持しています

aspect-ratio を使用して、カルーセル内の投稿プレビュー画像にアスペクト比 1:1 を設定します。
aspect-ratio を使用して、カルーセル内のポストプレビュー画像に 1:1 のアスペクト比を設定します。

残念ながら、これらの padding-top 値の計算は直感的ではなく、追加のオーバーヘッドと配置が必要になります。新しい組み込み aspect-ratio CSS プロパティにより、アスペクト比を維持するための記述が明確になりました。

同じマークアップで、padding-top: 56.25%aspect-ratio: 16 / 9 に置き換え、aspect-ratio を指定された比率 width / height に設定できます。

padding-top の使用
.container {
  width: 100%;
  padding-top: 56.25%;
}
aspect-ratio を使用する
.container {
  width: 100%;
  aspect-ratio: 16 / 9;
}

padding-top ではなく aspect-ratio を使用すると、はるかに明確になり、通常のスコープ外で何かを行うためにパディング プロパティを大幅に変更する必要がなくなります。

この新しいプロパティでは、アスペクト比を auto に設定する機能も追加されています。つまり、「本質的なアスペクト比に置き換えられた要素は、そのアスペクト比を使用します。そうでない場合、ボックスには推奨のアスペクト比はありません」。auto<ratio> の両方を同時に指定する場合、望ましいアスペクト比は、widthheight で割った値です。ただし、固有のアスペクト比に置換要素がある場合は除きます。その場合、代わりにこのアスペクト比が使用されます。

例: グリッド内の一貫性

これは、CSS グリッドや Flexbox などの CSS レイアウト メカニズムともうまく連携します。スポンサー アイコンのグリッドなど、アスペクト比を 1:1 に維持したい子を持つリストについて考えてみましょう。

<ul class="sponsor-grid">
  <li class="sponsor">
    <img src="..." alt="..."/>
  </li>
  <li class="sponsor">
    <img src="..." alt="..."/>
  </li>
</ul>
.sponsor-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
}

.sponsor img {
  aspect-ratio: 1 / 1;
  width: 100%;
  object-fit: contain;
}
さまざまなアスペクト比の親要素を持つグリッド内の画像。Codepen のデモをご覧ください。

例: レイアウト シフトを防ぐ

aspect-ratio のもう 1 つの優れた機能は、プレースホルダ スペースを作成して累積レイアウト シフトを防ぎ、Core Web Vitals を改善できることです。この最初の例では、Unsplash などの API からアセットを読み込むと、メディアの読み込みが完了するとレイアウト シフトが発生します。

読み込まれたアセットにアスペクト比が設定されていない場合に発生する累積レイアウト シフトの動画。この動画は、エミュレートされた 3G ネットワークで撮影されています。

一方、aspect-ratio を使用すると、このレイアウト シフトを防ぐプレースホルダが作成されます。

img {
  width: 100%;
  aspect-ratio: 8 / 6;
}
アスペクト比が設定された動画が、読み込まれたアセットで設定されています。この動画は、エミュレートされた 3G ネットワークで撮影されています。Codepen でデモを確認する。

参考: アスペクト比の画像属性

画像のアスペクト比を設定するには、image 属性を使用する方法もあります。画像のサイズが事前にわかっている場合は、これらのサイズを widthheight として設定することをおすすめします。

上の例では、サイズが 800 x 600 ピクセルなので、画像マークアップは <img src="image.jpg" alt="..." width="800" height="600"> になります。送信する画像のアスペクト比が同じでも、ピクセル値が必ずしも正確でない場合でも、画像属性値を使用して比率を設定できます。その際、スタイル width: 100% と組み合わせて、画像が適切なスペースを占めるようにします。すべてをまとめると、次のようになります。

<!-- Markup -->
<img src="image.jpg" alt="..." width="8" height="6">
/* CSS */
img {
  width: 100%;
  height: auto;
}

最終的な効果は、CSS で画像に aspect-ratio を設定するのと同様で、累積レイアウト シフトを回避できます(Codepen のデモをご覧ください)。

まとめ

新しい aspect-ratio CSS プロパティを使用すると、複数の最新ブラウザでリリースし、メディアとレイアウト コンテナで適切なアスペクト比を維持することが少し簡単になります。

写真提供: Amy ShamblenLionel Gustave(Unsplash)。