背景画像がスマホで見切れるのは、書き間違いではありません。background-size: cover は「箱を隙間なく埋め、はみ出した分を切り落とす」仕様で、PCの横長の箱とスマホの縦長の箱では切られる場所が変わります。直し方は「切れないようにする」ではなく、「どこを残すかをCSSで指定する」です。
鉄則は次の6行です。高さは min-height で持たせ、cover で埋め、background-position で残す場所を決めます。
.hero {
min-height: 480px;
background-color: #1e293b;
background-image: url("img/hero.jpg");
background-repeat: no-repeat;
background-position: center;
background-size: cover;
}
これで直らないときは、症状ごとに原因が違います。次の5つの症状と、背景画像にすべきかどうかの判断を、最小構成のコードで逆引きできます。コードは編集部が検証用ページを作り、375px・768px・1280pxの幅で確認しています(仕様と対応状況は2026年10月時点)。
cover は、画像の縦横比を保ったまま箱を完全に覆う最小サイズにし、余った部分を切り落とします(MDN: background-size)。箱の縦横比が画像と離れるほど、切られる量が増えます。
どのくらい切られるのかを、1600×900px(16:9)の画像を高さ480pxの箱に入れて測りました。
| 箱の幅(高さは480px) | 画像の描画サイズ | 切られる量 |
|---|---|---|
| 1280px(PC) | 1280×720px | 上下あわせて240px(高さの約33%) |
| 768px(タブレット) | 853×480px | 左右あわせて85px(横幅の約10%) |
| 375px(スマホ) | 853×480px | 左右あわせて478px(横幅の約56%) |
PCでは上下を3分の1失うだけの画像が、スマホでは横幅の半分以上を失います。
もう1つ、background-position の初期値は 0% 0%、つまり左上です(MDN: background-position)。位置を書き忘れると、右側と下側だけが切られます。主役を右から4分の1の位置に置いた検証用の画像は、375px幅で丸ごと画面の外に出ました。
自分の症状の行から進んでください。
残したい被写体の位置を、background-position のパーセントで指定します。
パーセント指定は「画像の◯%地点を、箱の◯%地点に重ねる」という意味です。主役が画像の右から4分の1にいるなら 75% と書けば、箱の幅がいくつでも主役の中心は箱の左から75%の位置に来ます。
.hero {
background-position: 75% center;
}
検証では、center のとき375px幅で主役の約4分の3が画面の外に出ました。75% center に変えると、3つの幅すべてで主役が収まりました。
当校のコード添削でも、PCの見た目だけで確認を終え、スマホで主役が切れたまま提出されるヒーロー画像(ページ最上部の大きな画像)は珍しくありません。
この方法で守れるのは、主役が1か所にまとまっている画像までです。見せたいものが両端にある写真は、スマホではどちらかが切れます。その場合は症状4の方法で画像を差し替えます。
文字を焼き込んだバナーを背景画像にするのも避けてください。文字は端が1文字欠けただけで読めなくなります。
余白や繰り返しは contain の仕様です。画像の全体を見せたいなら、箱の縦横比を画像に合わせます。
contain は、画像を切らずに箱へ収まる最大サイズにします。箱と比率が違えば余白ができ、no-repeat が無ければそこに同じ画像が並びます。375px幅・高さ480pxの箱で試すと、画像は375×211pxになり、残りの269pxに同じ画像が繰り返されました。
端が切れても困らない雰囲気写真は cover、ロゴや図のように欠けたら意味が変わる画像は contain が向いています。全体を見せて余白も出したくないときは、次のように書きます。
.banner {
aspect-ratio: 16 / 9;
background-image: url("img/banner.jpg");
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}
aspect-ratio に画像と同じ比率を書くと、箱が画像と同じ形のまま伸び縮みします。検証した3つの幅すべてで、切れも余白もゼロでした。
解説でよく見る padding-top: 56.25% は、aspect-ratio が使えなかった時代の代替手段です。2021年9月以降はすべての主要ブラウザで使えるので(MDN: aspect-ratio)、新しく書くコードで使う理由はありません。
背景画像は箱の高さを作りません。高さは min-height か aspect-ratio で持たせ、height では固定しないのが原則です。
中身が空で高さの指定もない div は高さ0pxになり、画像は表示されません。「背景画像が出ない」ときに最初に疑う場所です。
height で固定すると、スマホでは文字が折り返して行数が増え、箱からはみ出します。height: 120px の箱に文章を入れた検証では、375px幅で文字が81pxはみ出しました。min-height: 120px に変えると、箱が201pxまで伸びて収まりました。
aspect-ratio で作った箱も、中身が増えれば伸びます。16:9の箱は375px幅なら高さ211pxのはずが、長い文章を入れると609pxになりました。箱が縦長になれば、画像はまた左右が切れます。
100vh だけでは、スマホでアドレスバーの分だけ下にはみ出します(web.dev: The large, small, and dynamic viewport units)。
.hero {
min-height: 100vh;
min-height: 100svh;
}
svh は、ブラウザのツールバーが出ている状態の「小さいビューポート」を基準にした単位です。1行目は未対応ブラウザ向けの保険です(Can I useによると、対応はChrome 108、Safari 15.4、Firefox 101以降)。dvh はスクロール中に高さが変わるので、ヒーロー画像には svh が無難です。
横長の写真を縦長の箱に入れる限り、位置の調整には限界があります。スマホ用に縦長でトリミングした画像を用意し、メディアクエリで切り替えます。
.hero {
background-image: url("img/hero-pc.jpg");
background-position: 75% center;
}
@media (max-width: 767px) {
.hero {
background-image: url("img/hero-sp.jpg");
background-position: center;
}
}
2枚書いても、読み込まれるのは条件に合った1枚だけです。検証でも、375px幅ではスマホ用だけ、1280px幅ではPC用だけがリクエストされました。幅に合う画像がリクエストされる様子は、web.devでも確認できます(web.dev: Optimize CSS background images with media queries)。
混同しやすいのが image-set() です。これは画面幅ではなく、解像度や画像形式に応じてブラウザに1枚を選ばせる関数で、2023年9月以降はすべての主要ブラウザで使えます(MDN: image-set())。
.hero {
background-image: url("img/hero.jpg");
background-image: image-set(
url("img/hero.avif") type("image/avif"),
url("img/hero.jpg") type("image/jpeg")
);
}
ブラウザは上から順に見て、対応している最初の形式だけを読み込みます(Chrome 154で確認)。絵柄を変えるのはメディアクエリ、同じ絵柄を軽い形式で配るのは image-set() です。
iOSのSafariでは、2026年10月時点でも background-attachment: fixed が効きません。固定したいなら、position: fixed の疑似要素で作り直します。
Can I useは、iOS Safariを掲載中の最新版27.2まで「fixedは認識されるが効果がない」部分対応としています(Can I use: background-attachment)。WebKitに2024年6月に登録された不具合報告には、WebKitの開発者が「By design(意図した挙動)」とコメントしており、修正はされていません(WebKit Bug 275247)。
body::before {
content: "";
position: fixed;
inset: 0;
z-index: -1;
background: url("img/bg.jpg") center / cover no-repeat;
}
デスクトップのChromeでは、900pxスクロールしても背景は固定されたままでした。WebKitの不具合報告にも、固定の疑似要素なら問題なく動くという報告があります。ただし編集部ではiPhoneの実機確認まではしていません。納品するサイトでは実機で確かめてください。
弱点は、このコードで固定できるのがページ全体の背景だけという点です。セクションごとに背景が切り替わる演出には使えません。html と body の両方に背景色があると、疑似要素は body の背景の下に隠れます。スマホでは固定をやめる、という割り切りも選択肢です。
装飾は背景画像、商品・人物・図のように内容を伝える画像は <img> で置きます。ファーストビューの大きな写真は、表示速度の面でも <img> が有利です。
| 観点 | 背景画像 | img要素+object-fit |
|---|---|---|
| 代替テキスト | 持てない。読み上げソフトに画像の存在が伝わらない | altで内容を伝えられる |
| 読み込み開始 | CSSを取得して解釈するまで、ブラウザが画像に気づけない | HTMLを読んだ時点で始まる |
| 遅延読み込み | loading="lazy"は使えない | loading="lazy"が使える |
| 向いている用途 | 模様、質感、雰囲気づくり | 商品、人物、図解、ヒーロー画像 |
出典はMDN: background-image(代替テキスト)とweb.dev: Browser-level image lazy loading(遅延読み込み)です。
画面内で一番大きな画像やテキストが表示されるまでの時間をLCPと呼び、2.5秒以内が「良好」の基準です(web.dev: Largest Contentful Paint)。ヒーロー画像を背景画像にすると、CSSを読み終えるまでの待ち時間がLCPに上乗せされます(web.dev: Optimize Largest Contentful Paint)。
<img> で同じ見た目を作るコードです。
<section class="hero">
<picture>
<source media="(max-width: 767px)" srcset="img/hero-sp.jpg">
<img class="hero__img" src="img/hero-pc.jpg"
alt="窓際の席でノートパソコンを開く女性"
width="1600" height="900" fetchpriority="high">
</picture>
<div class="hero__body">
<h1>見出しテキスト</h1>
</div>
</section>
.hero {
position: relative;
display: grid;
align-content: center;
min-height: 480px;
}
.hero__img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
object-position: 75% center;
}
.hero__body {
position: relative;
padding: 24px;
}
@media (max-width: 767px) {
.hero__img {
object-position: center;
}
}
object-fit と object-position の書き方は、背景画像の cover や位置指定と同じです。このコードで、375px幅ではスマホ用、768px以上ではPC用の画像に切り替わり、3つの幅とも箱が埋まりました。
ファーストビューの画像に loading="lazy" は付けません。web.devも、LCPになる画像を遅延読み込みしないよう求めています。
背景画像のままにする場合は、head に次の行を足して、画像の存在を先にブラウザへ知らせます(web.devが挙げている改善策)。スマホとPCで画像を切り替えているなら、media 属性にCSSと同じ条件を書きます(MDN: rel="preload")。
<link rel="preload" as="image" href="img/hero-sp.jpg"
media="(max-width: 767px)" fetchpriority="high">
<link rel="preload" as="image" href="img/hero-pc.jpg"
media="(min-width: 768px)" fetchpriority="high">
表示速度を制作物でどう見せるかは、ポートフォリオの作り替え5ステップのステップ4に書いています。画像の形式選びと軽量化は、独学ロードマップのステップ4「実務品質」の卒業判定にも入れています。
375px・768px・1280pxの3点だけで確認を終えると、その間の幅で切れている箇所を見落とします。ブラウザの幅を連続して動かしながら見てください。
トリミングの基準は、実装する人が一人で決めないようにしています。どこを残すかはデザインの意図だからです。デザインカンプ(完成見本)に無い幅で主役が切れそうなら、その幅のスクリーンショットを添えて、デザイナーや発注者に先に確認します。
AddedPallasのカリキュラムでも、STEP3からはピクセルパーフェクトと保守性のあるコードを学ぶ段階に入ります。当校のサポートにはコード添削と質問回答があるので(サポート体制)、本人が気づきにくい切れ方を第三者に見てもらう場として使えます。
要素が横にはみ出すといった背景画像以外の崩れは、検証ツールでの特定手順と合わせて、CSSのレイアウトが崩れる原因の記事にまとめています。
押さえることは4つです。
cover は切って埋める仕様。background-position のパーセントで、主役のいる場所を残すaspect-ratio で箱の比率を合わせる。高さは height で固定せず、画面いっぱいなら 100svh を重ねる<img> と object-fit で置く背景画像の切れ方は、エラーも出ずページも動くので見逃しやすい箇所です。こうした「動くけれど商品としては通らない」部分の詰め方や学習の進め方は、無料カウンセリングでフリーランス経験のあるエンジニアに相談できます。
\相談だけでもOK!すべての疑問をプロが解決します!/
「自分にできるか不安」「まずは何をすればいいの?」
「副業でもできるの?」「転職もできるの?」