レスポンシブ レイアウトでスペースの維持に役立つ CSS プロパティ。
アスペクト比
アスペクト比は、ほとんどの場合、2 つの整数とコロン(width:height または x:y)で表されます。写真で最も一般的なアスペクト比は 4:3 と 3:2 ですが、動画や最近の一般向けカメラでは 16:9 のアスペクト比が一般的です。
レスポンシブ デザインの登場により、アスペクト比の維持はウェブ デベロッパーにとってますます重要になっています。特に、画像のサイズが異なり、使用可能なスペースに応じて要素のサイズが変化する場合は重要です。
アスペクト比の維持が重要となる例を以下に示します。
- レスポンシブ iframe を作成する。iframe は親の幅の 100% で、高さは特定のビューポート比率にする必要があります。
- 画像、動画、埋め込みの固有のプレースホルダ コンテナを作成し、アイテムが読み込まれてスペースを占有するときに再レイアウトしないようにする
- インタラクティブなデータの可視化や SVG アニメーション用の均一でレスポンシブなスペースを作成する
- カードやカレンダーの日付などの複数要素のコンポーネント用に、均一でレスポンシブなスペースを作成する
- さまざまなサイズの複数の画像に均一でレスポンシブなスペースを作成する(
object-fit
とともに使用可能)
object-fit
アスペクト比を定義すると、レスポンシブ コンテキストでメディアのサイズを調整できます。このバケットのもう 1 つのツールは object-fit
プロパティです。これにより、ブロック内のオブジェクト(画像など)がブロックをどのように埋めるかを指定できます。
initial
と fill
の値は、スペースを埋めるように画像を再調整します。この例では、ピクセルが再調整されるため、画像が押しつぶされてぼやけます。理想的ではありません。object-fit: cover
は、画像の最小サイズを使用してスペースを埋め、このサイズに基づいて画像を切り抜いてスペースに収まるようにします。最小境界で「ズームイン」します。object-fit: contain
を使用すると、画像全体が常に表示されるため、cover
とは逆に、最大境界のサイズ(上記の例では幅)を取得し、スペースに収まるように画像のサイズを変更して固有のアスペクト比を維持します。object-fit: none
の場合、画像の中心(デフォルトのオブジェクト位置)が自然なサイズで切り抜かれます。
object-fit: cover
は、さまざまなサイズの画像を扱う際に、ほとんどの状況で均一なインターフェースを実現できますが、この方法では情報が失われます(画像は最も長い辺で切り抜かれます)。
こうした詳細が重要である場合(美容製品のフラットレイを使用する場合など)は、重要なコンテンツを切り抜くことはできません。そのため、理想的なシナリオは、切り抜かずに UI スペースに収まるさまざまなサイズのレスポンシブ画像です。
古いハック: padding-top
でアスペクト比を維持する
レスポンシブにするには、アスペクト比を使用できます。これにより、特定のアスペクト比のサイズを設定し、残りのメディアを個々の軸(高さまたは幅)に基づいて設定できます。
画像の幅に基づいてアスペクト比を維持する、現在広く受け入れられているクロスブラウザ ソリューションは、「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
でアスペクト比を維持しています
残念ながら、これらの padding-top
値の計算は直感的ではなく、追加のオーバーヘッドと配置が必要になります。新しい組み込み aspect-ratio
CSS プロパティにより、アスペクト比を維持するための記述が明確になりました。
同じマークアップで、padding-top: 56.25%
を aspect-ratio: 16 / 9
に置き換え、aspect-ratio
を指定された比率 width
/ height
に設定できます。
.container { width: 100%; padding-top: 56.25%; }
.container { width: 100%; aspect-ratio: 16 / 9; }
padding-top
ではなく aspect-ratio
を使用すると、はるかに明確になり、通常のスコープ外で何かを行うためにパディング プロパティを大幅に変更する必要がなくなります。
この新しいプロパティでは、アスペクト比を auto
に設定する機能も追加されています。つまり、「本質的なアスペクト比に置き換えられた要素は、そのアスペクト比を使用します。そうでない場合、ボックスには推奨のアスペクト比はありません」。auto
と <ratio>
の両方を同時に指定する場合、望ましいアスペクト比は、width
を height
で割った値です。ただし、固有のアスペクト比に置換要素がある場合は除きます。その場合、代わりにこのアスペクト比が使用されます。
例: グリッド内の一貫性
これは、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;
}
例: レイアウト シフトを防ぐ
aspect-ratio
のもう 1 つの優れた機能は、プレースホルダ スペースを作成して累積レイアウト シフトを防ぎ、Core Web Vitals を改善できることです。この最初の例では、Unsplash などの API からアセットを読み込むと、メディアの読み込みが完了するとレイアウト シフトが発生します。
一方、aspect-ratio
を使用すると、このレイアウト シフトを防ぐプレースホルダが作成されます。
img {
width: 100%;
aspect-ratio: 8 / 6;
}
参考: アスペクト比の画像属性
画像のアスペクト比を設定するには、image 属性を使用する方法もあります。画像のサイズが事前にわかっている場合は、これらのサイズを width
と height
として設定することをおすすめします。
上の例では、サイズが 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 Shamblen、Lionel Gustave(Unsplash)。