CSS 背景图怎么随窗口等比缩放:cover 与 contain 的取舍

编程狮(w3cschool.cn) 2026-10-22 07:06:35 浏览数 (26)
反馈

先给结论:cover 保证铺满容器但会裁掉图的一部分,contain 保证完整显示但会留出空白,两者都是等比缩放,区别只在牺牲哪一边。想做到"随窗口等比缩放、既不留白也不裁切",前提是你的图与容器的宽高比本来就该一致,否则这件事在数学上无解。

背景图随窗口等比缩放时 cover 与 contain 的差异

很多人一上来就想找一个"完美"的取值,试完 cover 嫌它切掉了主体,试完 contain 又嫌上下两条白边难看,最后写成 background-size: 100% 100%,图倒是铺满了,人也被拉扁了。问题的本质不是取值没选对,而是没想清楚这张图在布局里到底承担什么角色。

本文用一个全屏 hero 区的例子,把背景图缩放的五个取值讲清:先给可运行的最小结构,再逐个说明它们的实际行为与适用边界,最后给出两种真正能落地的工程做法。

先看结论

  • 要铺满、允许裁切:cover,配 background-position 控制保留哪一块。
  • 要完整、允许留白:contain,适合 Logo、示意图这类不能缺边的图。
  • 要严格等比、不留白不裁切:让容器与图同宽高比,再用 100% 或 cover。

属性细节记不清时,翻 CSS 教程 里 background 相关章节最快。

一、最小场景与预期行为

任务定死:一张 1920×1080 的横图作为页面顶部的 hero 背景图,容器宽度跟随视口,高度固定为视口高度的 60%。要求这张背景图在 375 像素宽的手机和 2560 像素宽的显示器上都不变形、不出现明显空白。

<header class="hero">
  <h1>标题文字</h1>
</header>

.hero {
  height: 60vh;
  background-image: url("hero.jpg");
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
}

这段做的是把图铺满整个 hero 区,并居中定位。cover 会把图等比放大到"宽高都能盖住容器"为止,多出来的部分被容器裁掉。

预期结果(未在本机执行):窄屏上图的左右被裁掉较多,宽屏上上下被裁掉较多,但任何宽度下都不变形、不留白。这就是 cover 的取舍。

二、background-size 五个取值的实际行为

background-size 五个取值在同样容器里的表现

背景图的 background-size 取值可以分成五类,行为各不相同:

取值 是否等比 是否铺满 是否会留白
auto 是 否 会
一个长度或百分比 是 否 会
两个值(宽 高) 否 是 否
cover 是 是 否
contain 是 否 会

关键点有两个:

  1. 只写一个值时,另一个维度按原始宽高比推算,所以是等比的。写两个值(包括 100% 100%)时两个维度各自独立计算,图一定会被拉变形。
  2. cover 与 contain 都是"取较大的那个缩放比例"和"取较小的那个"。cover 取较大值,于是短边刚好盖住、长边溢出;contain 取较小值,于是长边刚好放下、短边留白。

background-position 决定裁切时保留哪一块。默认值是左上,人物居中的图常常被切掉头部,写成 center center 或 center 30% 会好很多。

三、两种能落地的工程做法

3.1 做法一:cover 配安全区

适合照片、氛围图这类"切一点无所谓"的背景。做法是接受裁切,但用安全区保证关键内容不被切到。

.hero {
  height: 60vh;
  background-image: url("hero.jpg");
  background-size: cover;
  background-position: center 40%;
  padding: 96px clamp(16px, 6vw, 120px);
}

这段做的是:把定位焦点上移到 40% 处,让人物头部更可能落在可视区内;内边距用 clamp 做出随视口变化的安全区,文字不会贴边。

适用边界:窄屏(竖屏手机)下横图会被裁得非常厉害,只剩中间一小条。真要兼顾,就得准备一张竖版图,用媒体查询换掉:

@media (max-width: 600px) {
  .hero {
    background-image: url("hero-mobile.jpg");
  }
}

这段做的是在窄屏下换用竖版素材。性能上浏览器只会下载命中的那一张,不会两张都下。

3.2 做法二:等比容器配 100%

适合必须完整显示、又不能留白的结构图与示意图。做法是让容器自己保持与图一致的宽高比。

.ratio-box {
  aspect-ratio: 16 / 9;
  background-image: url("diagram.png");
  background-size: 100% 100%;
  background-repeat: no-repeat;
}

这段做的是用 aspect-ratio 把容器锁成 16:9,与素材同比例。此时写 100% 100% 不会变形——因为容器的比例和图的比例相同,两个方向算出来的缩放系数一致。

它的代价是容器高度由宽度决定,内容区高度不可控。想在里面放文字,需要用绝对定位另起一层。

四、常见失败分支与验证清单

4.1 图被拉变形

写了 100% 100% 而容器比例与图不一致。修复办法是改回 cover 或 contain,或者给容器加 aspect-ratio 锁死比例。

4.2 窄屏上主体被切没了

cover 在极端比例下必然发生。修复办法是调整 background-position,或者按断点换素材。

4.3 contain 留下的白边破坏了设计

背景图用 contain 之后露出容器底色,往往是因为背景色没设对。修复办法是给容器设一个与图边缘接近的 background-color,让留白看起来像设计的一部分。

4.4 验证清单

  • 检查:在开发者工具里改视口宽度,观察图的宽高比是否恒定
  • 运行:从 320 像素拖到 2560 像素,每 200 像素停一次
  • 预期:图始终等比,比例一致时无留白,比例不一致时按所选策略裁切或留白
  • 失败:出现拉伸 → 用了两个值的 background-size 且容器比例不匹配
  • 修复:改 cover 或 contain;必须铺满时给容器加 aspect-ratio
  • 验证:用取色工具比对原图与页面上的像素,确认没有非等比缩放

上面这些步骤做的是确认等比、跑通断点、比对裁切范围。预期结果(未在本机执行)是拖动过程中比例恒定;若某一段突然变形,多半是容器高度被内容撑开导致比例变化。

背景图缩放取值怎么选的决策路径

总结

背景图要不要随窗口等比缩放,先回答"留白和裁切你更不接受哪个"。不接受留白用 cover 并配好裁切焦点,不接受裁切用 contain 并配好背景色,两者都不能接受就把容器比例锁成与图一致。

三条要点带走:

  • cover 与 contain 都是等比的,区别只在取较大还是较小的缩放系数;
  • 只写一个值时另一维按原比例推算,写两个值就会变形;
  • background-position 决定 cover 保留哪一块,默认左上最容易切掉主体。

下一步建议把站点里的全屏背景集中收口到一两个工具类,取值与断点写在一处,避免每张图各写一套。属性细节拿不准时,查 CSS 参考手册 里 background-size 的取值说明。

常见问题

Q:为什么 cover 之后图的一部分看不见了?

A:cover 会把图放大到两个方向都能盖住容器,多出来的部分被裁掉。用 background-position 调整保留区域,比如 center 40% 保留偏上的部分。

Q:怎么做到既铺满又不变形?

A:只有当图的宽高比与容器一致时才能同时满足。给容器加 aspect-ratio 锁成与图相同的比例,再写 100% 100%,此时两个方向缩放系数相同,不会变形。

Q:contain 留下的白边怎么处理?

A:给容器设一个与背景图边缘颜色接近的 background-color,让留白融入设计。图本身带纯色背景时效果最好。

Q:手机上看横图只剩中间一条怎么办?

A:横图在竖屏容器里用 cover 必然被裁得很厉害。用媒体查询在窄屏换一张竖版素材,或者改用 contain 加背景色。

Q:background-size 写百分比是相对谁的?

A:相对背景定位区域(默认是 padding-box)的尺寸,不是相对图本身。写 50% 表示图宽为容器宽的一半。

延伸学习

想把背景图的缩放取值练熟,可以按这个顺序来:

  1. 读一篇相关笔记 CSS background-size,把缩放与平铺的示例看清;
  2. 想系统补一遍基础,CSS 入门课程 可以跟一遍;
  3. 想快速试数值,用 CSS代码生成器 生成后对照改。

0 人点赞