object-fitは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/wp1/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/wp1/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/wp1/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/wp1/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;」を指定しました。

まとめ

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

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

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

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

Category&Tag