CSS aspect-ratioプロパティの基礎知識、便利な使い方、実装に必要なプログレッシブエンハンスメント
Post on:2021年6月23日
ついにSafariでもaspect-ratioプロパティがサポートされると先日のWWDC21で発表がありました(参考: webkit.org)。これで主要ブラウザすべてにサポートされることになり、aspect-ratioプロパティの基礎知識、便利な使い方、そして実装に必要なプログレッシブエンハンスメントについて紹介します。
CSSのaspect-ratioプロパティを使用すると、レスポンシブ対応の画像や下記のようにサイズが異なるロゴ画像を揃えて配置するのも簡単に実装できます。
Let's Learn About Aspect Ratio In CSS
by Ahmad Shadeed
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
- はじめに
- アスペクト比とは
- アスペクト比の算出方法
- CSSでのアスペクト比の実装
- aspect-ratioプロパティの基礎知識
- aspect-ratioプロパティのプログレッシブエンハンスメント
- aspect-ratioプロパティの知っておくと便利な使い方
- 終わりに
はじめに
レスポンシブ対応で実装する際、画像を他の要素の幅と高さの比率と一定にすることは重要です。CSSでは、長年にわたってpaddingハックを使用してきましたが、現在ではCSSでアスペクト比がブラウザにサポートされています。
参考: paddingハックについては、 古いハック: padding-topでアスペクト比を保つをご覧ください。
この記事では、アスペクト比とは何か、これまではどのようにしていたか、新しい実装方法について解説します。もちろん、適切なフォールバックを伴った実装も解説します。
それでは、始めましょう!
アスペクト比とは
アスペクト比とはWikipediaによると、
矩形における長辺と短辺の比率。
タイヤのような3次元形状の中の2次元平面(トーラス面)、あるいはロッドの長さや直径のようなものにも適用される。使用される代表的な物は、映像、紙、航空機や鳥の翼の形状、微細加工における穴径と深さなどである。例えば矩形のときは"長辺の割合:短辺の割合"で表される。
Webデザインで使用されるアスペクト比は、画像の幅と高さが互いに比例してサイズ変更する必要があることを意味します。下記をご覧ください。
4:3のアスペクト比
上記はリンゴとブドウで、比率が4:3であることを示しています。
アスペクト比が4:3の場合に作成できる最小サイズのボックスは、4px*3pxのボックスです。このボックスの高さが幅に比例して変更されると、アスペクト比を維持したボックスが作成されます。
アスペクト比を維持したいろいろなサイズのボックス
ボックスのサイズは比例して変更されており、幅と高さの比率は4:3で一貫しています。ここで、ボックスに重要な画像が含まれていると想像してみてください。
ボックスに重要な画像が含まれている場合
サイズが変わっても、画像のディテールが保たれていることに注目してください。アスペクト比を一定にすることで、下記のメリットが得られます。
- Webサイトで使用している画像は、さまざまなビューポートサイズでも一貫して表示されます。
- 重要なディテールは保たれます。
- レスポンシブな動画要素も用意できます。
- デザイナーが画像サイズの明確なガイドを作成することで、デベロッパーが実装プロセスで画像サイズを処理できます。
アスペクト比の算出方法
アスペクト比を算出するには、下記のように幅を高さで割ります。
アスペクト比の算出方法
上記の場合、幅と高さの比率は1.33です。つまり、この比率を尊重する必要があります。 それを考慮しながら、下記をご覧ください。
右は、横幅÷縦幅の値が1.02になっており、元のアスペクト比(1.33または4:3)とは異なります。
4:3という値をどのようにして求めるのかと思われるかもしれません。これは「最も近い標準的なアスペクト比」と呼ばれるもので、それを見つけるためのツール(Nearest Normal Aspect Ratio)もあります。UIデザインに取り組む際には、使用する画像のアスペクト比を正確に把握することを強くお勧めします。この計算機を使用すれば、それが可能になります。
アスペクト比のコンセプトが明確になったことを願っています。また、すでにご存じの方は、知識を再確認していただけたと思います。
CSSでのアスペクト比の実装
CSSでアスペクト比を実装するには、以前はパーセント値のpaddingを使用していました。しかし、最近、すべての主要ブラウザでaspect-ratioプロパティがネイティブサポートされるようになりました。ネイティブサポートの解説に入る前に、まずは昔ながらの方法を解説します。
ある要素に垂直方向のパーセント値のpaddingがある場合、それは親の幅に基づいて行われます。下記をご覧ください。
パーセント値のpaddingを与えた要素
見出し要素にpadding-top: 50%;がある場合、その値は親の幅に基づいて算出されます。上記では親の幅が200pxなので、padding-topは100pxになります。
使用するパーセント値を算出するには、画像の高さを幅で割る必要があります。その結果で得られた数値が、使用したいパーセント値です。画像の幅が260px、高さが195pxの場合を考えてみましょう。
パーセント値のpadding = 高さ / 幅
195/260の結果は0.75(または75%)です。
カードのグリッドがあり、それぞれにサムネイル画像があるとします。サムネイル画像は、幅と高さが等しくなるようになっています。
サムネイル画像は、幅と高さが等しくなるように
何らかの理由で、コンテンツの作成者が他の画像とサイズが一致しない画像をアップロードしました。中央のカードの高さが他のカードと同じではないことに注目してください。
高さを固定したり、object-fit: cover;を追加すればいいんじゃないか、と思われるかもしれません。問題は解決するでしょうか?そんなに単純ではありません。この解決策は、複数のビューポートサイズで見栄えが悪くなります。
高さを固定するのでは解決策にならない
中サイズでは、高さ固定の画像は左右から切り取られすぎ、スマホでは幅が広すぎます。これはすべて、高さを固定していることが原因です。さまざまなメディアクエリを使用して高さを定義することもできますが、実用的な解決策ではありません。
ここで必要となるのは、ビューポートのサイズに関係なく、サムネイル画像のサイズを統一することです。これを実現するには、パーセント値のpaddingを使用してアスペクト比を実装する必要があります。
1 2 3 4 5 6 7 8 9 |
<article class="card"> <div class="card__thumb"> <img src="thumb.jpg" alt="" /> </div> <div class="card__content"> <h3>Muffins Recipe</h3> <p>Servings: 3</p> </div> </article> |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
.card__thumb { position: relative; padding-top: 75%; } .card__thumb img { position: absolute; left: 0; top: 0; width: 100%; height: 100%; object-fit: cover; } |
上記のCSSにより、サムネイル画像のラッパー(.card__thumb)の高さはその幅に依存することが定義されました。また、画像は絶対配置され、親の全幅と全高を持ち、異なるサイズの画像がアップロードされても、object-fit: cover;が適用されます。これでさまざまなビューポートサイズで適切に表示されるようになります。
カードのサイズがどのように変化し、サムネイル画像のアスペクト比が影響を受けなかったかに注目してください。
aspect-ratioプロパティの基礎知識
今年の初頭に、Chrome、Safari TP、Firefox Nightlyで、CSSのaspect-ratioプロパティがサポートされました。さらに最近では、Safari 15でもサポートされました。
このプロパティの便利な点は、パーセント値のpaddingを使用せずに、アスペクト比を使用できることです。aspect-ratioプロパティに必要なアスペクト比を定義するだけでいいのです。
前述の例は、下記のように記述することができます。
1 2 3 4 5 6 7 8 9 10 11 |
/* 古い方法 */ .card__thumb { position: relative; padding-top: 75%; } /* aspect-ratioプロパティを使用した方法 */ .card__thumb { position: relative; aspect-ratio: 4/3; } |
アスペクト比がどのように変化するかは、下記をご覧ください。
実際の動作は、下記のデモページで確認できます。
※画像がリンク切れですが、アスペクト比の挙動は確認できます。
See the Pen
Changing Aspect Ratio by Ahmad Shadeed (@shadeed)
on CodePen.
次に、aspect-ratioプロパティを使用したネイティブのアスペクト比が役立つ使用例と、それを段階的に強化していく方法を解説します。
aspect-ratioプロパティのプログレッシブエンハンスメント
CSSの@supportsとCSS変数を使用することで、CSSのaspect-ratioプロパティを使用することができます。これは、Peter-Paul Kochの記事で学びました。
1 2 3 4 5 6 7 8 9 10 11 |
.card { --aspect-ratio: 16/9; padding-top: calc((1 / (var(--aspect-ratio))) * 100%); } @supports (aspect-ratio: 1) { .card { aspect-ratio: var(--aspect-ratio); padding-top: initial; } } |
参考: CSSの変数(カスタムプロパティ)便利な使い方を詳しく解説
aspect-ratioプロパティの知っておくと便利な使い方
CSSのaspect-ratioプロパティを使用する最も一般的な例は、カード画像です。これについてはすでに解説したので、改めて取りあげることはしません。ここでは、他の使用例を解説します。
ロゴ画像
私は以前、CSSのobject-fitと配置を使用して異なるサイズのロゴ画像を適切に配置するテクニックについて記事で解説しました。ここではaspect-ratioプロパティを使用してさらに簡単に実装できます。
参考: CSSでロゴのようにサイズが異なる画像を美しく揃えて配置するスタイルシートの実装テクニック
それでは、ロゴ画像を見てましょう。
それぞれサイズが異なるロゴ画像
サイズが異なるロゴ画像が一貫されていて、整列して配置されていることに注目してください。その舞台裏を見てみましょう。
1 2 3 4 5 |
<li class="brands__item"> <a href="#"> <img src="assets/batch-2/aanaab.png" alt="" /> </a> </li> |
1 2 3 4 5 6 7 8 9 |
.brands__item a { padding: 1rem; } .brands__item img { width: 130px; object-fit: contain; aspect-ratio: 2/1; } |
最小サイズにとしてベースの幅を130pxにし、高さはaspect-ratioプロパティが解決してくれます。
paddingと画像サイズ
ブルーのエリアは画像サイズで、object-fit: contain;を使用すると画像を歪まないようにできます。
レスポンシブ対応の円形要素
レスポンシブに対応した円形の要素を実装したと思ったことはありませんか? CSSのaspect-ratioプロパティは、これを実装するのに最適です。
レスポンシブ対応の円形要素
1 2 3 4 5 6 7 |
.person { width: 180px; aspect-ratio: 1; border-radius: 50%; border: 3px solid #d6d6d6; background-color: #f8f8f8; } |
アスペクト比を表す2つの値が同じ場合は、aspect-ratio: 1/1;ではなくaspect-ratio: 1;と記述することができます。FlexboxのCSSグリッドを使用している場合、幅はオプションとなり、最小値として機能するように追加できます。
外部リンク
これは、最近クライアントのプロジェクトで遭遇した使用例です。外部リンクがあり、最初はスマホとデスクトップで異なるpaddingを定義して実装していました。
外部リンク
aspect-ratioプロパティを使えば、スマホでpaddingを調整する(つまり小さくする)必要がなく、親の幅に合わせてレスポンシブにすることができます。
終わりに
リソース
- CSS spec
- Native Aspect Ratio Boxes in CSS thanks to aspect-ratio
- New aspect-ratio CSS property supported in Chromium
翻訳記事: CSS aspect-ratioプロパティの使い方、レスポンシブやレイアウトシフトで大活躍 - Create Responsive Image Effects With CSS Gradients And aspect-ratio
コメントや提案があれば、@shadeed9までお願いします。
sponsors