CSSのobject-fitで設置画像のサイズをコントールする
object-fitプロパティは、画像の元サイズとは違うサイズを指定した場合の表示コントロールに使います。
imgタグを囲む親要素に対してではなく、imgタグに対して直接CSSでサイズ指定します。
設定により拡大縮小・トリミング・縦横比などの度合いが変わります。
様々な投稿画像を揃える「object-fit」
本記事ではCSS「object-fit」プロパティを紹介します。
これを使うと、指定したサイズ枠に対して小さい画像は適切に引き伸ばされ、はみ出す画像はトリミングする事ができます。
object-fitのポイントは、背景画像に使う「background-size」と同じ感じで、配置画像(imgタグ)を直接コントロールできる点です。
本記事では各種サンプルを確認しながら、object-fitについて詳しく解説します。
画像は引き伸ばし・トリミングが必要な場合がある
このobject-fitには、明確な利用用途があります。
例えばブログ記事一覧にサムネイル画像を並べる場合、基本的に全ての画像は同じサイズで用意するべきですよね。
サイズがそれぞれ違う場合、元サイズに任せていると並びが崩れてしまうからです。
そこで各画像サイズに頼らずに、CSSで一律のサイズに指定する事がよくあります。
CMSなどでユーザーが投稿する場合
自分が用意する時はサイズを揃えれば良いだけですが、例えばクライアントに画像をUPしてもらう場合は難しい部分があります。
クライアントにもよりますが、画像を加工する技術が無い場合が多いです。
そこでどんなサイズの画像がアップされてもレイアウトが崩れないよう、CSSによる画像サイズのコントロールが必要になるのです。
つまり枠サイズは統一するので、多少引き伸ばされたり見切れていても勘弁して下さいという事ですね。
object-fitの役割
object-fitは、画像の縦横サイズとCSS上の設定サイズが違う場合に、どのように映すか決定するプロパティです。
CSSでimgに縦横サイズを指定したら、それが「表示枠」になります。
表示枠は親要素ではなくimgタグそのもの
ここでの表示枠とは外側を囲む「div」などの親要素ではなく、画像タグそのものを指します。
imgタグ(動画ならvideoタグ)自体に幅や高さをCSSで指定した場合です。
background-position
外枠を囲むdivに対してであれば、背景画像を制御する「background-position」がありますよね。
ただし直接画像が表示されるとなれば、それは使えません。
そんな時に役立つのが、object-fitプロパティです。
本来のサイズがバラバラの画像をまとめる用途
例えばそれぞれサイズの異なる以下の画像があったとします。
300×200の画像
600×450の画像
100×150の画像
この画像を各ページで単体で使っているなら、何も違和感はないでしょう。
ところがこの複数の画像を一緒に並べるとなると、そのままでは見栄えがよくありません。
高さや幅も違って不揃いなので気持ち悪い訳です。
300px×200pxに統一する場合
仮に300px×200pxが正式なサムネイル画像の表示枠だとすると、一番上の画像ならばピッタリマッチしています。
ではこの枠に対して、2つ目の600px×450pxの元サイズ画像をどう表示させるか。
縦に合わせて縮小するのか横に合わせるのか、どこをトリミングするのか、です。
さらに3つ目の100px×150pxの画像は小さいので、適切な拡大が必要になりますね。
この表示枠に対するフィット方法を設定するのが、object-fitの役割です。
object-fitプロパティ一覧
object-fitで設定できるプロパティには様々なものがあります。
object-fit: fill;
これは初期値です。
CSSで元サイズとは違うサイズを指定しつつ、かつobject-fitを設定しなかった場合と同じになります。
fillの場合は縦横比を無視して画像を表示枠サイズに変化させるので、元サイズが合っていなければ画像が歪みます。
object-fit: contain;
表示枠からはみ出さない様に、縦横比を維持しつつ拡大縮小されます。
常に縦横中央に配置され、元サイズの「長い方」が枠にフィットするまで拡大縮小するため、「短い方」に余白が出ます。
表示枠に対する拡大縮小のルール
横幅が長い画像は、表示枠の左右に収まり上下に余白ができる
縦幅が長い画像は、表示枠の上下に収まり左右に余白ができる
※width:100%;でも高さ優先
object-fit: cover;
表示枠に余白を出さない様に、縦横比を維持しつつ全体をカバーする形で拡大縮小されます。
containはサイズの長い方が軸でしたが、coverはサイズの短い方が軸となります。
縦横中央に配置され、表示枠からはみ出る部分はトリミングされます。
表示枠に対する拡大縮小ルール
縦幅が短い場合、表示枠の「高さ」に収まり左右がトリミングされる
横幅が短い場合、表示枠の「横幅」に収まり上下がトリミングされる
※余白はできない
object-fit: none;
縦横中央に配置され、画像の拡大縮小は起きずに元サイズのまま表示されます。
サイズの大きい画像はトリミング
サイズの小さい画像は余白ができる
object-fit: scale-down
表示枠より画像が大きい場合は「contain」を、小さい場合は「none」を指定します。
常に縦横中央に配置されます。
表示枠に対する拡大縮小ルール
横幅が長い画像は、表示枠の左右に収まり上下に余白ができる
縦幅が長い画像は、表示枠の上下に収まり左右に余白ができる
縦横いずれも小さい場合は、原寸サイズのまま上下左右に余白ができる
object-position:
基本的にobject-fitは縦横中央に配置されますが、このプロパティで画像の位置を指定できます。
object-position: "横位置" "縦の位置";
位置の指定は「%」「px」「top」「center」指定可能です。
初期値は「object-position:50% 50%」で縦横中央に配置された状態になります。
未設定の状態
ではいよいよサンプルを交えながら解説していきます。
まずはbootstrapのグリッドシステムを使って3列に並べた画像を配置します。
ソースコード
HTML
<div class="row"> <div class="col-sm-4"> <div class="object-fit-bg"> <img src="images/css_object_fit_img4.png" alt="object-fitサンプル画像"> </div> </div> <div class="col-sm-4"> <div class="object-fit-bg"> <img src="images/css_object_fit_img2.png" alt="object-fitサンプル画像"> </div> </div> <div class="col-sm-4"> <div class="object-fit-bg"> <img src="images/css_object_fit_img3.png" alt="object-fitサンプル画像"> </div> </div> </div>
CSS
.object-fit-bg{ border: solid 1px #999; } .object-fit-bg img{ padding: 2px; }
imgへのサイズ指定もなければ、object-fitもしていないベース状態です。
実例サンプル(同じサイズの画像)
画像サイズが全て同じなのでレイアウトが統一されています。本来はこうあるべきですね。
実例サンプル(サイズが不揃い)
結果
各サイズが違う画像が横並びしますが、そのまま反映されます。
横幅はグリッドシステムにより調整されますが、縦が大きい画像のせいで段が揃いません。
そして小さいサイズの画像は余白ができます。
overflow: hidden;(親枠への設定)
ではobject-fitを使う前に、まずは親枠のdivに対してoverflow: hidden;を設定して対応してみましょう。
以前までよく使っていたコントロール方法ですね。
ソースコード
HTML
<div class="row"> <div class="col-sm-4"> <div class="object-fit-bg"> <img src="images/css_object_fit_img4.png" alt="object-fitサンプル画像"> </div> </div> <div class="col-sm-4"> <div class="object-fit-bg"> <img src="images/css_object_fit_img2.png" alt="object-fitサンプル画像"> </div> </div> <div class="col-sm-4"> <div class="object-fit-bg"> <img src="images/css_object_fit_img3.png" alt="object-fitサンプル画像"> </div> </div> </div>
CSS
.object-fit-bg{ height: 146px; overflow: hidden; border: solid 1px #999; } .object-fit-bg img{ padding: 2px; }
画像を囲むdiv要素に対して高さを指定し、overflow: hidden;ではみ出る部分を非表示にしています。
実例サンプル
結果
これで並びは随分見やすくなりましたが、中央の画像は上端からトリミングされています。
さらにサイズの小さい画像に対しては何もできていませんね。
object-fit: fill;
ではいよいよobject-fitを設定します。まずはデフォルトの状態です。
ソースコード
HTML
<div class="row"> <div class="col-sm-4"> <div class="object-fit-bg"> <img class="of-fill" src="images/css_object_fit_img4.png" alt="object-fitサンプル画像"> </div> </div> <div class="col-sm-4"> <div class="object-fit-bg"> <img class="of-fill" src="images/css_object_fit_img2.png" alt="object-fitサンプル画像"> </div> </div> <div class="col-sm-4"> <div class="object-fit-bg"> <img class="of-fill" src="images/css_object_fit_img3.png" alt="object-fitサンプル画像"> </div> </div> </div>
CSS
.object-fit-bg{ border: solid 1px #999; } .object-fit-bg img{ padding: 2px; } img.of-fill{ width: 100%; height: 146px; object-fit: fill; }
divの高さ指定を外し、imgタグに直接幅と高さを指定しています。
実例サンプル
結果
fillの場合縦横比を無視して敷き詰めるため、縦横サイズが変化して画像が歪みます。
このobject-fit: fill;はデフォルトです。
object-fitを書かずにimgタグにサイズ指定をしただけでも同じ結果になります。
object-fit: contain;
containの特徴は長いサイズの方を表示枠にあわせて、足りない方は余白を作る事です。
ソースコード
HTML
<div class="row"> <div class="col-sm-4"> <div class="object-fit-bg"> <img class="of-contain" src="images/css_object_fit_img4.png" alt="object-fitサンプル画像"> </div> </div> <div class="col-sm-4"> <div class="object-fit-bg"> <img class="of-contain" src="images/css_object_fit_img2.png" alt="object-fitサンプル画像"> </div> </div> <div class="col-sm-4"> <div class="object-fit-bg"> <img class="of-contain" src="images/css_object_fit_img3.png" alt="object-fitサンプル画像"> </div> </div> </div>
CSS
.object-fit-bg{ border: solid 1px #999; } .object-fit-bg img{ padding: 2px; } img.of-contain{ width: 100%; height: 146px; object-fit: contain; }
実例サンプル
結果
containを指定した場合は縦横比を維持しつつ、表示枠からはみ出さない様に敷き詰めようとします。
縦横比は維持なので、上下や左右に余白が出ます。
高さが長い場合は高さ指定が優先
真ん中の画像の様に高さが長い画像の場合は、width: 100%;であっても「高さ指定」の方が優先されます。
高さが軸になるため、横幅に余白ができています。
画像をトリミングせず全体を表示したい場合に有効ですね。
object-fit: cover;
coverの特徴は短いサイズの方を表示枠にあわせるため、はみ出す部分はトリミング前提である事です。
ソースコード
HTML
<div class="row"> <div class="col-sm-4"> <div class="object-fit-bg"> <img class="of-cover" src="images/css_object_fit_img4.png" alt="object-fitサンプル画像"> </div> </div> <div class="col-sm-4"> <div class="object-fit-bg"> <img class="of-cover" src="images/css_object_fit_img2.png" alt="object-fitサンプル画像"> </div> </div> <div class="col-sm-4"> <div class="object-fit-bg"> <img class="of-cover" src="images/css_object_fit_img3.png" alt="object-fitサンプル画像"> </div> </div> </div>
CSS
.object-fit-bg{ border: solid 1px #999; } .object-fit-bg img{ padding: 2px; } img.of-cover{ width: 100%; height: 146px; object-fit: cover; }
実例サンプル
結果
画像はいずれも表示枠まで余白なしで敷き詰められます。
縦横比を維持しつつ位置は縦横中央になり、はみ出す部分がトリミングされます。
coverを指定した場合は縦横比を維持しつつ拡大縮小され、余白はできません。
object-fit: none;
noneを設定した場合、画像のリサイズは行われません。
ソースコード
HTML
<div class="row"> <div class="col-sm-4"> <div class="object-fit-bg"> <img class="of-none" src="images/css_object_fit_img4.png" alt="object-fitサンプル画像"> </div> </div> <div class="col-sm-4"> <div class="object-fit-bg"> <img class="of-none" src="images/css_object_fit_img2.png" alt="object-fitサンプル画像"> </div> </div> <div class="col-sm-4"> <div class="object-fit-bg"> <img class="of-none" src="images/css_object_fit_img3.png" alt="object-fitサンプル画像"> </div> </div> </div>
CSS
.object-fit-bg{ border: solid 1px #999; } .object-fit-bg img{ padding: 2px; } img.of-none{ width: 100%; height: 146px; object-fit: none; }
実例サンプル
結果
縦横中央に表示して画像がはみ出る場合はトリミングし、画像が小さい場合は余白が出ます。
表示枠に対してimgは元サイズのまま何も加工が入らない状態になります。
object-fit: scale-down;
scale-downはcontainと似ていますが、違う所もあります。
ソースコード
HTML
<div class="row"> <div class="col-sm-4"> <div class="object-fit-bg"> <img class="of-scale-down" src="images/css_object_fit_img4.png" alt="object-fitサンプル画像"> </div> </div> <div class="col-sm-4"> <div class="object-fit-bg"> <img class="of-scale-down" src="images/css_object_fit_img2.png" alt="object-fitサンプル画像"> </div> </div> <div class="col-sm-4"> <div class="object-fit-bg"> <img class="of-scale-down" src="images/css_object_fit_img3.png" alt="object-fitサンプル画像"> </div> </div> </div>
CSS
.object-fit-bg{ border: solid 1px #999; } .object-fit-bg img{ padding: 2px; } img.scale-down{ width: 100%; height: 146px; object-fit: scale-down; }
実例サンプル
結果
中央の画像は表示枠より高さがあるのでcontainと同じく高さに合わせて左右の余白ができています。
右の画像は表示枠より縦横が小さいのですが、containの様に拡大されません。
表示枠より画像が小さくても引き伸ばしされないため、画像が荒れない特徴があります。
scale-downの特徴
表示枠より画像が大きい場合はcontainの効果
表示枠より画像が小さい場合はnoneの効果
object-position設定
最後はobject-positionです。常に上下左右中央に表示される画像を位置指定します。
ソースコード
HTML
<div class="row"> <div class="col-sm-4"> <div class="object-fit-bg1"> <img src="images/css_object_fit_img4.png" alt="object-fitサンプル画像"> </div> </div> <div class="col-sm-4"> <div class="object-fit-bg2"> <img src="images/css_object_fit_img2.png" alt="object-fitサンプル画像"> </div> </div> <div class="col-sm-4"> <div class="object-fit-bg3"> <img src="images/css_object_fit_img3.png" alt="object-fitサンプル画像"> </div> </div> </div>
CSS
.object-fit-bg1 img, .object-fit-bg2 img, .object-fit-bg3 img{ width: 100%; height: 146px; object-fit: none; border: solid 1px #999; } .object-fit-bg1 img{ object-position: 40px 40px; } .object-fit-bg2 img{ object-position: 100% 0; } .object-fit-bg3 img{ object-position: right bottom; }
わかりやすいようにobject-fit: none;を設定し、画像が引き伸ばされない様にしています。
実例サンプル
結果
左の画像は上と左にそれぞれ40pxだけ移動した状態です。
中央の画像は右上を見せる位置指定です。
右の画像は右下を軸に見せる位置指定です。
未設定の場合は上下左右中央が起点ですから、いわゆるobject-position: 50% 50%の状態です。
object-positionを設定した時点で、左上が起点となります。