图片尺寸与响应式图片
在网页中使用图片时,控制尺寸和适应不同屏幕是两个核心问题。本节将介绍如何通过 HTML 属性和 CSS 控制图片尺寸,以及如何实现响应式图片策略来适配各种设备和屏幕分辨率。
前置知识
阅读本节前,建议先了解:src 与 alt 属性
基础概念
图片尺寸控制涉及两个层面:HTML 属性(width/height)和 CSS 样式。HTML 属性用于告诉浏览器图片的原始尺寸,帮助浏览器在图片下载前预留空间,防止累积布局偏移(CLS)。CSS 则控制图片在页面中的实际显示尺寸。
响应式图片是指根据用户设备的屏幕宽度、分辨率等因素,自动加载最合适的图片版本。这不仅提升了用户体验,还减少了不必要的带宽消耗。
语法
width 和 height 属性
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>图片尺寸属性</title>
</head>
<body>
<h1>width 与 height 属性</h1>
<!-- 只设置 width,高度按比例缩放 -->
<img src="photo.jpg" alt="风景照片" width="300">
<br>
<!-- 同时设置 width 和 height -->
<img src="photo.jpg" alt="风景照片" width="300" height="200">
<br>
<!-- 错误:width 和 height 比例与原图不一致,图片变形 -->
<!-- <img src="photo.jpg" alt="风景照片" width="300" height="100"> -->
<!-- 原始尺寸(不推荐:可能导致布局偏移) -->
<img src="photo.jpg" alt="风景照片">
</body>
</html>CSS 控制图片尺寸
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>CSS 控制图片尺寸</title>
<style>
/* 固定宽高 */
.fixed-size {
width: 400px;
height: 300px;
object-fit: cover; /* 裁剪填满 */
}
/* 自适应宽度 */
.responsive {
width: 100%;
height: auto; /* 保持比例 */
max-width: 600px;
}
/* 限制最大尺寸 */
.max-size {
max-width: 100%;
max-height: 400px;
}
/* CSS 宽高与 HTML 属性宽高的区别 */
.css-sized {
width: 200px;
/* CSS width 覆盖 HTML width 属性 */
}
</style>
</head>
<body>
<h1>CSS 控制图片尺寸</h1>
<!-- CSS 固定尺寸 + object-fit -->
<img class="fixed-size" src="photo.jpg" alt="风景" width="800" height="600">
<!-- CSS 响应式宽度 -->
<img class="responsive" src="photo.jpg" alt="风景" width="800" height="600">
<!-- CSS 限制最大尺寸 -->
<img class="max-size" src="photo.jpg" alt="风景" width="1920" height="1080">
</body>
</html>详细说明
HTML 属性 vs CSS 控制
HTML 的 width/height 属性和 CSS 的 width/height 有不同的用途:
| 对比项 | HTML width/height | CSS width/height |
|---|---|---|
| 单位 | 像素(无单位数值) | 像素、百分比、em 等 |
| 作用 | 预留布局空间 | 控制实际显示尺寸 |
| 优先级 | 被 CSS 覆盖 | 优先级更高 |
| 目的 | 防止 CLS | 视觉呈现 |
| 是否必须 | 建议设置 | 按需设置 |
为什么设置 width/height 属性很重要
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>CLS 演示</title>
</head>
<body>
<h1>设置 width/height 防止布局偏移</h1>
<!-- 推荐:设置了 width 和 height -->
<!-- 浏览器在图片下载前就能预留正确空间 -->
<p>文章标题</p>
<img src="hero.jpg" alt="文章配图" width="800" height="450">
<p>文章正文内容...</p>
<hr>
<!-- 不推荐:未设置 width 和 height -->
<!-- 图片下载前不占空间,下载后页面布局突然跳动 -->
<!-- <p>文章标题</p> -->
<!-- <img src="hero.jpg" alt="文章配图"> -->
<!-- <p>文章正文内容...</p> -->
</body>
</html>CLS 累积布局偏移
当页面元素在加载过程中发生位置变化,会导致 CLS(Cumulative Layout Shift)。不设置图片尺寸是 CLS 的常见原因之一。Google 将 CLS 作为 Core Web Vitals 指标,影响搜索排名。
CSS object-fit 属性
object-fit 控制图片在指定容器中的填充方式:
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>object-fit 属性</title>
<style>
.box {
width: 300px;
height: 200px;
border: 2px solid #333;
margin-bottom: 10px;
overflow: hidden;
}
.box img {
width: 100%;
height: 100%;
}
.fill img { object-fit: fill; }
.contain img { object-fit: contain; }
.cover img { object-fit: cover; }
.none img { object-fit: none; }
.scale-down img { object-fit: scale-down; }
</style>
</head>
<body>
<h1>object-fit 对比</h1>
<!-- fill(默认):拉伸填满,可能变形 -->
<div class="box fill">
<img src="photo.jpg" alt="fill 模式" width="800" height="600">
</div>
<p>fill:拉伸图片填满容器,可能导致变形</p>
<!-- contain:保持比例,完整显示 -->
<div class="box contain">
<img src="photo.jpg" alt="contain 模式" width="800" height="600">
</div>
<p>contain:保持比例,完整显示图片,可能留白</p>
<!-- cover:保持比例,填满容器(可能裁剪) -->
<div class="box cover">
<img src="photo.jpg" alt="cover 模式" width="800" height="600">
</div>
<p>cover:保持比例,填满容器,超出部分被裁剪</p>
<!-- none:原始尺寸,可能溢出 -->
<div class="box none">
<img src="photo.jpg" alt="none 模式" width="800" height="600">
</div>
<p>none:保持原始尺寸,不缩放</p>
<!-- scale-down:取 none 和 contain 中较小的 -->
<div class="box scale-down">
<img src="photo.jpg" alt="scale-down 模式" width="800" height="600">
</div>
<p>scale-down:选择 contain 或 none 中较小的结果</p>
</body>
</html>object-fit 值对比
| 值 | 行为 | 变形 | 裁剪 | 留白 |
|---|---|---|---|---|
fill | 拉伸填满 | 可能 | 不 | 不 |
contain | 保持比例,完整显示 | 不 | 不 | 可能 |
cover | 保持比例,填满容器 | 不 | 可能 | 不 |
none | 原始尺寸 | 不 | 可能 | 可能 |
scale-down | 取 none/contain 较小值 | 不 | 不 | 可能 |
object-position 属性
object-position 控制图片在容器中的对齐位置(配合 object-fit: cover 或 contain 使用):
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>object-position</title>
<style>
.crop-box {
width: 300px;
height: 200px;
border: 2px solid #333;
overflow: hidden;
margin: 10px 0;
}
.crop-box img {
width: 100%;
height: 100%;
object-fit: cover;
}
.center { object-position: center; } /* 默认 */
.top { object-position: top; }
.bottom { object-position: bottom; }
.left { object-position: left; }
.right { object-position: right; }
.custom { object-position: 30% 70%; } /* 自定义位置 */
</style>
</head>
<body>
<h1>object-position 对比</h1>
<div class="crop-box"><img class="center" src="portrait.jpg" alt="居中" width="400" height="600"></div>
<p>center(默认):居中显示</p>
<div class="crop-box"><img class="top" src="portrait.jpg" alt="顶部" width="400" height="600"></div>
<p>top:对齐顶部,适合人像照片</p>
<div class="crop-box"><img class="custom" src="portrait.jpg" alt="自定义" width="400" height="600"></div>
<p>custom 30% 70%:自定义焦点位置</p>
</body>
</html>响应式图片策略
在不同设备上提供合适的图片尺寸,可以大幅优化性能:
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>响应式图片策略</title>
<style>
/* 策略 1:CSS max-width 100% */
.fluid-img {
width: 100%;
height: auto;
max-width: 800px;
display: block;
}
/* 策略 2:CSS 媒体查询切换背景图 */
.hero {
width: 100%;
height: 400px;
background-size: cover;
background-position: center;
}
@media (max-width: 768px) {
.hero {
height: 250px;
/* 小屏幕使用小图 */
background-image: url('images/hero-small.jpg');
}
}
@media (min-width: 769px) {
.hero {
/* 大屏幕使用大图 */
background-image: url('images/hero-large.jpg');
}
}
/* 策略 3:使用 srcset 和 sizes(推荐) */
/* 在 img 标签中直接配置,见下方 HTML */
</style>
</head>
<body>
<h1>响应式图片策略</h1>
<!-- 策略 1:CSS 流式图片 -->
<figure>
<img class="fluid-img"
src="photo-800.jpg"
alt="流式布局的风景照片"
width="800" height="533">
<figcaption>CSS max-width: 100% 让图片自适应容器宽度</figcaption>
</figure>
<!-- 策略 3:HTML 响应式属性 -->
<figure>
<img src="photo-default.jpg"
srcset="photo-320.jpg 320w,
photo-640.jpg 640w,
photo-1024.jpg 1024w,
photo-1600.jpg 1600w"
sizes="(max-width: 480px) 100vw,
(max-width: 768px) 80vw,
600px"
alt="使用 srcset 和 sizes 的响应式图片"
width="1600" height="1067"
class="fluid-img">
<figcaption>HTML srcset + sizes 根据屏幕宽度选择最佳图片</figcaption>
</figure>
<!-- 策略 2:CSS 媒体查询背景图 -->
<div class="hero" role="img" aria-label="城市天际线背景图"></div>
</body>
</html>响应式图片策略对比
| 策略 | 方法 | 优点 | 缺点 |
|---|---|---|---|
| CSS max-width | width: 100% | 简单直接 | 只缩放不换图,带宽浪费 |
| CSS 媒体查询 | background-image | 精确控制 | 无法用 img 标签,SEO 差 |
| HTML srcset/sizes | srcset + sizes | 语义化、SEO 友好 | 语法稍复杂 |
| HTML picture | <picture> 元素 | 最灵活 | 代码量较大 |
实战示例
响应式图片画廊
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>响应式画廊</title>
<style>
* {
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.gallery-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 20px;
}
.card {
border-radius: 12px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.card img {
width: 100%;
height: 220px;
object-fit: cover;
display: block;
}
.card-body {
padding: 16px;
}
.card-body h3 {
margin: 0 0 8px;
}
.card-body p {
margin: 0;
color: #666;
font-size: 14px;
}
</style>
</head>
<body>
<h1>摄影作品集</h1>
<p>点击图片查看大图,画廊自动适配不同屏幕尺寸。</p>
<div class="gallery-grid">
<div class="card">
<img src="photo1-600.jpg"
srcset="photo1-400.jpg 400w, photo1-600.jpg 600w, photo1-900.jpg 900w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 50vw, 33vw"
alt="黄昏时分湖泊的倒影,远处群山轮廓"
width="900" height="600"
loading="lazy">
<div class="card-body">
<h3>湖畔黄昏</h3>
<p>宁静的湖面映着夕阳的余晖</p>
</div>
</div>
<div class="card">
<img src="photo2-600.jpg"
srcset="photo2-400.jpg 400w, photo2-600.jpg 600w, photo2-900.jpg 900w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 50vw, 33vw"
alt="白雪覆盖的松树林,阳光从树缝中洒下"
width="900" height="600"
loading="lazy">
<div class="card-body">
<h3>雪中松林</h3>
<p>冬日暖阳穿过林间的光影</p>
</div>
</div>
<div class="card">
<img src="photo3-600.jpg"
srcset="photo3-400.jpg 400w, photo3-600.jpg 600w, photo3-900.jpg 900w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 50vw, 33vw"
alt="夜晚城市的天际线,万家灯火通明"
width="900" height="600"
loading="lazy">
<div class="card-body">
<h3>城市夜景</h3>
<p>繁华都市的璀璨灯火</p>
</div>
</div>
</div>
</body>
</html>注意事项
- HTML
width/height属性的单位是像素(无需写px),CSS 中必须写单位 - CSS 的
width/height会覆盖 HTML 属性中的同名属性 object-fit: cover可能会裁剪图片,需要配合object-position控制焦点- 不设置
width/height属性会导致 CLS,影响 Core Web Vitals 评分 width: 100%+height: auto是最简单的响应式方案,但不适用于需要精确控制的场景- CSS
background-image不支持alt文本,不利于无障碍和 SEO
最佳实践
- 始终设置 HTML 的
width和height属性(使用图片原始尺寸) - 使用 CSS
max-width: 100%+height: auto实现基本的响应式 - 裁剪区域使用
object-fit: cover+object-position控制焦点 - 对于多尺寸适配,优先使用 HTML 的
srcset/sizes或<picture>元素 - 头图/大图使用
loading="lazy"实现懒加载 - 生成多版本图片时,使用 1.5x 和 2x 密度版本覆盖高 DPI 屏幕
- 使用 CDN + WebP/AVIF 格式进一步优化加载性能
下一节
继续学习:srcset 与 sizes