Webサイトのレイアウトをするとき、動画や画像は潜在的な問題を抱えています。
たとえば、CSSで画像の幅を明示的に指定したとしましょう。もしその幅がパーセントまたはビューポート単位で指定され、高さがautoに設定されていると、ブラウザーのウインドウサイズを変更しても画像のアスペクト比は保たれますよね。
ただ、これだと画像が縦長の場合にスペースを取ってしまうので、画像の高さを制限したいときもあります。ところが、単に高さをCSSで制限すると、今度はアスペクト比が崩れてしまうのです。
こうした、画像とアスペクト比に関連する多くの問題は、CSSのobject-fitとobject-positionのプロパティで解決できます。object-fit、object-positionプロパティは、background-sizeとbackground-positionプロパティに似ています。object-fit、object-positionプロパティを聞いたことがない人でも、仕組みはすぐに理解できると思います。
この2つのプロパティは置換要素(replaced elements)に働きかけます。ですが、説明を分かりやすくするため、この記事の中では置換要素の代わりに「画像」という言葉を使うことにします。
なぜ、object-fitとobject-positionを使うのか?
background-sizeとbackground-positionがあるのに、どうしてこの2つのプロパティを使うのかと不思議に思うかもしれません。それには2つの理由があります。
1つは、ある記事の一部として画像を使いたい場合を考えてみましょう。冒頭に書いたケースと同じで、CSSで画像のサイズを設定すると、ブラウザーのウィンドウサイズを変更したときに、アスペクト比が変わります。このケースでは、単にimgタグを使うだけでは不十分です。divタグで、background-sizeとbackground-positionを指定します。
しかしこの方法では、imgタグでコンテンツを指定し、backgroundプロパティでデザインを指定する、といった具合に分けて書く必要があります。imgタグにobject-fitとobject-positionを使えば、imgタグだけの指定で済むのです。
もう1つの理由は、backgroundプロパティは動画に対応できませんが、object-fitとobject-positionなら対応できる点です。動画を表示させるためにはobject-fitとobject-positionが唯一の選択肢ということになります。
object-fitプロパティ
object-fitプロパティは、画像や動画をコンテンツボックスの中でどのように使うかを指定します。次の5つの値があります。
- fill
- contain
- cover
- none
- scale-down
object-fitの構文は以下の通りです。
.fit-image {
object-fit: fill|contain|cover|none|scale-down;
}
fillを設定すれば画像のサイズはコンテンツボックスの中でフィットするように変更されます。このケースでは画像の高さはボックス自体の高さと同じになります。以下がfillプロパティの初期値です。
値をcontainにすると、画像がアスペクト比を維持したままコンテンツボックス内にフィットするようにサイズ変更されます。画像のゆがみ防止とコンテンツボックス内での画像の維持という2つの目的を果たします。画像の余白はあらかじめ設定した色になります。
containは画像の大きさがわからず、コンテナの幅にフィットさせたいときに使えますね。
コンテンツボックスのスペースをアスペクト比を維持したまま完全に埋めたい場合は、coverを使います。画像のサイズは縦横のうち小さい方を基準にして拡大・縮小されます。コンテンツボックスからはみ出した部分は切り取られます。
コンテンツボックスの高さの値も幅の値も無視して、画像を本来の大きさで表示したい場合は、noneを指定します。画像はリサイズされず、コンテンツボックスからはみ出した部分は切り取られます。
最後のscale-downは、画像を縮小します。noneかcontainの値を設定したようにサイズが変更されます。画像の大きさがコンテンツボックスの大きさより小さければnoneの値が適用されます。
object-positionプロパティ
coverプロパティは画像のアスペクト比を維持したままコンテンツボックスのすべてのスペースに表示されます。また、画像はデフォルトで中央に配置されます。画像の中でフォーカスしたいポイントが中央にある場合にはよいですが、そうでない場合はどうしたらいいでしょうか?
そんなときはobject-positionプロパティを設定します。background-positionと同じ機能です。以下はフォーカスポイントを左上に設定しています。
.zero-zero {
object-position: 0px 0px;
}
ピクセルで大きさを指定する代わりに、パーセントも使えます。たとえば、object-position: 0% 0%は左上になり、object-position: 100% 100%は右下になります。
画像のアスペクト比とコンテンツボックスの大きさが同じなら、object-positionを設定してもあまり違いが見られません。とはいえ、明確な理由があってアスペクト比をオフに設定した場合には結果は改善されます。下記のCodePenのデモでこのポイントを紹介しています。
2つ目の、ポジションを左上に設定すれば太陽が表示されます。
object-positionプロパティについてもう1つ。これを使えばアニメーションになります。正しく使えば驚くような効果が得られるのです。下のコードを見てみましょう。
img {
/* other CSS here... */
object-fit: cover;
object-position: 0% 0%;
animation: ltr 5s alternate infinite;
}
@keyframes ltr {
0% {
object-position: 0% 0%;
}
25% {
object-position: 20% 0%;
}
100% {
object-position: 100% 100%;
}
}
このコードでは、キーフレームアニメーションで画像の位置を動かしています。すばらしい出来栄えです。
1人の対象から他の人にフォーカスを移動する動画にも使えますね。
ブラウザーサポートとポリフィル
今回紹介したプロパティが使えそうだなと分かったと思います。ただ、実際に現場で使えるかは、ターゲットとするブラウザーによりますよね。object-fit、object-positionともにIE/Edgeを除く、メジャーなブラウザをサポートしています。
一般的に、object-fitプロパティがあればよいでしょう。もし特定のユーザー層のエクスペリエンスを多少犠牲にしても構わないのであれば、積極的にこのプロパティを使ってもよいでしょう。古いブラウザーをサポートする必要がある場合は、Federico Briganteのポリフィルを試してみるといいかもしれません。
(原文:Using CSS’s object-fit and object-position Properties)
[翻訳:島田理彩]
[編集:Livit]