レスポンシブ レイアウトで間隔の維持に役立つ新しい CSS プロパティです。
アスペクト比
アスペクト比は一般的に、2 つの整数とコロンで、幅:高さ、x:y のいずれかのサイズで表現します。写真の最も一般的なアスペクト比は 4:3 と 3:2 ですが、動画などの最近の消費者向けカメラのアスペクト比は 16:9 である傾向があります。
レスポンシブ デザインの登場により、ウェブ デベロッパーにとってアスペクト比を維持することがますます重要になっています。特に、画像のサイズの違いや、使用可能なスペースに応じて要素のサイズが変化するためです。
アスペクト比を維持することが重要になるのは、次のような場合です。
- レスポンシブ iframe を作成する(親の幅の 100%、高さは特定のビューポート比率のままにする)
- 画像、動画、埋め込み用の固有のプレースホルダ コンテナを作成して、アイテムが読み込まれてスペースを占有するときに再レイアウトされないようにする
- インタラクティブなデータ可視化や SVG アニメーションのための、均一で応答性の高いスペースの作成
- カードやカレンダーの日付などの複数要素コンポーネント用に、均一で応答性の高いスペースを作成する
- 寸法の異なる複数の画像に対して、均一で応答性の高いスペースを作成する(
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
として設定します。次に例を示します。
- アスペクト比 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
値の計算はあまり直感的ではなく、追加のオーバーヘッドと配置が必要になります。新しい組み込み CSS プロパティである aspect-ratio
により、アスペクト比をより明確に管理できるようになりました。
同じマークアップで、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
のもう一つの優れた機能は、プレースホルダ スペースを作成して、Cumulative Layout Shift を防止し、より優れたウェブに関する指標を提供できることです。この最初の例では、Unsplash などの API からアセットを読み込むと、メディアの読み込み完了時にレイアウト シフトが発生します。
一方、aspect-ratio
を使用すると、このレイアウト シフトを防ぐためのプレースホルダが作成されます。
img {
width: 100%;
aspect-ratio: 8 / 6;
}
参考: アスペクト比の画像属性
画像のアスペクト比を設定するもう 1 つの方法は、画像属性を使用することです。事前に画像の寸法がわかっている場合は、その寸法を 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%;
}
結局のところ、その効果は CSS を使用して画像に aspect-ratio
を設定するのと同じで、累積レイアウト シフトが回避されます(Codepen のデモを参照)。
おわりに
新しい aspect-ratio
CSS プロパティを使用すると、複数の最新ブラウザで起動し、メディア コンテナとレイアウト コンテナで適切なアスペクト比を維持しやすくなります。
撮影者: Amy Shamblen、Lionel Gustave(Unsplash 提供)