INSPIRATION

【CSS】object-fitはCSSだけで画像をコンテナーにフィットさせてトリミングもできるとっても素晴らしいプロパティー

CSSプロパティーの「object-fit」を使えば、簡単にCSSだけで画像を指定したサイズ(コンテナー)にフィットさせて、かつ、はみ出すの部分はトリミングができてしまいます。要は画像として配置しているのに、「background-size」と同じことができてしまいます。

そこで今日は、素晴らしいCSSプロパティー「object-fit」を色々とサンプルで詳しく紹介していきたいと思います。
 

なぜ画像フィット・トリミングが必要なのか?

例えば、記事一覧ページでサムネイル画像が並ぶページの場合、全ての画像が同じサイズ、もしくは縦横比でないと並びが崩れてしまいます。

横幅はCSSで揃えられるけど縦幅はバラバラで崩れている

 

じゃ、全部同じサイズでアップすれば良いじゃん!と思いますが、CMSでユーザーが任意の画像をアップする場合などはそうはいきません。

ですので、どのようなサイズの画像が配置されても並びが崩れないようにするために画像のフィット・トリミングが必要になってきます。

基準のサイズで画像をトリミングして揃えているので並びが崩れていない。※点線部分はトリミングされていて実際は表示されません。

 



object-fitとは?

そこで登場するのがCSSプロパティー「object-fit」です。

「object-fit」はコンテナーに対して、置換要素(画像や動画)をどのように表示するかを設定します。ここでいうコンテナーとは、「div」などの画像や動画をラップする要素ではなく、画像や動画に高さ、幅を指定してそれ自体をコンテナーとします。


 

プロパティー一覧

では、設定できるプロパティーを見ていきましょう。

fill 初期値。縦横比を無視して画像をコンテナーにフィットさせます。縦横比無視なので画像は歪む場合があります。
contain 縦横比を維持しつつ、コンテナーからはみ出さないようにぴったりフィットするようにします。余白の部分は縦横どちらの場合も中央に配置します。
cover コンテナーに余白が出ないよう縦横比を維持しつつ、全体を覆うようにフィットさせ縦横中央に配置します。コンテナーからはみ出る部分はトリミングします。
none 画像のリサイズはせずに縦横中央に配置します。
scale-down コンテナーより画像が大きい場合は「contain」を、小さい場合は「none」を指定します。
object-position 画像の位置を指定します。指定の仕方は「object-position:’横の位置’ ‘縦の位置’;」となります。位置の指定は「%」、「px」や「top」・「center」という指定もできます。初期値は「object-position:50% 50%」で縦横中央に配置します。

 



使い方

では使い方をやっていきましょう。今回は違いがわかりやすいように、下の3つの画像でやっていきます。


 

ベースのHTML

HTMLは下記をベースとして使用します。

<div class="container">
	<div class="container-item">
		<div class="container-item-img">
			<img src="https://webdesignday.jp/wp-content/uploads/2020/04/p7976-4.jpg" alt="">
		</div>
		<h5>title here</h5>
		<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis. </p>
	</div>
	<div class="container-item">
		<div class="container-item-img">
			<img src="https://webdesignday.jp/wp-content/uploads/2020/04/p7976-5.jpg" alt="">
		</div>
		<h5>title here</h5>
		<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis. </p>
	</div>
	<div class="container-item">
		<div class="container-item-img">
			<img src="https://webdesignday.jp/wp-content/uploads/2020/04/p7976-6.jpg" alt="">
		</div>
		<h5>title here</h5>
		<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis. </p>
	</div>
</div>

 

まずは何も設定していない状態

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.


並びが崩れてとても見づらいですね。。。
 

CSS

.container{
	display: flex;
	justify-content: space-between;
}
.container-item{
	width: 30%;
}
.container-item-img{
	border: 1px solid #ccc;
}
.container-item-img img{
	display: block;
	height: auto;
	max-width: 100%;
}

サムネイルを横並びにするために「.container」は「display:flex」にしています。
 



親要素にheightとoverfflow:hiddenを指定してやる

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.


並びは揃って見やすくなりました。しかし、画像のトリミング位置をなんとかしたいです。。。
 

CSS

.container{
	display: flex;
	justify-content: space-between;
}
.container-item{
	width: 30%;
}
.container-item-img{
	border: 1px solid #ccc;
	height: 150px;
	overflow: hidden;
}
.container-item-img img{
	display: block;
	height: auto;
	max-width: 100%;
}

CSSは画像をラップする要素「.container-item-img」に高さを指定し、「overflow: hidden;」ではみ出す部分を非表示にしています。
 



object-fit「fill」でやる

やっとobject-fitの登場です。まずは初期値の「fill」指定します。

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.


こちらも並びが揃いました。しかし画像が歪んでいます。。。
 

CSS

.container{
	display: flex;
	justify-content: space-between;
}
.container-item{
	width: 30%;
}
.container-item-img{
	border: 1px solid #ccc;
}
.container-item-img img{
	display: block;
	height: 150px;
	object-fit: fill;
	width: 100%;
}

「.container-item-img」の高さ指定はなしにして、「.container-item-img img」で「img」に直接、幅と高さを指定しています。横幅は「width: 100%;」で横幅いっぱいに指定しています。初期値の「fill」では縦横比は無視しますので、画像が歪みます。また初期値なので「object-fit: fill;」は省略しても同じ結果になります。
 



object-fit「contain」でやる

次は「contain」を指定した場合です。

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.


こちらも並びは揃っています。縦横比が崩れているわけでもないですがコンテナーに余白が出ています。
 

CSS

.container{
	display: flex;
	justify-content: space-between;
}
.container-item{
	width: 30%;
}
.container-item-img{
	border: 1px solid #ccc;
}
.container-item-img img{
	display: block;
	height: 150px;
	object-fit: contain;
	width: 100%;
}

「contain」を指定した場合は、縦横比を維持しつつ、コンテナーからはみ出さないようにぴったりフィットするようにします。たとえ「width: 100%;」を指定していても、それによってコンテナーからはみ出してしまう場合は自動で「height: 100%;」になります。画像をトリミングせず全体を表示したい時に指定すると良いですね。
 



object-fit「cover」でやる

次は「cover」を指定した場合です。

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.


画像はコンテナーいっぱいに余白が出ることなくフィットしています。かつ、縦横比は維持し、位置は縦横中央になり、はみ出す部分はトリミングされています。
 

CSS

.container{
	display: flex;
	justify-content: space-between;
}
.container-item{
	width: 30%;
}
.container-item-img{
	border: 1px solid #ccc;
}
.container-item-img img{
	display: block;
	height: 150px;
	object-fit: cover;
	width: 100%;
}

「cover」を指定した場合は、縦横比を維持しつつ全体を覆うようにコンテナーにフィットします。「background-size: cover;」を背景画像ではなく通常の画像でできてしまいます。
 



object-fit「none」でやる

次は「none」を指定した場合です。

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.


画像がリサイズされずに元のサイズで表示されますので、コンテナーより画像が小さい場合は余白が出ています。
 

CSS

.container{
	display: flex;
	justify-content: space-between;
}
.container-item{
	width: 30%;
}
.container-item-img{
	border: 1px solid #ccc;
}
.container-item-img img{
	display: block;
	height: 150px;
	object-fit: none;
	width: 100%;
}

「none」では画像のリサイズは行わず、縦横中央に表示して画像がはみ出る場合はトリミングします。逆にコンテナーより画像が小さい場合は余白が出ます。
 



object-fit「scale-down」でやる

次は「scale-down」を指定した場合です。

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.

title here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.


「contain」と似ていますが、左と中央の画像はコンテナーより大きいので「contain」が指定され、右の画像はコンテナーより小さいのでリサイズされていません。
 

CSS

.container{
	display: flex;
	justify-content: space-between;
}
.container-item{
	width: 30%;
}
.container-item-img{
	border: 1px solid #ccc;
}
.container-item-img img{
	display: block;
	height: 150px;
	object-fit: scale-down;
	width: 100%;
}

「scale-down」ではコンテナーより画像が大きい場合は「contain」を、小さい場合は「none」を指定します。「contain」と違う点はこちらはコンテナーより画像が小さい場合はリサイズされないので、画像が荒れることはありません。
 



トリミングする位置の指定「object-position」

「object-fit」は自動で画像の配置を縦横中央にしてくれて便利なのですが、中央以外の位置を指定したい場合は「object-position」で画像の位置を指定することができます。基準点は左上で初期値は「object-position:50% 50%」です。

違いがわかりやすいようにこちらだけ画像を変更しました。それ以外のHTMLの変更はありません。

数値で指定。

「object-position: 40px 40px;」で左上を基準に縦横40px移動しています。

右上を指定

「object-position: 100% 0;」で指定しています。

右下を指定

「object-position: right bottom;」で指定しています。


画像の位置を任意で指定しました。
 

CSS

.container{
	display: flex;
	justify-content: space-between;
}
.container-item{
	width: 30%;
}
.container-item-img{
	border: 1px solid #ccc;
}
.container-item-img img{
	display: block;
	height: 150px;
	object-fit: none;
	width: 100%;
}
.container-item:nth-child(1) img{
	object-position: 40px 40px;/*pxで指定*/
}
.container-item:nth-child(2) img{
	object-position: 100% 0;/*右上*/
}
.container-item:nth-child(3) img{
	object-position: right bottom;/*右下*/
}

位置指定もわかりやすいように「object-fit: none;」で画像をリサイズしない指定にしています。
 



videoでやる

せっかくなので動画でもやってみます。

トリミング前の動画です。

 


動画でも画像と同様にフィットとトリミングができています。素晴らしいです。
 

HTML

<video class="video" src="https://webdesignday.jp/wp-content/uploads/2020/05/p7976-video.mp4" autoplay muted loop width="200" height="auto"></video>

videoタグで動画を配置しただけです。
 

CSS

.video{
	height: 150px;
	object-fit: cover;
	width: 100%;
}

画像と同じく幅と高さを指定して「object-fit: cover;」を指定しました。
 



IE対応

「object-fit」を初めて知った時は「なんて素晴らしいプロパティーがあるんだ!!!」と小躍りしたい気持ちになったのですが、喜びも束の間、絶望の底に叩き落とされることになりました。なんとIE11には対応しておりません。(2020年5月現在)


 

上の画像はこの記事の「containでやる」の部分をIE11で見たところです。「object-fit:fill(初期値)」と同様の表示結果となってしまっています。
 

これはもう「残念」とか「悲しい」では言い表せない激情が渦巻いていますが、そんなことを言っても何も解決しないので、粛々とIEにも対応させていきたいと思います。。。
 

jsファイルの読み込み

IE対応は「object-fit-images」のjsファイルを読み込んで解決します。下記のリンクから必要データ一式をダウンロードします。
GitHub – fregante/object-fit-images

そして、「dist」フォルダ内にある「ofi.min.js」をheadタグ内で読み込みます。

<script type="text/javascript" src="ofi.min.js"></script>

ファイルのパスは適宜変更してください。
 

CSSで指定

さらにCSSで「object-fit-images」用の指定をしていきます。指定は「font-family」でやります。

.container-item-img img{
	display: block;
	font-family: 'object-fit: contain;';
	height: 150px;
	object-fit: contain;
	width: 100%;
}

 

scriptの記述

最後にscriptを記述して完了です。下記のコードを</body>の直前に記述します。

<script>
	objectFitImages();
</script>

ただこれだと全ての画像が対象になってしまいますので、下記のように特定のクラスやIDに適用した方が良いです。

<script>
	objectFitImages('.obj-fit-img');
	objectFitImages('#obj-fit-img');
</script>

任意で決めたクラス、IDのみが対象になります。
 

これでIE11でもできました!!!
 



まとめ

CSSプロパティー「object-fit」、いかがだったでしょうか?

以前に「【jQuery】コピペでOK!画像や動画を全画面にフィットさせて中央に表示する」という記事を書いたり、「改良版【jQuery】コピペでOK!画像や動画を親要素にフィットさせて中央に表示する」という記事を書いたりと、画像をフィットさせるには四苦八苦してきました。

この記事を書いて、「新しい情報を知らないのは罪なことだな」と改めて感じました。無駄なことをせずに簡単にできる方法があるなら採用しない手はありません。ただどうしても新しいプロパティーなどは全ブラウザに対応していなかったりするデメリットはあるのですが。。。

きっと近いうちにこの「object-fit」も、全てのブラウザで正常に表示できると信じて使っていきたいと思います。
 

それでは良いWEBデザイン日和を!Have a nice WEBDESIGNDAY!
 

【CSS】Sassは絶対使った方が良いよ!使い方入門編
PREVIOUS INSPIRATION