



WithCodeMedia-1-pc
WithCodeMedia-2-pc
WithCodeMedia-3-pc
WithCodeMedia-4-pc




WithCodeMedia-1-sp
WithCodeMedia-2-sp
WithCodeMedia-3-sp
WithCodeMedia-4-sp









Webサイトに画像を配置したとき、「縦横比がおかしくなって人物が横に潰れた」「余白だらけで余ってしまった」「カード型レイアウトで画像の高さがバラバラになった」——そんな経験はないだろうか。これらはすべて、CSSのobject-fitプロパティを使えばほぼ解決できる。
object-fitは、<img>や<video>要素が「枠(コンテナ)」の中にどのようにフィットするかを制御するCSSプロパティだ。背景画像のbackground-sizeに相当する役割を、インライン要素に対して果たす。値は5種類あり、用途に応じて使い分けることで、あらゆるサイズ・比率の画像を美しくトリミング・表示できる。
この記事では、object-fitの5つの値の違いをビジュアルに近い形で解説し、object-positionによる表示位置の調整、aspect-ratioと組み合わせた枠の固定、background-sizeとの使い分けまで徹底的に扱う。コードはすべてコピペで動く実践スタイルで提供する。初心者から中級者まで「これ一本読めば実務で困らない」を目指した。
まず大前提を整理する。imgタグに幅・高さを両方指定すると、ブラウザはデフォルトで画像を引き伸ばして枠いっぱいに表示する。元の縦横比が4:3なのに枠が1:1なら、画像は正方形に押しつぶされる。これが「潰れ問題」の正体だ。
以下の基本コードを見てほしい。widthとheightを両方指定した場合、object-fitを指定しないとデフォルト値のfillが適用される。
/* object-fit未指定=デフォルトはfill(引き伸ばし) */
img {
width: 300px;
height: 200px;
/* このままだと画像が歪む */
}
/* object-fitを指定することで歪みを防げる */
img {
width: 300px;
height: 200px;
object-fit: cover; /* 枠を埋めつつ比率を維持 */
}object-fitはimg・videoなどの置換要素(replaced element)にのみ有効だ。divやpには効かない点は覚えておこう。
対応ブラウザはChrome・Firefox・Safari・Edge、いずれも現行バージョンで完全対応済み。IE11はサポート対象外の現場がほとんどになった2026年時点では、ポリフィルなしで使える。
object-fitには5つの値がある。それぞれの動作の違いを順番に理解すれば、どんな場面でどれを選ぶべきかが自然とわかるようになる。ここでは300px × 200pxの枠に対して、横長(1600×900)・縦長(900×1600)・小さい画像(100×100)を入れたときの動作を意識しながら読んでほしい。
fillはobject-fitのデフォルト値。画像を枠のサイズにあわせて強制的に引き伸ばす。縦横比は無視されるため、比率が異なる画像では必ず歪む。ほぼ使わない値だが、枠と画像の比率が完全に一致する場合のみきれいに表示できる。
.img-fill {
width: 300px;
height: 200px;
object-fit: fill; /* デフォルト。比率が合わないと歪む */
}containは画像全体が枠に収まるよう縮小・拡大する。縦横比は維持されるため、枠の比率と異なると余白(レターボックス)が生まれる。画像を切り取られたくない商品画像・ロゴに向いている。
.img-contain {
width: 300px;
height: 200px;
object-fit: contain;
background-color: #f0f0f0; /* 余白部分に背景色をつけると見栄えが良くなる */
}余白部分はimg自体のbackground-colorで塗れる。商品ページのサムネイルで「画像の周りを白くしたい」場合はこの組み合わせが定番だ。
coverは枠全体を画像で埋めつつ、縦横比を維持する。はみ出た部分はトリミングされる。ブログのアイキャッチ・カードのサムネイル・ヒーロー画像など、「枠を必ず埋めて余白を出さない」場面で最もよく使われる値だ。
.img-cover {
width: 300px;
height: 200px;
object-fit: cover;
/* はみ出た部分はトリミング。表示位置はobject-positionで調整 */
}noneは画像をリサイズしない。元の解像度のまま枠の中央に表示し、はみ出た部分はトリミングされる。小さい画像は余白が生まれ、大きい画像は端が切れる。用途は限られるが、ドット絵やスプライト画像など「拡大縮小で品質が落ちてはいけない」素材に使うことがある。
.img-none {
width: 300px;
height: 200px;
object-fit: none;
/* 元サイズのまま表示。枠より小さければ余白、大きければはみ出てトリミング */
}scale-downはcontainとnoneを比較して、画像が小さく表示されるほうを自動的に選ぶ。「画像が枠より小さいときは実寸で、枠より大きいときはcontainで縮小」という動作になる。ロゴや小さいアイコンを枠に配置しつつ「拡大されて粗くなるのを防ぎたい」場面で便利だ。
.img-scale-down {
width: 300px;
height: 200px;
object-fit: scale-down;
/* 画像が枠より小さければ実寸、大きければcontainと同じ動作 */
}object-fit: coverを使うと画像がトリミングされるが、どの部分を見せるかはデフォルトで中央(center center)になる。人物写真でいえば顔ではなく胴体が切れるケースも出てくる。これを制御するのがobject-positionだ。
/* キーワードで指定 */
img {
width: 300px;
height: 200px;
object-fit: cover;
object-position: top; /* 上基準 */
object-position: bottom; /* 下基準 */
object-position: left; /* 左基準 */
object-position: right; /* 右基準 */
object-position: center; /* 中央(デフォルト)*/
}
/* X Y の順で2値指定 */
img {
object-fit: cover;
object-position: center top; /* 水平中央、垂直上 */
object-position: right bottom; /* 右下 */
}
/* パーセンテージで細かく指定 */
img {
object-fit: cover;
object-position: 30% 20%; /* 左から30%、上から20%の位置を中心に表示 */
}
/* pxで絶対指定も可能 */
img {
object-fit: cover;
object-position: 50px 100px;
}縦長の人物写真を横長の枠に入れるとき、デフォルト(center)では顔が切れることがある。object-positionで調整する。
.portrait-card {
width: 300px;
height: 180px;
object-fit: cover;
object-position: center 20%; /* 上から20%の位置を表示の中心に(顔が上にある写真に有効)*/
}人物の顔位置がほぼ一定のコーポレートサイトのスタッフ写真では、object-position: top centerを一律に当てておくと破綻しにくい。
.product-thumb {
width: 240px;
height: 240px;
object-fit: cover;
object-position: right top; /* 商品の右上に特徴的な部分がある場合 */
}カード型レイアウトで複数の画像を並べるとき、画像ごとに縦横比が違うと高さがバラついてレイアウトが崩れる。これを防ぐにはaspect-ratioプロパティを使う。widthだけ指定してheightをaspect-ratioで決める方法が、レスポンシブ対応と相性が良い。
/* 幅だけ指定して高さをアスペクト比で自動計算 */
img {
width: 100%;
aspect-ratio: 16 / 9; /* 16:9の比率を固定 */
object-fit: cover;
}
/* 正方形(1:1)サムネイル */
img {
width: 100%;
aspect-ratio: 1 / 1;
object-fit: cover;
}
/* 映画的な2.35:1 */
img {
width: 100%;
aspect-ratio: 2.35 / 1;
object-fit: cover;
}<div class="card-grid">
<article class="card">
<img src="thumbnail1.jpg" alt="記事タイトル1" class="card__img">
<h2>記事タイトル1</h2>
</article>
<article class="card">
<img src="thumbnail2.jpg" alt="記事タイトル2" class="card__img">
<h2>記事タイトル2</h2>
</article>
<article class="card">
<img src="thumbnail3.jpg" alt="記事タイトル3" class="card__img">
<h2>記事タイトル3</h2>
</article>
</div>.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24px;
}
.card__img {
width: 100%;
aspect-ratio: 16 / 9; /* 比率を統一。どんな元画像でも同じ高さになる */
object-fit: cover;
display: block; /* imgのデフォルト inline を解除してベースライン問題を防ぐ */
}
@media (max-width: 640px) {
.card-grid {
grid-template-columns: 1fr;
}
}aspect-ratioはすべての現行ブラウザで対応済み。古いコードでよく見られた「paddingトリック(padding-top: 56.25%)」はほぼ不要になった。2026年現在では素直にaspect-ratioを使ってよい。
「background-size: coverと何が違うの?」という疑問はよく聞く。機能的には似ているが、使う場面・メリット・デメリットが異なる。
/* ---------- object-fitパターン ---------- */
.hero-img {
width: 100%;
height: 400px;
object-fit: cover;
object-position: center center;
display: block;
}
/* ---------- background-sizeパターン ---------- */
.hero-bg {
width: 100%;
height: 400px;
background-image: url('hero.jpg');
background-size: cover;
background-position: center center;
background-repeat: no-repeat;
}Googleのコアウェブバイタル・LCP(Largest Contentful Paint)の観点では、ヒーロー画像はimgタグで実装しfetchpriority=”high”を付けるほうが有利だ。CSSのbackground-imageはプリロードが効きにくく、LCPが遅延しやすい。
object-fitはvideoタグにも使える。背景動画・フルスクリーン動画を実装するとき、videoの縦横比がブラウザウィンドウと異なると黒帯が出る。これをobject-fit: coverで解消できる。
<div class="video-hero">
<video
class="video-hero__video"
autoplay
muted
loop
playsinline
src="hero-video.mp4"
></video>
<div class="video-hero__content">
<h1>キャッチコピーをここに</h1>
</div>
</div>.video-hero {
position: relative;
width: 100%;
height: 100vh; /* ビューポートの全高 */
overflow: hidden;
}
.video-hero__video {
position: absolute;
inset: 0; /* top:0; right:0; bottom:0; left:0; の省略形 */
width: 100%;
height: 100%;
object-fit: cover; /* 縦横比を維持して枠を埋める */
object-position: center;
}
.video-hero__content {
position: relative; /* video要素の上に重ねるためz-indexを機能させる */
z-index: 1;
color: #fff;
text-align: center;
padding-top: 40vh;
}playsinline属性はiOS Safariで自動再生を許可するために必須。muted属性がないとAutoplayポリシーで自動再生がブロックされる。この2つはセットで覚えておこう。
YouTubeのiframe埋め込みでも同様の問題が起きる。ただしiframeはobject-fitが効かないため、親要素にpadding-topトリックまたはaspect-ratioを使うのが正しいアプローチだ。
/* YouTube iframeのレスポンシブ対応 */
.youtube-wrapper {
width: 100%;
aspect-ratio: 16 / 9;
position: relative;
}
.youtube-wrapper iframe {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}ここまでの知識を使い、実務でよく登場する3つのUIパターンのコードを完全な形で示す。いずれもコピペで動く。
<ul class="thumb-grid">
<li class="thumb-grid__item">
<a href="#">
<img src="img01.jpg" alt="商品名1" class="thumb-grid__img" loading="lazy">
</a>
</li>
<li class="thumb-grid__item">
<a href="#">
<img src="img02.jpg" alt="商品名2" class="thumb-grid__img" loading="lazy">
</a>
</li>
<li class="thumb-grid__item">
<a href="#">
<img src="img03.jpg" alt="商品名3" class="thumb-grid__img" loading="lazy">
</a>
</li>
<li class="thumb-grid__item">
<a href="#">
<img src="img04.jpg" alt="商品名4" class="thumb-grid__img" loading="lazy">
</a>
</li>
</ul>.thumb-grid {
list-style: none;
padding: 0;
margin: 0;
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
}
.thumb-grid__img {
display: block;
width: 100%;
aspect-ratio: 1 / 1; /* 正方形固定 */
object-fit: cover;
object-position: center;
border-radius: 4px;
transition: transform 0.3s ease;
}
.thumb-grid__item a:hover .thumb-grid__img {
transform: scale(1.03); /* ホバーで軽くズーム */
}
@media (max-width: 640px) {
.thumb-grid {
grid-template-columns: repeat(2, 1fr);
gap: 8px;
}
}<section class="hero">
<img
src="hero.jpg"
alt="ブランドメインビジュアル"
class="hero__img"
fetchpriority="high"
decoding="async"
>
<div class="hero__text">
<h1>あなたの暮らしを、もっと豊かに。</h1>
<a href="#contact" class="hero__cta">お問い合わせ</a>
</div>
</section>.hero {
position: relative;
width: 100%;
overflow: hidden;
}
.hero__img {
display: block;
width: 100%;
height: 600px;
object-fit: cover;
object-position: center 30%; /* 空が多い写真なら下寄りに調整 */
}
.hero__text {
position: absolute;
inset: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #fff;
background: rgba(0, 0, 0, 0.35); /* テキストの可読性を確保 */
text-align: center;
padding: 24px;
}
.hero__cta {
display: inline-block;
margin-top: 24px;
padding: 14px 40px;
background: #d16176;
color: #fff;
text-decoration: none;
border-radius: 4px;
font-weight: bold;
}
@media (max-width: 640px) {
.hero__img {
height: 340px;
object-position: center center;
}
}<div class="staff-card">
<img
src="staff01.jpg"
alt="山田 太郎"
class="staff-card__avatar"
loading="lazy"
>
<p class="staff-card__name">山田 太郎</p>
<p class="staff-card__role">フロントエンドエンジニア</p>
</div>.staff-card {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
.staff-card__avatar {
width: 120px;
height: 120px;
border-radius: 50%; /* 丸くする */
object-fit: cover;
object-position: center top; /* 顔が上にある写真に対応 */
border: 3px solid #EFBDB7;
}
.staff-card__name {
font-weight: bold;
margin: 0;
}
.staff-card__role {
color: #666;
font-size: 0.875rem;
margin: 0;
}border-radius: 50%を使えば、正方形の枠をそのまま円形にできる。object-fit: coverと組み合わせることで、縦横比がバラバラな写真でも常に顔が中央に表示されるアバターが完成する。
PCでは横長(16:9)、スマートフォンでは正方形(1:1)など、デバイスによって最適なアスペクト比が異なることがある。メディアクエリとaspect-ratioを組み合わせることで柔軟に対応できる。
.featured-img {
width: 100%;
object-fit: cover;
object-position: center;
display: block;
}
/* PC:横長 */
@media (min-width: 641px) {
.featured-img {
aspect-ratio: 16 / 9;
}
}
/* スマートフォン:正方形に近い比率 */
@media (max-width: 640px) {
.featured-img {
aspect-ratio: 4 / 3;
}
}複数箇所で比率を使い回す場合、CSSカスタムプロパティで一元管理すると保守性が上がる。
:root {
--ratio-hero: 16 / 9;
--ratio-card: 3 / 2;
--ratio-square: 1 / 1;
}
.hero__img {
width: 100%;
aspect-ratio: var(--ratio-hero);
object-fit: cover;
}
.card__img {
width: 100%;
aspect-ratio: var(--ratio-card);
object-fit: cover;
}
@media (max-width: 640px) {
:root {
--ratio-hero: 4 / 3; /* モバイルでは比率を変更 */
}
}<img
class="responsive-img"
src="image-800.jpg"
srcset="image-400.jpg 400w, image-800.jpg 800w, image-1600.jpg 1600w"
sizes="(max-width: 640px) 100vw, 50vw"
alt="レスポンシブ画像の例"
loading="lazy"
>.responsive-img {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
display: block;
}srcsetでブラウザが最適な解像度の画像を選び、object-fitで比率・トリミングを制御する。この組み合わせがパフォーマンスと見た目を両立させる現代的なベストプラクティスだ。
object-fitが機能するには、widthとheightの両方が指定されている必要がある。片方だけだと画像は通常の自動リサイズになり、object-fitは無効になる。aspect-ratioを使う場合はwidthとaspect-ratioの組み合わせでheightが自動計算されるため問題ない。
/* NG:widthしかない → object-fitが機能しない */
img {
width: 300px;
object-fit: cover; /* 効かない */
}
/* OK:widthとheight両方を指定 */
img {
width: 300px;
height: 200px;
object-fit: cover; /* 正常に動く */
}
/* OK:widthとaspect-ratioの組み合わせ */
img {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover; /* 正常に動く */
}imgはデフォルトでinline要素。インライン要素はベースライン揃えになるため、下に数pxの余白が生まれることがある。特にimgを囲むdivやliの底に謎の空白が出た場合はこれが原因だ。display: blockを追加するだけで解消する。
img {
display: block; /* inline要素のベースライン余白を解消 */
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
}繰り返しになるがobject-fitは置換要素(img, video等)にしか効かない。divやspanに指定しても何も起きない。div背景の場合はbackground-size: coverを使う。
object-positionは「X(水平) Y(垂直)」の順。background-positionと同じ順序なので混乱しにくいが、「上にある顔を見せたい」のにobject-position: topだけ書いて効かないケースがある。1値指定のとき、もう一方の値はcenterになる。意図した結果が出ない場合は2値で明示的に書くこと。
/* 1値指定のとき:もう一方はcenter */
object-position: top; /* = top center */
object-position: left; /* = left center */
/* 意図を明確にするなら2値で書く */
object-position: center top; /* 水平中央、垂直上寄り */SEOとアクセシビリティの観点で大きく異なる。imgタグはalt属性を持てるため、スクリーンリーダーや検索エンジンに画像の内容を伝えられる。background-imageはCSSで装飾的に使うものと見なされ、alt情報を持てない。また、loading=”lazy”・fetchpriority・srcsetなどのパフォーマンス最適化属性もimgだけが使える。コンテンツとして意味のある画像は必ずimgタグ+object-fitを選ぶべきだ。
aspect-ratioはChrome 88・Firefox 89・Safari 15から対応。2026年時点で対応率は98%以上あり、ほとんどの案件では問題ない。どうしても旧Safari 14以下などをサポートしなければならない場合は、padding-top: 56.25%(= 9/16 × 100%)を親のdivに当て、その中にimgをposition: absoluteで配置する旧来の方法をフォールバックとして使う。@supportsで分岐することもできる。
/* フォールバック(aspect-ratio非対応ブラウザ用) */
.img-wrapper {
position: relative;
width: 100%;
padding-top: 56.25%; /* 16:9 */
}
.img-wrapper img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
/* aspect-ratio対応ブラウザではフォールバックを上書き */
@supports (aspect-ratio: 16/9) {
.img-wrapper {
padding-top: 0;
aspect-ratio: 16 / 9;
}
.img-wrapper img {
position: static;
}
}object-fit: containで出る余白部分はimg要素自身のbackgroundが表示される。imgにbackground-colorを指定するだけで変えられる。白い余白にしたいならbackground-color: #fff、透過にしたいなら背景を指定しない(デフォルトは透明)。PNG画像で透過が含まれる場合も同様に制御できる。
.product-img {
width: 240px;
height: 240px;
object-fit: contain;
background-color: #f8f8f8; /* 余白部分の色 */
padding: 12px; /* 余白をさらに広げたい場合 */
box-sizing: border-box;
}使える。Next.jsのImageコンポーネントはstyle属性またはclassNameでobject-fitを渡せる。fill propを使う場合は親要素をposition: relativeにし、imgにposition: absoluteが自動で当たる設計になっているため、そのままobject-fit: coverを追加するだけでよい。Nuxt/imageも同様にclass属性でCSSを当てられる。フレームワーク固有の最適化(遅延読み込み・自動WebP変換)を活かしつつ、トリミングの制御はCSSに委ねる形になる。
できる。object-positionはtransitionとanimationの対象にできるため、ホバーやスクロールにあわせて表示位置をスライドさせる表現が可能だ。ただしGPUコンポジットレイヤーには乗らない(transformのように高速ではない)ため、多数の要素に同時にアニメーションさせるとフレームレートが落ちる可能性がある。必要に応じてwill-change: object-positionを検討するが、基本的には慎重に使うこと。
.img-animate {
width: 300px;
height: 200px;
object-fit: cover;
object-position: center 30%;
transition: object-position 0.5s ease;
}
.img-animate:hover {
object-position: center 70%; /* ホバーで表示位置が下にスライド */
}object-fitは「画像の見た目をCSSで完全にコントロールするための核心プロパティ」だ。使いこなせれば、どんなサイズの画像が入ってきてもレイアウトが崩れないコードが書けるようになる。aspect-ratio・object-position・srcsetと組み合わせることで、見た目・パフォーマンス・アクセシビリティをすべて両立できる。
あわせて読みたい:CSS aspect-ratioの使い方|アスペクト比を保つ方法

副業・フリーランスが主流になっている今こそ、自らのスキルで稼げる人材を目指してみませんか?
未経験でも心配することはありません。初級コースを受講される方の大多数はプログラミング未経験です。まずは無料カウンセリングで、悩みや不安をお聞かせください!
WithCodeでWeb制作を習得後、フリーランスエンジニアとして活動。HTML/CSS・JavaScript・WordPress案件を中心に年間20件以上の制作実績を持つ。「難しい技術をわかりやすく」をモットーに、初心者〜中級者向けの技術記事を執筆。副業・フリーランス独立を目指す方に向けた情報発信に注力している。
公式サイト より
今すぐ
無料カウンセリング
を予約!